Post by bcherry on Jan 26, 2005 1:08:09 GMT -5
I just figured out (kind of) how to handle enemies or other dynamic elements of a game in the way that seems most intuitive, yet hardest to implement. What I always wanted was an array for the level map, with static blocks or tiles being numbers less than 100, and dynamic things like moving blocks or enemies being greater than 100, so you have a master array detailing the start locations of all of your enemies.
Then what you do is draw the map like any other, where you loop through the pertinent area and draw each tile based on its tile code. But the problem was how to handle the enemies. So what I do is complicated. As I come across an enemy, I take it out of the map, making that spot 0. Then I put the enemy as an object into a linked list of enemies, that I deal with later. Once I've filled the list and drawn the map, I look through the list one by one until I reach the end. But another problem arises. Lets say I've got 50 different kinds of enemies possible. I don't want to have a 50 large if-else block or case switch set. So what I do is what I've been trying to figure out for months, and just made work. I need to create a structure typedef, Enemy. Within that structure I have basic easy stuff like health and position. But I also have a pointer to the enemy's sprite, so I can just say enemy.sprite and get the right thing to draw, without the hassle of if else. But enemies dont stand still do they? They move around. They attack. They do all sorts of stuff. Different stuff. How do I handle that? The answer is, function pointers. The structure has a field called "behavior" that is a pointer to the function I want. Lets say my two enemy types are Koopa and Goomba. I can make a koopa like this:
Enemy koopa1;
koopa1.sprite = koopaSprite;
koopa1.behavior = koopaBehavior;
And then I can use koopa1.behavior() like I would use any other function, and it would be identical to the predefined function koopaBehavior(). If you're not lost yet, then keep reading. I can make an array of enemies equal to the number of different types there are called "enemyTemplates". This would hold basic templates of type Enemy, with the sprites and behaviors preset to the right value. Then when I come across 101 in the map array, I know to get enemyTemplates[1] and use that to initialize a new Enemy to add into the linked list. Then I run through the linked list, and for each element e, i do draw(e.sprite,e.x,e.y), and e.behavior(e). And handle any kind of enemy I dream up with a general function. To create a new enemy type, I merely would need to make a behavior function, a sprite, and give it a number and make a template. Then everything would fall into place and the game would handle it just fine. Final point of goodness:
When I loop through my list, if I find something to be out of bounds, I drop it back onto the map and take it out of the list, so I don't have to deal with it, but will find it where I left it when I come back for it. If something dies, it disappears from the list, and runs its death function, then never appears again.
Now where am I going with this ultimately? I'm going to revive my metroid project with my newfound knowledge and create a true metroid for the TI-89. Wish me luck. Comment on my implementation, if it makes sense, too.
Then what you do is draw the map like any other, where you loop through the pertinent area and draw each tile based on its tile code. But the problem was how to handle the enemies. So what I do is complicated. As I come across an enemy, I take it out of the map, making that spot 0. Then I put the enemy as an object into a linked list of enemies, that I deal with later. Once I've filled the list and drawn the map, I look through the list one by one until I reach the end. But another problem arises. Lets say I've got 50 different kinds of enemies possible. I don't want to have a 50 large if-else block or case switch set. So what I do is what I've been trying to figure out for months, and just made work. I need to create a structure typedef, Enemy. Within that structure I have basic easy stuff like health and position. But I also have a pointer to the enemy's sprite, so I can just say enemy.sprite and get the right thing to draw, without the hassle of if else. But enemies dont stand still do they? They move around. They attack. They do all sorts of stuff. Different stuff. How do I handle that? The answer is, function pointers. The structure has a field called "behavior" that is a pointer to the function I want. Lets say my two enemy types are Koopa and Goomba. I can make a koopa like this:
Enemy koopa1;
koopa1.sprite = koopaSprite;
koopa1.behavior = koopaBehavior;
And then I can use koopa1.behavior() like I would use any other function, and it would be identical to the predefined function koopaBehavior(). If you're not lost yet, then keep reading. I can make an array of enemies equal to the number of different types there are called "enemyTemplates". This would hold basic templates of type Enemy, with the sprites and behaviors preset to the right value. Then when I come across 101 in the map array, I know to get enemyTemplates[1] and use that to initialize a new Enemy to add into the linked list. Then I run through the linked list, and for each element e, i do draw(e.sprite,e.x,e.y), and e.behavior(e). And handle any kind of enemy I dream up with a general function. To create a new enemy type, I merely would need to make a behavior function, a sprite, and give it a number and make a template. Then everything would fall into place and the game would handle it just fine. Final point of goodness:
When I loop through my list, if I find something to be out of bounds, I drop it back onto the map and take it out of the list, so I don't have to deal with it, but will find it where I left it when I come back for it. If something dies, it disappears from the list, and runs its death function, then never appears again.
Now where am I going with this ultimately? I'm going to revive my metroid project with my newfound knowledge and create a true metroid for the TI-89. Wish me luck. Comment on my implementation, if it makes sense, too.