gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > NPC System

#114405 - QuantumDoja - Sun Jan 07, 2007 6:02 pm

Hi, I just want to tell you about the system Im trying to implement for my npc system, please any thoughts are very welcome.....


OAM Array will be an array that holds a typedef like, {id, OAMPtr etc}

OAM Entry 30 to 127 are free to use (for me) so I set up an array with 127 items in it (whenever ill loop, ill start from 30).

ok....so I move the map, and lo and behold a "coin" is in the next column of my npc array...so i need to load that in.......

first i check to see if this "coin" at this position has been loaded into the OAM Array, if it has, dont bother, if it hasnt, add it to the array, then loop the array for find a matching OAM ID thats in memory (a sprite), if none is found, DMA a sprite into memory and update the OAM array with this data, then I draw this onto the screen....

I am fine up to this point (c code).

I can scroll the map now, and the "coin" is scrolling with the map, ok, im getting confused with what happens when the "coin" scrolls off of the edge, should i destroy it? - Should I set it to live, but offscreen....any thoughts welcome....
_________________
Chris Davis

#114426 - DekuTree64 - Sun Jan 07, 2007 9:30 pm

Depends on your needs, really. My opinion:

Easy way: Coin is alive at all times, and only deallocates its OAM if it's offscreen.

Hard way: Keep an array of bools for wether each coin has been picked up. When a coin comes onto the screen, if it hasn't already been picked up, spawn an entity for it. When it goes offscreen, kill the entity.

If you have massive numbers of coins in a level, the hard way will save some memory and processor time, since you'd only need to store 1 bit for each coin, and they don't need to have any sort of updating done to them when offscreen.

If you have less coins, then the easy way is better because you don't need all that code to handle to spawning/killing when scrolling, and managing the status array. Another benefit is that your processing time stays more constant since there aren't things being created and destroyed constantly as you move around, so you don't have to worry about jerky frame rates as much.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#114439 - sajiimori - Sun Jan 07, 2007 11:18 pm

QuantumDoja,

A red flag goes up for me at your second sentence -- the topic of OAMs shouldn't even come up in a discussion about NPCs. =)

NPCs are a very high-level game concept, and OAMs are a very low-level hardware concept. If you have to worry about hardware details while programming game logic, then more abstraction is needed.

Try making a Sprite class that handles details like OAMs.
Code:

class Sprite
{
public:
  enum Size
  {
    SIZE_8x8,
    ...
  };

  void setGraphic(const void* pixelData);
  void setPalette(const void* colorData);
  void setSize(Size);
  void setPosition(const Vector2&);

  const Vector2& position() const;
};

Think about the minimum amount of information that you should have to provide to describe an NPC. If you're writing much more than that in your NPC class, then use more abstraction.
Code:

class Npc
{
public:
  enum Type
  {
    NPC_SHEEP_FLOGGER,
    ...
  };

  Npc(Type type)
  {
    mSprite.setGraphic(kNpcData[type].graphic);
    mSprite.setPalette(kNpcData[type].palette);
    mSprite.setSize(kNpcData[type].size);
  }

  void setPosition(const Vector2& p)
  {
    mSprite.setPosition(p);
  }

  const Vector2& position() const
  {
    return mSprite.position();
  }

private:
  Sprite mSprite;
};

#118934 - Touchstone - Sun Feb 18, 2007 10:17 am

sajiimori wrote:
If you have to worry about hardware details while programming game logic, then more abstraction is needed.

Not necessarily. If you have endless resources you can abstract to your hearts content but to really squeeze every last bit of performance you have to bite the bullet and get rid of abstraction.

Obviously it's a matter of code design, but "more abstraction is needed" is simply not always true.
_________________
You can't beat our meat

#119117 - sajiimori - Mon Feb 19, 2007 10:04 pm

Nobody squeezes every last bit of performance. Attempting to do so results in unmaintainable garbage... not to mention failure to achieve the desired goal of efficiency!

In real life, inadequate abstraction results in bad performance because the programmers can't spend their optimization hours effectively.

And abstraction doesn't necessarily reduce performance. Sometimes it increases performance on plain technical merits, like better cache behavior from reducing code size.

Additionally, good programming tools make it possible to use seemingly expensive abstractions at low cost. Templates and inline functions in C++ are good examples of abstraction tools with potentially zero runtime cost.

So again, if you think you need to twiddle OAM bits in the middle of would-be "high level" game logic, there's something wrong with your design.

Maybe you'll get lucky and no optimizations will be needed, but if performance does become an issue, you'll find yourself in a pit of unmaintainable code that you can't escape without extensive rewrites.

#119295 - sgeos - Wed Feb 21, 2007 6:02 pm

sajiimori wrote:
Nobody squeezes every last bit of performance. Attempting to do so results in unmaintainable garbage... not to mention failure to achieve the desired goal of efficiency!

If you squeeze every last bit of space, you won't be able to localize your game. Saying something in French takes more characters than English. Japanese requires a 1000 to 2000 character font and code to manage it.

-Brendan