Status Report
I wanted to give you an update since this blog post and let you know how well (or not) I'm following those plans.
Blue Portals: Anniversary Edition (Skip this if you don't care..)
Sunday I pushed a long over due push to Steam for beta testers to play and give feedback. I don't like to push to Steam often as my connection isn't that strong so any uploads bigger then a few megabytes causes an upload failure, I usually split updates into multiple pushes to prevent such problems but sometimes you have to push one large file that'll cause a error. This time I instead used my unlimited 4G mobile data and I had way better luck, and will be using this method from now on.
We right now only have a small handful of testers and I wish to keep it that way for a little while longer. It's interesting to see the same play-tester play the same map in different updates regardless if anything changed. There was one map where no reports or issues where given from this tester last update. I barely changed the room, and this time they informed me that something felt impossible to achieve.
I also keep play-testers out of developer news. This way I can introduce something brand new to them and they can report back if they understood it and/or liked the idea. I really wish I was in a position to watch people using Steam's broadcasting service, but I think even with my mobile data, it'd be unwatchable due to the high ping that wireless services have.
Although I wished the teaser trailer was done last month, I'm happy to report that it's being worked on now. I've got a message this morning that the recording is done. It just needs to be edited and such. Really cool as the mod has a look and feel that we're happy with. I guess it's better that the stuff got recorded today than a month ago as a month ago some models still had their ambient occlusion maps for skins!
Overall, the mod is coming together very nicely. There are a few things I'm worried about but I'm sure time will allow me to answer more questions I have. I'll keep you posted on this as I see it as a major stepping stone.
LEX2
A few hours ago, I pushed a near final build of it. In-short, I've cleaned up the code, deleted useless classes and changed how somethings operate.
For example, LEX2 has this function called AssetManager:PrecacheGlobal(path) which you call when you want something to be pre-loaded in memory so your game can load it later without a hitch. This was done by calling AssetManager:PrecacheGlobal(path) in App:Start() and what it did was load those paths into a list. Then when ever the world loaded a new map, PrecacheList was called which loaded every asset in that list. Although you only needed to define the asset once, it still needed to be loaded multiple times!
In this blog, Josh mentioned that it's possible to load assets into one world and have it just sit in memory while your game world is active. I decided to try this, but I was careful to prevent two worlds from being current at the same time.
First, I retired the old PrecacheList and made a new function.
void AssetManager::PrecacheJunkyard()
{
DevMsg("AssetManager: Creating Junkyard.");
// Save the current world if we have one.
World* oldworld = WORLD;
junkyard = World::Create();
World::SetCurrent(junkyard);
// Precache global objects.
std::list<std::string>::iterator it;
for (it = precache_list.begin(); it != precache_list.end(); ++it)
{
if (it->c_str() != S_NULL)
{
AssetManager::Precache(it->c_str());
}
}
// Go back to the 'real' world if there was one.
if (oldworld != NULL)
{
World::SetCurrent(oldworld);
}
else
{
World::SetCurrent(NULL);
}
}
This will load all the assets in the list that PreacheList used into a different world than the game. Then if there is ever the chance that a world exists when the junkyard world is created, it'll go back to it. To prevent that ever happening though, I made this function not exposed to Lua and have it called at the very end of App::Start() in C++.
bool App::Start()
{
//Create a window
windowmanager.CreateWindow(System::AppName);
// Create a context
contextmanager.CreateContext();
...
#ifdef LUA_GAME
// Finally, test the app script
if (ScriptApp::Start() == false)
{
#ifdef WIN32
MessageBox(NULL, "Error: Failed to execute App script!", "Critical Error!", MB_OK | MB_IConstop); //MB_ICONWARNING
#endif
return false;
}
#else
if (GAME::Start() == false)
{
return false;
}
#endif
...
// If the user preached anything in App:Start() or GAME::Start(), load them in another world.
// The Junkyard world will keep those entities in memory.
AssetManager::PrecacheJunkyard();
...
return true;
}
So then your Lua script will look like this
function App:Start() AssetManager:PrecacheGlobal("Models/Characters/hitbox.mdl") AssetManager:PrecacheGlobal("Models/Junk/cinderblock.mdl") return true end
But wait! What if you want the game to automatically launch a map? I didn't want a conflict where a world would exist, and then another world gets created to spawn assets. For safety measures, I just made a PostStart() function for Lua, and have it called after AssetManager::PrecacheJunkyard().
{
.....
// If the user preached anything in App:Start() or GAME::Start(), load them in another world.
// The Junkyard world will keep those entities in memory.
AssetManager::PrecacheJunkyard();
#ifdef LUA_GAME
ScriptApp::PostStart();
#else
GAME::PostStart();
#endif
return true;
}
-- This function will be called right after when the program starts. function App:PostStart() end
I really didn't test what would happen if I did load a map before AssetManager::PrecacheJunkyard(). I assume there would be a pause, as the worlds get swapped around, but I'm a bit too scared to try.. but also kind of curious...
I've also sorted the filesytem. Everything LEX2 is within Source/Core with one cpp file looking like this.
// $PROJECT_NAME_main.cpp.
#include "Core/base.h"
#ifndef LUA_GAME
namespace GAME
{
// This function will be called once when the program starts.
bool Start()
{
return true;
}
// This function will be called right after when the program starts.
void PostStart()
{
}
// This is our main program loop and will be called continuously until the program ends.
bool Loop()
{
return true;
}
// This function is called when the program is loading a map. (This is where you draw your loading screen!)
void OnMapLoad()
{
}
// This function is called when the program is called to pause.
void onpause()
{
}
// This function is called when the program is called to resume.
void onresume()
{
}
// This function is called when the program finished loading a map.
void OnPostMapLoad()
{
}
// This function is called when the program disconnected from a map.
void OnDisconnect()
{
}
// This function is called when the program closes.
void OnShutdown()
{
}
// C++ function only. This is how you link editor entities to your C++ classes
void LoadEntity(Entity* entity)
{
/*
// Attach loaded entites to puppeteers.
// This can get long and messy, there is some talk about this getting auto-generated with an offical actor class.
// Cross your figners for that day....
Puppeteer* puppeteer = NULL;
if (entity->GetKeyValue("puppeteer") == "Rocket")
{
puppeteer = new Rocket(entity);
}
else if (entity->GetKeyValue("puppeteer") =="Demon")
{
puppeteer = new Demon(entity);
}
else if (entity->GetKeyValue("puppeteer") =="Portal")
{
puppeteer = new Portal(entity);
}
*/
}
}
#endif // !LUA_GAME
As you can see, it's pretty much exactly like App.lua. If LUA_GAME isn't defined, it calls this code instead of the App.lua file. I did this to make making a game for C++ and Lua very similar. There is a function that gets called within the MapHook to link entities to the Puppeteer class which can be linked with one script.
Script.puppeteername="" --choiceedit "Puppeteer" "foo,boo" function Script:Start() -- Attach us to a C++ class like this! self.entity:SetKeyValue("puppeteer",puppeteername) end -- There needs to be a better way of flowgraphing with C++ classes!! function Script:User1()--in self.component:CallOutputs("User1") end function Script:User2()--in self.component:CallOutputs("User2") end function Script:User3()--in self.component:CallOutputs("User3") end function Script:User4()--in self.component:CallOutputs("User4") end
Summer Games Tournament
As I stated, I much want to participate in this one. I don't really have much time to make a unique piece, but I want something to stress test LEX2 and see if it can be used easily and effectively. I'm thinking about my take on the AI and Events map from the Advanced First-Person Shooter Template. That map kind of bothers me as the scaling is all wacky (It was made when the editor used Meters) and I feel that it's in the one person team field of difficulty.
Seems easy, where's the challenge? Well, While the end result will be a revision, I want to remodel most assets and code the entire game in C++ using LEX2's puppeteer system! I also will be coding things to my preferences so it's not like I'm just gonna convert existing Lua code to C++.
I had other ideas but this seems like the best one currently. It should be an interesting project, and I'll open-source it when I'm done. Anything I make will be available for others to use in the future. I wish to start tomorrow; or when I wake up as it's past midnight.
Steam Dev Days
I'm making arrangements to go to Steam Dev Days this year. I've bought my ticket and I just got a few things to iron out with traveling, hotel, and some company naming conflict. My overall goal is to talk to network with other people, talk about developing games, and learn new things. I'm really stoked about the entire thing.
That's all for now, wish me luck!
- 4
5 Comments
Recommended Comments