This is an old revision of the document!
“Update and Render functions? Where we're going we don't need hardcoded Update and Render functions”
First of all, a disclaimer: You don't really *HAVE* to use the Proton Entity System to use the framework. If you already have a system you like, or are porting existing code, you can safely ignore most of this section.
I've made a lot of engines and a lot of game frameworks and for some reason I'm constantly trying new methods, mostly because it keeps things fun and interesting.
Here are some past methods I've tried when creating games:
Using all of these, this is how it went:
(Ladies, look at your game programming development cycle)
(Now look at mine)
What if we could trade some initial complexity in the beginning for a more sane experience over all?
Aka, “my interpretation of how Unity internals sort of work after I used it for a few hours”.
If you take a look at Entity.h you'll see some functions but nothing about thinking/updating or drawing. So what can an entity do?
Well, not much, alone. It's fairly lightweight at about 200 bytes.
Instantiate an entity
Ok, time to just cannon-ball into the pool and show you what this stuff can do. The important thing to realize is we're just using entities and components to do everything.
If you say a weird function, like, BobEntity(), realize that it's just a helper function from EntityUtils.cpp and is components to manipulate things to make any entity “bob”. These helpers are not that complicated and just save on repetitive code, so dig in and look at them.
My philosophy is if it's a simple one line of code to add a fade, zoom, or bob to a visual, you are that much more likely to do it.
If you'd like to work along with me, open the RTSimpleApp project now!
//Open App.cpp. Find MainMenuCreate(pGUIEnt) in App::Update(), comment it out and add two lines so you have this: //MainMenuCreate(pGUIEnt); AddFocusIfNeeded(pGUIEnt); //so it will render, update, and draw. Really it just adds a few components. Entity *pEnt = CreateOverlayEntity(pGUIEnt, "logo", "interface/proton.rttex", 0,0);
Instead of the menu as before, you should see the proton logo rendered. (I've set my screen output to iPhone size in main.cpp btw)
Well, we see the logo there. If you looked inside of CreateOverlayEntity, you'd see it creates an Entity, and adds a RenderOverlay component to it and sets some properties. (All of which are storied in either entity's VariantDB (like pos2d, color, scale2d, etc) or the components VariantDB if it is specific to the component. (properties like fileName, and framex, framey)
Add a few more lines of code:
//MainMenuCreate(pGUIEnt); AddFocusIfNeeded(pGUIEnt); //so it will render, update, and draw. Really it just adds a few components. Entity *pEnt = CreateOverlayEntity(pGUIEnt, "logo", "interface/proton.rttex", 0,0); //Instead of drawing at 0,0, let's set the pos2d variable to 100,100 so it draws there instead. pEnt->GetVar("pos2d")->Set(CL_Vec2f(100,100)); //let's move to 200,200 1000ms (one second) later. GetMessageManager()->SetEntityVariable(pEnt, 1000, "pos2d", CL_Vec2f(200,200)); //and, move back to 0,0 a second after that. GetMessageManager()->SetEntityVariable(pEnt, 2000, "pos2d", CL_Vec2f(0,0));
So now the ball sort of jerks around the screen. Any variable can be “scheduled” to be set in this way. If the entity is destroyed, any pending messages are also destroyed.
Instead of jerkily moving, we can use an InterpolateComponent to smoothly change one variant value to another. This works numbers, vectors, colors, etc. I don't think it works for strings though, although that does seem possible.
Instead of adding InterpolateComponent directly, we'll use some helper functions that apply it to pos2d, but just keep in mind we can do this for any variable.
Replace with this code:
//MainMenuCreate(pGUIEnt); AddFocusIfNeeded(pGUIEnt); //so it will render, update, and draw. Really it just adds a few components. Entity *pEnt = CreateOverlayEntity(pGUIEnt, "logo", "interface/proton.rttex", 0,0); CL_Vec2f imageSize = pEnt->GetVar("size2d")->GetVector2(); FadeInEntity(pEnt, true, 1000); //zoom to bottom right, take 1000 ms to get there, initiate it in 1000 ms. ZoomToPositionEntityMulti(pEnt, GetScreenSize()-imageSize, 1000, INTERPOLATE_SMOOTHSTEP, 1000); //zoom back to start ZoomToPositionEntityMulti(pEnt, CL_Vec2f(0,0), 1000, INTERPOLATE_SMOOTHSTEP, 2000); //zoom to bottom right again ZoomToPositionEntityMulti(pEnt, GetScreenSize()-imageSize, 1000, INTERPOLATE_SMOOTHSTEP, 3000); FadeOutAndKillEntity(pEnt, true, 1000, 4000)
The logo now fades in, smoothly zooms around the screen a bit, then fades out. (and kills the entity completely)
Let's add a cool “shadow” effect.