I've been asking myself this for a while because I've done pretty poor results so far.
My current working game engine does the following : There is an "object table" wich basically state all present objects on the screen (player aside), including monsters and items, or just nothing if the object slot is unused. If it's a monster, then it will refer to a big monster table wich state data for all monsters of the game (basically hit points, animation frame table, color, and AI). For AI, the game engine will just jump to the specified adress, and code here has to be made to handle monster moves in function of any existing element. This code also has to be made so that if the monster has taken enough damage it should die (because that won't be done automatically, even if the damage is recorded automatically).
I think it's kinda anoying to have to code low level stuff for each specific monster, but I don't know how I could do anything better.
If someone has any (good) experience doing this stuff, please share it here.
PS : It has been a while since I (or even anyone else) asked an actual nesdev question arround (instead of random blablering)... No never mind this.
The "Object Table Way" is indeed the standard way to do things. If you read
the blog entry about programming M.C. Kids, you'll see that he also uses object tables.
The main areas that method can be improved are separate tables for projectiles, so that monsters searching for player projectiles does not need to skip over the other monsters, or other game objects which do not respond to collisions. If you still need to accelerate collision checking with projectiles, repeatedly subdivide the screen so that objects far away are never even considered.
That's an interesting article. Even trough I didn't 100% get everything on the first read, that's really great stuff to know.
It doesn't much cover A.I. however, it just looks like they worked with a lot of flags and just have each object have it's own routine to handle all non-automated stuff.
What my game engine curently does is have the same table for projectiles, objects and monsters (however, it's easy to see wich one is a said objects because the main bits of their object ID directly says their type, to have optimised collision and code execution, because all projectiles and items require very similar programm to be executed), but I have a different table for graphical effects (explosions, etc...) that have nothing to do with actual math stuff, so that they can be handled separately.
I haven't gotten to this part in my game yet, but I plan to do things in a similar way... I'll have the active objects array, with all their information. Somewhere in there will be the type of the enemy/object, which is used to read the addresses of their routines and jump there (through a jump table).
The index of the enemy slot is still in one of the index registers, so that the routine can work with the correct object slot. To minimize the ammount of code in each object's routine, common things they can do are stored in other subroutines, and all objects can make use of those.
When the object's routine is called, another parameter (besides the object slot) is passed, indicating if it should be loaded, unloaded, or just processed normally. Of course it can unload itself after it dies, but it can be removed if the screen it was at was unloaded, so the object is requested to unload itself, so that it can do this properly (some objects will refuse to be unloaded, but that is desirable sometimes).
I don't know if this will be any good speed-wise, but makes a lot of sense. The best way I could think of so far.
tokumaru wrote:
I haven't gotten to this part in my game yet, but I plan to do things in a similar way... I'll have the active objects array, with all their information. Somewhere in there will be the type of the enemy/object, which is used to read the addresses of their routines and jump there (through a jump table).
C++ does this. Once you get a jump table per actor type, then you're programming object-oriented assembly
Quote:
The index of the enemy slot is still in one of the index registers, so that the routine can work with the correct object slot. To minimize the ammount of code in each object's routine, common things they can do are stored in other subroutines, and all objects can make use of those.
Inheritance. And when you set up jump tables that override some common functions but not others, that's polymorphism.
Yeah, I never really thought about object-oriented concepts in assembly, but I guess you are right! =)
The other great piece of advice: Don't have lots of objects which collide with the same type...Like if you're writing Bubble Bobble, don't have the bubbles check for collision with the other bubbles. You'll quickly learn what O(N^2) means.
Collision detection, like sorting, is O(n^1.5) or even O(n log n) if you do it right. Keep your collidable objects sorted by X or Y coordinate, and you'll never have to compare two objects that are more than, say, 16 pixels apart.
My game engine is made so that item objects check if they collide to the player, projectile objects check if they collide with either player and monsters (depending on a flag beside the projectile itself), and monster objects only check for the player (logical). All other types of collision aren't needed for my game.
Quote:
I haven't gotten to this part in my game yet, but I plan to do things in a similar way... I'll have the active objects array, with all their information. Somewhere in there will be the type of the enemy/object, which is used to read the addresses of their routines and jump there (through a jump table).
That's pretty much what I do, exept that the routine is hard-cored and is the same for all types of projectiles, and there is a spearate tables for items (wich holds simple and unsequential programms, called only once the player collides with them and ignored otherwise) and enemies (wich typically hold complicated sequencial programms, that should be called each frame). All colision detection and damage is done in the global loop regardless of the items themselves. I ask myself if I should move to a more generic format, where all routines besides the enemies are doing all by themselves, including collision detection (I guess they would just all share a jsr something, that isn't a terrible waste of space if you ask me) and this allows for monsters to ignore collision detecion in some situations (actually I can already do that by forcing the monster to be in a "hurt" state even if it's not hurt, so that the main programm ignoeres it).
Doing so would allow more flexibility, but even more low-level code in each monster programm, and this would be annoying. This would also allow to merge monsters and items together, since everything would be in their respective programm and not hard-cored into the game engine. A great advantage of this would be the use of very particular objects, that could only react to a single type of projectile (revealing a secret passage) or such things, that cannot be currently supported (or at least not without very tricky specific programms).
Bregalad wrote:
My game engine is made so that item objects check if they collide to the player, projectile objects check if they collide with either player and monsters (depending on a flag beside the projectile itself), and monster objects only check for the player (logical). All other types of collision aren't needed for my game.
Yeah, my game is like this too. Each enemy/object knows what it can collide with (and this is usually just the player), so that no unnecessary checks are performed. Also, enemies and objects have limited collision with the ground, walls and such (some don't need any), so they don't spend much time with that either.
What really concerns me about my game engine (speed-wise) is what I call "object metatiles". These are metatiles that belong to objects, and they "patch" the level map, modifying it in a way that they can be animated and removed somewhat like sprite objects, but with limitations of course. These allow me to simulate bigger sprite objects, otherwise impossible on the NES. Thing is that every time I render a row or a column of metatiles due to scrolling, I have to check this list for any object metatiles that should be in the row/column I'm currently rendering. I'm currently thinking of a way to sort this list so that looking for metatiles in it is not painfully slow.
As long as your game don't slow down (or isn't too close of doing so) I see no reason to optimise things more. Actually I'm more wondering optimising for having a good and confortable interface with your objects (I'm not too satisfacted in that area right now), rather than optimising the speed of code execution (of course, things have to be done decently fast, but I'm not too worried about this, this isn't what causes me much trouble).
Bregalad wrote:
As long as your game don't slow down (or isn't too close of doing so) I see no reason to optimise things more.
Unless you plan on porting your engine to handhelds, all of which have "sleep" instructions that cut power to the CPU until the next IRQ. Or unless you want to add more things going on at the same time.