proton_entity
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
proton_entity [2010/10/25 04:22] – created seth | proton_entity [2012/02/07 09:38] (current) – aki | ||
---|---|---|---|
Line 9: | Line 9: | ||
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. | 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 past methods I've tried when creating games: | + | Here are some past methods I've tried when creating games: |
- | * Not knowing what I'm doing and hacking everything (see, Dink source) **VERDICT: | + | * Not knowing what I'm doing and hacking everything (see, Dink source) |
- | * Create a giant entity class hierarchy where each kind of thing gets its own class. | + | * **VERDICT: |
- | * Create one SUPER HUGE Entity class that does everything, possibly having it initialize sub objects. It ends up with 200 functions and bloated beyond belief. (See Novashell' | + | * Create a giant entity class hierarchy where each kind of thing gets its own class. |
+ | * **VERDICT: | ||
+ | * Create one SUPER HUGE Entity class that does everything, possibly having it initialize sub objects. It ends up with 200 functions and bloated beyond belief. (See Novashell' | ||
+ | * **VERDICT: | ||
Using all of these, this is how it went: | Using all of these, this is how it went: | ||
- | (Ladies, look at your game development cycle) | + | (Ladies, look at your game programming |
{{: | {{: | ||
Line 29: | Line 32: | ||
==== The Proton Entity System ==== | ==== The Proton Entity System ==== | ||
- | Aka, my version of "my interpretation of how Unity internals sort of work after I used it for a few hours" | + | 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/ | If you take a look at Entity.h you'll see some functions but nothing about thinking/ | ||
- | Well, not much, alone. | + | Well, not much, alone. |
- | ** Instantiate an entity ** | + | The power comes from Components. |
+ | |||
+ | They way they accomplish this is by connecting a component function (say, Render) to a function object called " | ||
+ | |||
+ | There is no looping through the entities to do things, Entities don't even need to be in the same hierarchy or in a list to work. But it's a good idea as the hierarchy makes rendering/ | ||
+ | |||
+ | ====Test drive===== | ||
+ | |||
+ | Ok, time to just cannon-ball into the pool and show you some stuff. | ||
+ | |||
+ | If you see a weird function, like, BobEntity(), | ||
+ | |||
+ | There are a TON of tiny helper functions in **EntityUtils.cpp**, check the h sometime. | ||
+ | |||
+ | If you'd like to work along with me, open the RTSimpleApp project now! | ||
- | Let's do some real code to give you an idea of how to use these things, feel free to type along. (you could write it in App:: | ||
<code cpp> | <code cpp> | ||
- | Entity ent; //instantiate | + | //Open App.cpp. |
- | //Ok, now we've got one. | + | //MainMenuCreate(pGUIEnt); |
- | ent.SetName("DeLorean"); | + | AddFocusIfNeeded(pGUIEnt); |
+ | Entity *pEnt = CreateOverlayEntity(pGUIEnt, | ||
- | LogMsg(" | + | </ |
- | //Shortcut: we could' | + | Instead of the menu as before, you should |
- | //Yes, I like printf formatting, so sue me. I also like std::strings. | + | {{: |
+ | |||
+ | Well, we see the logo there. | ||
+ | |||
+ | Add a few more lines of code: | ||
+ | <code cpp> | ||
+ | // | ||
+ | AddFocusIfNeeded(pGUIEnt); | ||
+ | Entity *pEnt = CreateOverlayEntity(pGUIEnt, | ||
+ | // | ||
+ | pEnt-> | ||
+ | |||
+ | // | ||
+ | GetMessageManager()-> | ||
+ | //and, move back to 0,0 a second after that. | ||
+ | GetMessageManager()-> | ||
</ | </ | ||
- | ** Is it an entity or a database?! ** | + | |
- | This "Delorean" | + | So now the ball sort of jerks around the screen. |
+ | |||
+ | Instead of jerkily moving, we can use an InterpolateComponent to smoothly change one variant value to another. | ||
+ | |||
+ | 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: | ||
<code cpp> | <code cpp> | ||
- | ent.GetVar(" | + | // |
- | ent.GetVar("trivia")->Set("Doc pronounced giggawatt wrong in the movie"); | + | AddFocusIfNeeded(pGUIEnt); //so it will render, update, and draw. Really it just adds a few components. |
+ | Entity *pEnt = CreateOverlayEntity(pGUIEnt, | ||
- | //retrieve the data like this: | ||
- | LogMsg(" | + | CL_Vec2f imageSize = pEnt->GetVar(" |
+ | |||
+ | FadeInEntity(pEnt, true, 1000); | ||
+ | |||
+ | //zoom to bottom right, take 1000 ms to get there, initiate it in 1000 ms. | ||
+ | ZoomToPositionEntityMulti(pEnt, | ||
+ | //zoom back to start | ||
+ | ZoomToPositionEntityMulti(pEnt, CL_Vec2f(0, | ||
+ | //zoom to bottom right again | ||
+ | ZoomToPositionEntityMulti(pEnt, | ||
+ | FadeOutAndKillEntity(pEnt, | ||
</ | </ | ||
- | Great. Notice that to retrieve | + | The logo now fades in, smoothly zooms around the screen a bit, then fades out. (and kills the entity completely) |
+ | |||
+ | Notice that most things work by time in milliseconds. | ||
+ | |||
+ | Let's add a graphic trail effect to our moving logo. | ||
+ | |||
+ | <code cpp> | ||
+ | // | ||
+ | AddFocusIfNeeded(pGUIEnt); | ||
+ | Entity *pEnt = CreateOverlayEntity(pGUIEnt, | ||
+ | |||
+ | //only this part is new, we're adding a component here | ||
+ | EntityComponent *pComp = pEnt-> | ||
+ | |||
+ | CL_Vec2f imageSize = pEnt-> | ||
+ | FadeInEntity(pEnt, | ||
+ | |||
+ | //zoom to bottom right, take 1000 ms to get there, initiate it in 1000 ms. | ||
+ | ZoomToPositionEntityMulti(pEnt, | ||
+ | //zoom back to start | ||
+ | ZoomToPositionEntityMulti(pEnt, | ||
+ | //zoom to bottom right again | ||
+ | ZoomToPositionEntityMulti(pEnt, | ||
+ | FadeOutAndKillEntity(pEnt, | ||
+ | </ | ||
+ | |||
+ | {{: | ||
+ | |||
+ | You see the same thing as before but with trail. | ||
+ | |||
+ | By simply adding the TrailRenderComponent we can add a " | ||
+ | |||
+ | In fact, this will even work with visuals not invented yet because the method TrailRenderComponent is using is just recording specific variables such as " | ||
+ | |||
+ | We accepted TrailRender' | ||
+ | |||
+ | First, take a look at TrailRenderComponent:: | ||
+ | |||
+ | We see: | ||
+ | <code cpp> | ||
+ | //shared with the rest of the entity | ||
+ | m_pPos2d = & | ||
+ | m_pSize2d = & | ||
+ | m_pScale2d = & | ||
+ | m_pColor = & | ||
+ | m_pAlignment = & | ||
+ | m_pColorMod = & | ||
+ | m_pAlpha = & | ||
+ | m_pRotation = & | ||
+ | m_pTrailAlpha = & | ||
+ | //register ourselves to render if the parent does | ||
+ | GetParent()-> | ||
+ | |||
+ | //our own variables/ | ||
+ | m_pFrames = & | ||
+ | m_pTimeBetweenFramesMS = & | ||
+ | </ | ||
+ | |||
+ | The first big chunk setting up pointers to variables that the parent has (or doesn' | ||
+ | |||
+ | Look near the bottom, it's not using the GetParent() prefix, it's using variables from its own VariantDB. | ||
+ | |||
+ | (It means every 50 ms it takes a " | ||
+ | |||
+ | So those are the two properties we can change! | ||
+ | |||
+ | Add this code somewhere after the TrailRenderComponent | ||
+ | |||
+ | <code cpp> | ||
+ | pComp-> | ||
+ | pComp-> | ||
+ | </ | ||
+ | |||
+ | Then compile and you'll get this: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Whee! | ||
+ | |||
+ | Let's say you want the image to be clickable, and when clicked, it changes to a random tint color. | ||
+ | |||
+ | Here is the new code: | ||
+ | <code cpp> | ||
+ | //first add this anywhere above the App:: | ||
+ | |||
+ | void OnEntityTouched(VariantList *pVList) | ||
+ | { | ||
+ | CL_Vec2f touchPt = pVList-> | ||
+ | Entity *pEntTouched = pVList-> | ||
+ | |||
+ | LogMsg(" | ||
+ | |||
+ | // | ||
+ | pEntTouched-> | ||
+ | } | ||
+ | |||
+ | //Next, add this to your existing init code from the last section | ||
+ | |||
+ | //add the change color when touch stuff | ||
+ | pComp = pEnt-> | ||
+ | pEnt-> | ||
+ | </ | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Clicking (tapping once on a touch device) it will now change the color randomly and show something like " | ||
+ | |||
+ | Well, we came this far, let's make a few changes so ten of these things spawn and randomly move around forever. | ||
+ | |||
+ | First we'll need to add another separate function to wire to, in addition to the one we did. Here they both are: | ||
+ | |||
+ | <code cpp> | ||
+ | |||
+ | void OnEntityTouched(VariantList *pVList) | ||
+ | { | ||
+ | CL_Vec2f touchPt = pVList-> | ||
+ | Entity *pEntTouched = pVList-> | ||
+ | |||
+ | LogMsg(" | ||
+ | |||
+ | //change to a new random tint | ||
+ | pEntTouched-> | ||
+ | } | ||
+ | |||
+ | void MoveEntityToRandomPlace(VariantList *pVList) | ||
+ | { | ||
+ | Entity *pEnt = pVList-> | ||
+ | |||
+ | CL_Vec2f vPosToMoveTo = CL_Vec2f(Random(GetScreenSizeX()), | ||
+ | |||
+ | int timeToTakeForMoveMS = RandomRange(100, | ||
+ | ZoomToPositionEntityMulti(pEnt, | ||
+ | |||
+ | // | ||
+ | //message manager | ||
+ | GetMessageManager()-> | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | And here is the replacement code for the init: | ||
+ | |||
+ | <code cpp> | ||
+ | // | ||
+ | AddFocusIfNeeded(pGUIEnt); | ||
+ | |||
+ | int logosToCreate = 10; | ||
+ | |||
+ | while (logosToCreate--) | ||
+ | { | ||
+ | |||
+ | //start in a random place | ||
+ | Entity *pEnt = CreateOverlayEntity(pGUIEnt, | ||
+ | EntityComponent *pComp = pEnt-> | ||
+ | pComp-> | ||
+ | pComp-> | ||
+ | float scale = RandomRangeFloat(0.4f, | ||
+ | pEnt-> | ||
+ | FadeInEntity(pEnt, | ||
+ | |||
+ | //add the change color when touch stuff | ||
+ | pComp = pEnt-> | ||
+ | pEnt-> | ||
+ | |||
+ | // | ||
+ | //then use the MessageManager to trigger it when we want | ||
+ | |||
+ | pEnt-> | ||
+ | |||
+ | //Call it now to get things started. | ||
+ | pEnt-> | ||
+ | } | ||
+ | </ | ||
- | Types the database understands are float, string, uint32, CL_Vector2, CL_Vector3, CL_Rect2f, *Entity, and *EntityComponent. | + | {{:entity_5.png?|}} |
- | VariantDB' | + | And now you get a bundle of crazy logos bouncing around. |
- | ** | + | So now you probably can sort of see the concept of " |
+ | Well written components respond to property changes at any time - for instance, if you were to change the " |
proton_entity.txt · Last modified: 2012/02/07 09:38 by aki