I haven’t posted in a few days and that’s because I’ve been spending my time doing research. I’ve been peeking at other games and seeing how they handle sprite objects. By sprite object, I mean entities in a game that are represented on screen with sprites: enemies, projectiles, powerups, etc. When I was trying to code bullets, I didn’t really know how to go about it. Should I keep them separate from other sobjects (sprite objects) or are there enough similarities to lump them together?

If you think about it, a bullet isn’t much different from an enemy. It has an x and a y. It has a speed and a movement pattern. It has a palette. It has a hit box. The main difference is what you check for collision against. Enemies collide with the hero. Hero bullets don’t. They collide with enemies instead.

So some logic is different, but the data (or rather type of data stored) is the same! As far as turning the sobject data into actual sprites, bullets can be treated just the same as enemies (the hero too). Why do I care? If I am able to lump them all together, I can make all the sprites in a single loop. Here’s an example of what I mean:

Sobjects to Sprites

Let’s say I have a hero. That’s one sobject. He can shoot bullets. Let’s say I want to allow 3 bullets maximum on the screen at a time. That’s three more potential sobjects. Then enemies. Just pulling a number out of the air, lets say I want there to be 10 enemies on the screen at a time maximum. That’s ten more potential sobjects.

1 hero + 3 bullets + 10 enemies = 14.

So I have 14 sobjects that could be represented on the screen at any one time. If I treat them all the same, I can hold all of the data in arrays, like this:

sobj_id: .res 14
sobj_hp: .res 14
sobj_x: .res 14
sobj_y: .res 14
sobj_hitbox_top: .res 14
sobj_hitbox_bottom: .res 14
...etc

Then whenever I need to turn them into sprites, I can just loop through them all using an index register:

sobjects_to_sprites:
    ldx #$00
@loop:
    lda sobj_id, x
    ;do stuff
    ;calculate y, CHR#, attrib and x
    ;for each sprite of the sprite object
    ;and store in DMA sprite RAM

    inx
    cpx #.sizeof(sobj_id) ;loop through all 14
    bne @loop
    rts

And that will cover all my sobjects as far as turning their data into sprites. I don’t need to write more than one routine!

To differentiate between sobject types (bullet vs. enemy vs. hero), I can just have their index range set. For example, hero is always index 0. Bullets are always 1-3. And enemies are always 4-13. This way I always know what to test for collisions against: enemies will always test against index 0 (hero) and deal damage on a collision. Enemies will also test against index 1-3 (bullets) and receive damage on a collision.

With defined index ranges, limit testing is easy too: If the player presses the fire button, check sobjects 1-3. If they are full already, don’t create a new bullet. If there is an open space there, create a new bullet.

Conclusion

I think I finally figured out how I’m going to arrange sprite objects. Today I rewired all of my previous hero-moving code to fit into this new data model and I think I have it working. Tomorrow I’m going to try to add bullets for real!

One Response to “Explorer: 11 – Sobjects”

  1. miau says:

    Exactly the way I’m doing it. The Mega Man games have inspired me in particular.
    However, I’m considering to restrict some of the variables (that bullets/particles don’t use) to the hero/enemies only and thus save ram.

    That would allow for a few more bullets on screen.

    E.g.
    hero/enemies = index 0-10
    bullets = index 11-20
    - x and y position vars used for all objects, index 0-20 valid
    - a set of flags that bullets don’t use (e.g. the “climbing” flag in my engine, bullets don’t usually climb ladders), index 0-10 valid, anything above is actually “unallocated” free memory that can be used for other data

    Just gotta be careful not to use any of the latter variables in the main game physics routine and other code that you want to handle both types of objects.

    Anyway, just another brain dump of mine, might not be worth it in your project. I’ll be keeping it simple for now as well. :)

Leave a Reply