Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Classic Chat / There has to be a better way to do this ... SpriteID to Type Def lookup/mapping ....

Author
Message
ProfVersaggi
12
Years of Service
User Offline
Joined: 6th Apr 2012
Location: Maastricht Netherlands / Chicago, USA
Posted: 24th Feb 2013 22:47
I'm trying to investigate if AppGameKit does this natively (although I think it does not): To Map from a SpriteID to a Type Definition root.

Concept: Missile (Physics Enabled, part of Type Definition) hits an Enemy Vehicle (Physics Enabled, also part of a different Type Definition).

The GetSpriteFirstContact will tell me that my Missile actually hit something and GetSpriteContactSpriteID2 will return the SpriteID of the vehicle it hit.

In 'my' view of the way the world *should* be, the missile should be able to just inform the Enemy Vehicle that it was just hit, and pass along the amount of damage it inflicted as a parameter, the enemy vehicle would know what to do next.

I have complete info on the Missile, no problem there. But all I have is a simple SpriteID for the Enemy Vehicle to work with.

My first question is ... is there any native way to do this in AppGameKit?

Given my dread that there is none, what's the best way to implement this? Sprite Reverse Lookup Table is the only thing which comes to mind...

Here's a psudocode of the problem:




GetSpriteFirstContact(missile.sprID) will tell me that my missile hit something, and spr2 = GetSpriteContactSpriteID2() will retrieve the sprite ID of what it hit, effectively attackbooatSpriteID which equals 116.

What I need to do is map the Sprite ID 116 back to the instance of the Type Definition "attackbooat" which was instantiated "as _enemy", so I can copy the damage amount the Missile bestowed upon it.

Short of creating a "Reverse Lookup Table" which maps SpriteID to their Associated Type Definition bases, I'm at a loss of how to most effectively implement something like this...

Any clues?

----
From the Desk of Prof Versaggi ...
Naphier
13
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 24th Feb 2013 23:01 Edited at: 24th Feb 2013 23:07
I do a FOR-NEXT looping through the possible spriteIDs like so


I was at first worried that this might take a long time, but it doesn't seem to be a problem, it might be more of a problem if you actually have 1000x1000 sprites, but I'm not sure what kind of game might have that many...

Also, when I create a sprite I store the sprite ID and its type in a UDT array. Then as long as I know what ID I started at I can use that to reference the index in the array.

Hope this helps.

Matty H
15
Years of Service
User Offline
Joined: 7th Oct 2008
Location: England
Posted: 24th Feb 2013 23:15
I too think this is a major problem:

User Data

A user data feature has been requested and would solve this issue.

For now though, what Naphier said is probably your best bet. Make sure your sprite ID's are consecutive, then your UDT array will match up with the associated sprite ID, with an offset value.

MikeMax
AGK Academic Backer
12
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 25th Feb 2013 01:07 Edited at: 25th Feb 2013 01:07
Yes i also already asked for a command like this (like in Delphi):

- SetSpriteTag(sprID,Tag) (or Tag$ )
- GetSpriteTag(sprID)

A user defined value associated with the sprite ID (integer ? string ? String may be better... and you can concatenate multiple value .. )
ProfVersaggi
12
Years of Service
User Offline
Joined: 6th Apr 2012
Location: Maastricht Netherlands / Chicago, USA
Posted: 25th Feb 2013 12:13
Thanks for the input gents, I think I may have stumbled across a better solutions (for some discrete cases), which executes at straight lookup speeds rather than iterating through arrays ... have a look and let me know what you think.

Assume the following psudocode (as before):



This enables me to do something like:
spriteLookup[GetSpriteContactSpriteID2()].typeDefinition and get back the string: "Enemy".

Which I can then use in a Select/Case statement of a Finite State Machine, etc ... to quickly retrieve the contents of the UDT.

And instead of having to iterate through the arrays, this operates at straight lookup speeds.

The idea is that to instantiate an array of even 10K items is only a startup cost, is reasonably fast, and doesn't take up much room (I think), because it is by and large sparsely populated. The sprite value itself (which by definition must be unique) is also it's lookup index to the array.

So once we create a sprite, we use it's sprite ID as the array index, put it's String Designation ("enemy", etc) into the corresponding 'typeDefinition' slot, and then we can later on use the results of GetSpriteContactSpriteID2() as the index to the record in the array we are looking for, in the form of:
"spriteLookup[GetSpriteContactSpriteID2()].typeDefinition"

Now, that only gets you a simple string as a lookup, but it's fast, and for some specific cases, that's all you need as input to a select/case statement which would do the rest of the 'heavy' lifting .... so to speak.

Here's how I used did the heavy lifting psudocode:



I plan to implement this in an "Enemy Factory" type of set up which creates enemies by the scores so I'll be able to tell you (later) if this strategy works in that context.

I hope this helps ....

----
From the Desk of Prof Versaggi ...
Digital Awakening
AGK Developer
21
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 25th Feb 2013 13:38
You know you can specify groups and collision bits for the sprites too? I don't remember the specifics but I use them for my game.


Demo 3 is out now!
Van B
Moderator
21
Years of Service
User Offline
Joined: 8th Oct 2002
Location: Sunnyvale
Posted: 25th Feb 2013 14:09
I think you'd be better off using a controlling type that matches your sprite ID's. So sprite 1 is indice 1 on your typed array. Basically every entity in your game would be governed by an entity type and array. This goes for the player, the enemies, the bullets, everything that moves really.

Then, when you detect a collision, the sprite ID can reference that entity type, and instantly you can check what the sprite actually is.

This can cause your program to have a bigger memory footprint, but it's worth it the first time you don't have to do a recursive check - like if you had to make a function to return the entity based on which sprite collided. Really you'd just be adding an array to provide parallel data to the sprite itself - need to know who fired a bullet?, add a variable to track the parent sprite ID, then you can check if it's a player bullet or an enemy bullet. Doing it this way makes it much easier and faster.

I got a fever, and the only prescription, is more memes.
Naphier
13
Years of Service
User Offline
Joined: 2nd Oct 2010
Location: St Petersburg, Florida
Posted: 25th Feb 2013 20:14
The UDT array is the way to go in my book. Just need to keep track of the array size and you can use all sorts of flags to avoid multiple function calls.
I'm concerned that a command the returns a sprite ID that collided with a sprite that was input as a parameter would be heavy on the processor. It's really not that difficult to make an array containing sprite number and sprite type. An iteration through an array is pretty light on CPU.

One thing to watch out for is there are a couple issues with arrays. If you re dimension an array[x,y] where y > 1 you'll lose data. This may be fixed in 1088b. Also to note an array[x] actually allows you to store 0 to x elements, i.e. one more element than is typical. And a final array issue I found is that if you make a UDT array[x] and accidentally store data in index X you'll get a big crash (unexpected error message instead of subscript OOB).

I iterate through multiple arrays in my game to handle sprites and sacrifice no speed that I can notice
At the end of the level I clear them all out since I think they can only be 8000 elements max, or something like that.

ProfVersaggi
12
Years of Service
User Offline
Joined: 6th Apr 2012
Location: Maastricht Netherlands / Chicago, USA
Posted: 25th Feb 2013 20:17
Van B - I think I'm graduating toward that philosophy. Do you have any short N sweet examples lying around the house?

----
From the Desk of Prof Versaggi ...
Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 26th Feb 2013 02:27 Edited at: 26th Feb 2013 02:46
This is how I would approach this problem (and have done, many times before, in DBPro, AppGameKit and C++, among others):



This code may or may not actually compile as I haven't tested it; it's here for you to see how I would approach this problem, not to copy and paste (although you're absolutely welcome to do this if you really want).

There's probably quicker ways of doing this, but I haven't found any and so far this has proved to be an exceptionally fast method anyway

EDIT: Of course if you're not re-using emptied array indices and you're using statically sized arrays you can simply place data about each sprite in its corresponding array index (ie, spriteID=arrayIndex), which makes it much quicker and far simpler to find specific array indices. You simply use the sprite's ID as the array index.

EDIT2: This will only work, of course, if you only have one array containing sprites. If you have two or more, you'd have to use an offset on the sprite's ID to find the array index. For example, assume you have two arrays, each of size 50. To find a sprite in array 1, you would use "array1[spriteID]". To find a sprite in array 2, you would use "array2[spriteID-50]" (because the array indices begin at 0, not 50, whereas sprite IDs 1-50 have been used up in array1). I'm sure you understand

EDIT3: Forgot to mention that because array indices start at 0 and sprite IDs start at 1, you'd have to use "array1[spriteID-1]". I'm sure you thought of that already, though

EDIT4: Just for the sake of being clear, here is another example, this time using the methods described in my previous EDITs. I'm fairly certain the offsets are correct, but I have other things to do and don't have time to check for you



Clonkex

Van B
Moderator
21
Years of Service
User Offline
Joined: 8th Oct 2002
Location: Sunnyvale
Posted: 26th Feb 2013 09:56 Edited at: 26th Feb 2013 09:58
I would make an entity type to hold any additional and live data...


Like group to set the type of sprite, mode to set the live state, and parent to store which sprite fired a bullet, or effect etc. Then the array is created with 4000 indexes.

Then I'd make a custom CreateSprite function...



So now there's an array called ent, which holds the sprite group, and any other variables that you need.

Theres a couple of tricks you can pull with this as well. Like, if you have 100 bullets, you could use a tiled sprite sheet with each different bullet on it, then set the frame to suit the bullet. When you might usually delete or hide a bullet sprite (after it hits something), you could hide it and set it's mode to 0. Then, the next time you need a bullet sprite, step through the bullet section of that array for modes that equal 0 - set it's mode to 1, show it, and set it's frame to suit the new bullet.

So you could have a recycle function, like this:



That would check through all the sprites for the first sprite that matches the image and is dead (mode=0). There are lots of optimisations that you can do - like have a specific range of sprites that are bullets, say sprites 100 to 200. Once you 'fetch' a sprite, set the frame to whatever you need, show it, and set its mode to live again (mode=1). It might be an idea to use an array, with an index for each sprite group, say group 0 is the player, group 1 is bullets, group 2 is enemies, group 3 is for effects. Then have a counter for each group, like a range of sprites...



So you would set groupsprite[1].start to 2, and groupsprite[1].finish to 100, and have the .current variable reset to the .start value when it goes over the .finish value. Doing this would keep the recursion checks down to a minimum when spawning a sprite, as it would only need to check the relevant group.

So that fetch function might have a version that uses the group to filter out the sprite search...



This is what I would do at least, say I was writing an arcade game with lots of bullets, or lots of enemies or collectables even - I think it's worth doing when you have more than a dozen or so sprites to manage.
I hope I've made sense.

I got a fever, and the only prescription, is more memes.
ProfVersaggi
12
Years of Service
User Offline
Joined: 6th Apr 2012
Location: Maastricht Netherlands / Chicago, USA
Posted: 26th Feb 2013 12:55
Van B - Thank you again, I've not only used your water demo as inspiration for my game but this one as well.

I ended up making a type "_spriteLookupTable" that held a few necessary fields and then instantiating a global array of size 20K to hold every movable sprite in the game ... which I assigned to the table upon creation. I next used a series of Finite State Machines along with local types and corresponding global arrays for the various munitions and bad guys.

The sprite lookup table didn't take up much space and the reference are straight indexed lookups which can't be beat.

Big thanks from the Netherlands!

----
From the Desk of Prof Versaggi ...
Van B
Moderator
21
Years of Service
User Offline
Joined: 8th Oct 2002
Location: Sunnyvale
Posted: 26th Feb 2013 13:27
Sounds like your making real progress, glad I was able to help

I got a fever, and the only prescription, is more memes.

Login to post a reply

Server time is: 2024-05-03 00:05:47
Your offset time is: 2024-05-03 00:05:47