Author Topic: Entity ID system implementation  (Read 2202 times)

NateTheGreatt

  • Member
  • **
  • Posts: 83
  • Karma: +0/-0
  • smell the sound
    • View Profile
    • n8bit
Entity ID system implementation
« on: Wed, Aug 10, 2011 »
I want to implement an entity ID system into my game because I am going to have quite a bit of of items and pickups. I wasn't sure of the best way to go about this. I would like to be able to call a function like player.giveItem(itemID) and have it sort out what type of item it is and put it in my player's inventory. For now the items are just weapons and ammo, but I plan to have a lot more items like tools, parts, accessories, food, etc.

Are there any standard ways to implement a system like this?
"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."
-Antoine de Saint-Exupery

foosety

  • Member
  • **
  • Posts: 88
  • Karma: +0/-0
    • View Profile
Re: Entity ID system implementation
« Reply #1 on: Wed, Aug 10, 2011 »
Not sure if this is what your looking for but you can give sprites their own unique id by setting Flxsprite().ID; It's pretty useful.

cambrian man

  • Member
  • **
  • Posts: 6
  • Karma: +0/-0
    • View Profile
Re: Entity ID system implementation
« Reply #2 on: Thu, Aug 11, 2011 »
You could have an array somewhere with references to the classes of your items. So when you call giveitem(23) it looks in entities[23] and instantiates that.

Personally, the way I've been doing things in my current game is to use getDefinitionByName() in flash.utils to get a reference to a class definition from a string. That way, I can just put a 'Bat' into my game, rather than '124' or something, which I'll probably forget.

For instance:
Code: [Select]
entity = new (getDefinitionByName("enemies." + Monster) as Class)(X, Y);
You do have to remember to actually declare a variable somewhere in your source code so that the class gets added to your project. So, like,
Code: [Select]
private var __bat:Bat;

NateTheGreatt

  • Member
  • **
  • Posts: 83
  • Karma: +0/-0
  • smell the sound
    • View Profile
    • n8bit
Re: Entity ID system implementation
« Reply #3 on: Sat, Aug 13, 2011 »
You could have an array somewhere with references to the classes of your items. So when you call giveitem(23) it looks in entities[23] and instantiates that.

Personally, the way I've been doing things in my current game is to use getDefinitionByName() in flash.utils to get a reference to a class definition from a string. That way, I can just put a 'Bat' into my game, rather than '124' or something, which I'll probably forget.

For instance:
Code: [Select]
entity = new (getDefinitionByName("enemies." + Monster) as Class)(X, Y);
You do have to remember to actually declare a variable somewhere in your source code so that the class gets added to your project. So, like,
Code: [Select]
private var __bat:Bat;

That is useful! Thank you
"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."
-Antoine de Saint-Exupery

Titch

  • Contributor
  • ****
  • Posts: 270
  • Karma: +0/-0
  • Thing with the guy in the place.
    • View Profile
Re: Entity ID system implementation
« Reply #4 on: Sun, Aug 14, 2011 »
There are a lot of options for this.

You could create an object registry. Make a dictionary of strings and associated classes, so you can parse in a string and get an class back (which you can then new() to make a new instance). Something like this:

Quote
public class ClassRegistry
   {
      
      private var store:Dictionary = new Dictionary
      private var warnings:Dictionary = new Dictionary
      
      public function ClassRegistry()
      {
         
      }
      
      public function registerClass ($class:Class, $key:String):void
      {
         trace("registering " + $class +  " at " + $key);
         if ($key in store)
         {
            trace("warning, key overlap, class " + store[$key] + " will be replaced with " + $class);
         }
         store[$key] = $class;
      }
      
      public function getClass ($key:String):Class
      {
         if ($key in store) return store[$key];
         else if (!warnings[$key])
         {
            trace(this + " WARNING : [" + $key + "] not registered with a class, call registerClass first");
            warnings[$key] = true;
         }
         return null;
      }
      
      public function hasClass($key:String):Boolean
      {
         if ($key in store) return true;
         return false;
      }
      
   }

The big annoying downside if that you have to have a register all the strings somewhere when the application starts. But it does mean giving the player an item is going to be readable since you can just write.

giveItem(new registry.getClass("LASER_SWORD"))

This whole solution is a little isn't that elegent and would be a strain on the processor if you gave the player a lot of stuff at once since it's fabricating every single object.

The 'neat' alternative is to extend FlxSprite with some sort of InventoryObject class and make an inventory manager. InventoryObject have their own int variable that tracks the number of that item that is stacked, a boolean to track if they are stackable objects or not and a unique string key that lets you identify the object without needing the class (which could just be a string of the class name, for simplicity).

When the player picks up an object the manager looks in the list of items to see if the player is carrying a stackable version of them same item. If not it just creates adds that item under the key defined in the object. Keep in mind that it's a reference to the same object so if you kill() it somewhere else it might have strange effects. If it -does- find an identical item with the same key it just increases it's stack variable by the amount of the object being added (rather than 50 bullet objects the player has 1 bullet object with a stack value of 50) and trashes the old object.

You could of course combine both to keep the amount of objects created down. So you could store item 'drops' as a list of registry key names and stack counts. Then when the player uses an interaction that requires them to pick up the drops you could created them and parse them into the players inventory manager.
Free cake whippings every day at #flixel on irc.freenode.net.

NateTheGreatt

  • Member
  • **
  • Posts: 83
  • Karma: +0/-0
  • smell the sound
    • View Profile
    • n8bit
Re: Entity ID system implementation
« Reply #5 on: Sun, Aug 14, 2011 »
There are a lot of options for this.

You could create an object registry. Make a dictionary of strings and associated classes, so you can parse in a string and get an class back (which you can then new() to make a new instance). Something like this:

The big annoying downside if that you have to have a register all the strings somewhere when the application starts. But it does mean giving the player an item is going to be readable since you can just write.

giveItem(new registry.getClass("LASER_SWORD"))

This whole solution is a little isn't that elegent and would be a strain on the processor if you gave the player a lot of stuff at once since it's fabricating every single object.

The 'neat' alternative is to extend FlxSprite with some sort of InventoryObject class and make an inventory manager. InventoryObject have their own int variable that tracks the number of that item that is stacked, a boolean to track if they are stackable objects or not and a unique string key that lets you identify the object without needing the class (which could just be a string of the class name, for simplicity).

When the player picks up an object the manager looks in the list of items to see if the player is carrying a stackable version of them same item. If not it just creates adds that item under the key defined in the object. Keep in mind that it's a reference to the same object so if you kill() it somewhere else it might have strange effects. If it -does- find an identical item with the same key it just increases it's stack variable by the amount of the object being added (rather than 50 bullet objects the player has 1 bullet object with a stack value of 50) and trashes the old object.

You could of course combine both to keep the amount of objects created down. So you could store item 'drops' as a list of registry key names and stack counts. Then when the player uses an interaction that requires them to pick up the drops you could created them and parse them into the players inventory manager.

This sounds brilliant. I'm gonna give my hand at combining these methods, because I do want drop tables :D. Your posts are wonderfully helpful, can't thank you enough
"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."
-Antoine de Saint-Exupery

Titch

  • Contributor
  • ****
  • Posts: 270
  • Karma: +0/-0
  • Thing with the guy in the place.
    • View Profile
Re: Entity ID system implementation
« Reply #6 on: Sun, Aug 14, 2011 »
Oh, one more thing I forgot to mention. You could keep using numeric indexing for objects and just define constants for everything as static constants. So you would have one big static ObjectIDs.as that would look like this

Code: [Select]
public class ObjectIDs
{

public static const SWORD:int = 0;
public static const POTION:int =1;
public static const COIN:int =2;
}

Then whenever you need to make a reference to the object you just use the constant name

Code: [Select]
giveItem(ObjectIDs.SWORD)
There are two issues with this. The first is it creates a huge, hard to maintain class that has to be manually updated every time you add an object (imagine if you need to add something in the middle of the numerical sequance and every object higher has to be bumped up by one). The second is that the constant references are only going to be useful within the scope of the code. If you wanted to parse some kind of external list (from XML or text) you couldn't use the constant referances without making some sort of wacky wrapper function inside ObjectID's that could look up the constant based on a string. Also it's going to mean doing twice as many lookups, as opposed to the single one you would be doing with a class registry

String --> ObjectIDs --> Constant --> ClassRegistry --> Item;

as opposed to

String --> ClassRegistry --> Item;

It is however worth keeping in mind that you could set string constants for objects you refer to alot in code so that you are less likely to screw up the spelling by mistake, or if you do make an error its the same all the way through the code rather than being wrong in just one place. For example:
Code: [Select]
public class ObjectIDs
{

public static const PNEUMONOULTRAMICROSCOPIC-SILICOVOLCANOCONIOSIS:string= "PNEUMONOULTRAMICROSCOPIC-SILICOVOLCANOCONIOSIS";
}

If you make a typo in the constant name then the compiler will stop before compiling the code, and you won't end up with a wacky error at runtime. Also if you use FlashDevelop it will give you code completion too :)

(NB: Yes, I went on Google and looked up 'hardest to spell word' >_>)
Free cake whippings every day at #flixel on irc.freenode.net.

John Hutchinson (Johntron247)

  • Commodore 256
  • Contributor
  • ****
  • Posts: 392
  • Karma: +1/-0
  • I can has lazerz?
    • View Profile
    • Level X Games
Re: Entity ID system implementation
« Reply #7 on: Sun, Aug 14, 2011 »
Wow Titch, phenominal suggestions!

NateTheGreatt

  • Member
  • **
  • Posts: 83
  • Karma: +0/-0
  • smell the sound
    • View Profile
    • n8bit
Re: Entity ID system implementation
« Reply #8 on: Mon, Aug 15, 2011 »
Wow Titch, phenominal suggestions!

Seriously! Can't thank you enough, Titch. My game owes you two!
"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."
-Antoine de Saint-Exupery

NateTheGreatt

  • Member
  • **
  • Posts: 83
  • Karma: +0/-0
  • smell the sound
    • View Profile
    • n8bit
Re: Entity ID system implementation
« Reply #9 on: Fri, Aug 26, 2011 »
There are a lot of options for this.

You could create an object registry. Make a dictionary of strings and associated classes, so you can parse in a string and get an class back (which you can then new() to make a new instance). Something like this:

The big annoying downside if that you have to have a register all the strings somewhere when the application starts. But it does mean giving the player an item is going to be readable since you can just write.

giveItem(new registry.getClass("LASER_SWORD"))

This whole solution is a little isn't that elegent and would be a strain on the processor if you gave the player a lot of stuff at once since it's fabricating every single object.

The 'neat' alternative is to extend FlxSprite with some sort of InventoryObject class and make an inventory manager. InventoryObject have their own int variable that tracks the number of that item that is stacked, a boolean to track if they are stackable objects or not and a unique string key that lets you identify the object without needing the class (which could just be a string of the class name, for simplicity).

When the player picks up an object the manager looks in the list of items to see if the player is carrying a stackable version of them same item. If not it just creates adds that item under the key defined in the object. Keep in mind that it's a reference to the same object so if you kill() it somewhere else it might have strange effects. If it -does- find an identical item with the same key it just increases it's stack variable by the amount of the object being added (rather than 50 bullet objects the player has 1 bullet object with a stack value of 50) and trashes the old object.

You could of course combine both to keep the amount of objects created down. So you could store item 'drops' as a list of registry key names and stack counts. Then when the player uses an interaction that requires them to pick up the drops you could created them and parse them into the players inventory manager.

I tried implementing this but when I do spawnItem(new itemRegistry.getClass("redSquare")) it throws an error saying that the method cannot be used as a constructor :c. Anyone know the proper way to implement this?
"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."
-Antoine de Saint-Exupery