GCC4 Chapter 6 - Components question

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • GCC4 Chapter 6 - Components question

      Hi there :)

      I am slightly confused about the example given of Pickup components.

      It showed how there is a VApply which should do whatever it needs to be done, such as adding health to the player. But it never mentioned when the VApply should run or to be more precise, how to manage picking up the health pack actor.

      In some games I can imagine it being easy as overloading the pickup interface's VUpdate function to see if the player is in "pickup radius" and then VApply, as well as maybe call a "destroy" event on the actor as it should disappear after picked up.

      How would you go on games where you use a button to use/pickup objects as in most games now? Will the VUpdate be useless? Will the use function, if targets the pickup-actor have to try and GetComponent(pickup component id) and if it exists VApply it to itself?

      Now generally reading the book feels lacking and probably needs the source code, ComponentId is mentioned a lot but never what it is (unsigned int? HashedString as with GCC3?)

      I feel chapter 6 was pretty lacking on examples, say how do you manage hit points? Is it its own component? how do you edit it or react to editing it via combat. I tried to find information in chapter 21 but it felt missing there too.

      The post was edited 1 time, last by Shanee ().

    • RE: GCC4 Chapter 6 - Components question

      The code has just been posted so feel free to grab it now. It definitely helps to look at the code to get a feel for what's happening. Now I'll answer your specific points.

      Originally posted by Shanee
      I am slightly confused about the example given of Pickup components.

      It showed how there is a VApply which should do whatever it needs to be done, such as adding health to the player. But it never mentioned when the VApply should run or to be more precise, how to manage picking up the health pack actor.

      Honestly, the Pickup component is not meant to be a pattern you copy for actually creating pickups in your game. Its purpose is to show the creation of a trivial component to introduce how one can be created. An actual health pickup should be implemented entirely in Lua.

      For a more direct example of how to apply things like hit points, take a look at the code for sphere collision events. You can see that in ActorManager.lua around line 240. You're looking for ActorManager : OnPhysicsCollision(). This is the Lua event delegate for a physics collision event. You can see how it checks the actor types and how it calls the _DamageTeapot() function to lower the health of that teapot. Teapot health is a variable that lives on the Lua side of the ScriptComponent. That's built up in the ActorManager:AddEnemy() function, which is called when an AI teapot is added to the world.

      A pickup should work exactly the same way. There should be a case for when a "Teapot" actor type and "Health" actor type collide, and should add to the teapot's hit points. The actual health pack actor should be rather simple and doesn't need a Pickup component at all. All its data (such as how much health to provide) should live on the Lua side of the ScriptComponent.

      Basically, you should be able to create a health pickup without having to recompile the game at all. It's 100% XML and Lua.


      In some games I can imagine it being easy as overloading the pickup interface's VUpdate function to see if the player is in "pickup radius" and then VApply, as well as maybe call a "destroy" event on the actor as it should disappear after picked up.

      You never want to do this. VUpdate() is a tick function, meaning it runs every frame. You're testing for something to be within the radius every single frame which is wasteful and slow. You want to use physics events rather than poll for it every frame. If you can help it, never write VUpdate() functions.


      How would you go on games where you use a button to use/pickup objects as in most games now? Will the VUpdate be useless? Will the use function, if targets the pickup-actor have to try and GetComponent(pickup component id) and if it exists VApply it to itself?

      If that were the case, I would set up the pickup and health exactly as I have it now. I would send an event (let's call it EvtData_AttemptPickup) which would be received by the ActorManager. The ActorManager would then do a quick radius test that would check to see if there were any pickups in the area and run whatever logic needed to happen if there were. I would also probably have a new list in ActorManager to store all pickups for the level so that's faster to iterate through them. If I had a lot of pickups, I'd likely split that list into a spacial partition so that I only iterate through a small section of it based on where I am in the world.


      Now generally reading the book feels lacking and probably needs the source code, ComponentId is mentioned a lot but never what it is (unsigned int? HashedString as with GCC3?)

      I feel chapter 6 was pretty lacking on examples, say how do you manage hit points? Is it its own component? how do you edit it or react to editing it via combat. I tried to find information in chapter 21 but it felt missing there too.

      This chapter is really about component architecture, not how to implement specific components. Check out the source code for examples of specific components. We also talk about specific components later in the book. For example, it doesn't do much good to talk about the script component before talking about Lua. :)

      ActorId and ComponentId can be anything you want, that's why they're typedef's. There's no right or wrong answer, you should do whatever makes sense for your game. In RatRace and Barbie (two adventure games I worked on), they were cached const strings. This allowed designers and scripters to references specific characters or objects by string directly. On The Sims Medieval, they were 64-bit unsigned ints because we didn't have that requirement and they're faster. In TeapotsWars, ActorId and ComponentId are typedef'ed to unsigned int for the much the same reasons as The Sims Medieval. They are defined at the top of interfaces.h.

      Regarding your hit points and combat question, look at ActorManager.lua to see how it's done in code. You should also read the Actor Manager section of chapter 21, starting on page 739 and continuing to the end of the chapter. That's the section that specifically shows you how to handle pretty much everything you just asked for. ;)

      You should be able to tune or even reinvent the combat system without having to touch any C++ code.

      -Rez