Okay so I'm in the process of trying to design AI for enemies. So far in my game I have one enemy - A snake. I've tried a couple things out for his AI, but currently there are 3 states. One where the snake is just slithering around randomly, one where he's moving towards the player to go in for the attack, and another where he's moving away from the player after being attacked himself. The snake only moves towards the player if he's within a certain radius of him. The basic outline goes like this:
To be honest, I've never gotten far enough in a project to have to worry about how enemies and such behave, so I don't really know what good AI logic looks like. I understand it's different depending on the game and what the entity is actually doing, but I feel like my approach is really redundant. Having multiple entity collision checks that are the same, albeit in different states, just seems incorrect, but I don't know how I'd go about making it only need to happen once without sacrificing the readability of my asm code. I guess what I'm asking for is tips on how you guys go about writing AI code, as I feel like I'm just confusing myself when I don't need to be.
Code:
if (snake.state != RETREATING)
//if snake isn't within a certain radius of the player, set state to slithering
if (player.hb_x < snake.x)
if (snake.x - player.hb_x > 120)
snake.state = SLITHERING;
else
snake.state = ATTACKING;
else if (snake.hb_x < player.x)
if (player.x - snake.hb_x > 120)
snake.state = SLITHERING;
else
snake.state = ATTACKING;
else if (player.hb_y < snake.y)
if (snake.y - player.hb_y > 100)
snake.state = SLITHERING;
else
snake.state = ATTACKING;
else if (snake.hb_y < player.y)
if (player.y - snake.hb_y > 100)
snake.state = SLITHERING;
else
snake.state = ATTACKING;
else
snake.state = ATTACKING;
else
//move snake in its direction at 1 pixel per frame
//resolve collision with background
if (snake.phi_timer == 0) //end of post-hit invincibility
snake.state = SLITHERING;
//exit routine
if (snake.state == SLITHERING)
//randomly move about at .5 pixels per frame, changing directions every second
//resolve collision with the background
else if (snake.state == ATTACKING)
if (player.hb_y < snake.y)
snake.dir = UP;
//move snake up 1 pixel per frame
//resolve collision with background
else if (player.y > snake.hb_y)
snake.dir = DOWN;
//move snake down 1 pixel per frame
//resolve collision with background
else if (player.hb_x < snake.x)
snake.dir = LEFT;
//move snake left 1 pixel per frame
//resolve collision with background
else if (player.x > snake.hb_x)
snake.dir = RIGHT;
//move snake right 1 pixel per frame
//resolve collision with background
else
if (snake collided with player's weapon)
snake.state = RETREATING;
snake.phi_timer = 60;
//set snake direction to opposite of player's direction
//hurt snake, play a sound effect, etc
else
//snake collided with player
//hurt player, put player into post-hit invincibility, play a sound effect, etc
//if snake isn't within a certain radius of the player, set state to slithering
if (player.hb_x < snake.x)
if (snake.x - player.hb_x > 120)
snake.state = SLITHERING;
else
snake.state = ATTACKING;
else if (snake.hb_x < player.x)
if (player.x - snake.hb_x > 120)
snake.state = SLITHERING;
else
snake.state = ATTACKING;
else if (player.hb_y < snake.y)
if (snake.y - player.hb_y > 100)
snake.state = SLITHERING;
else
snake.state = ATTACKING;
else if (snake.hb_y < player.y)
if (player.y - snake.hb_y > 100)
snake.state = SLITHERING;
else
snake.state = ATTACKING;
else
snake.state = ATTACKING;
else
//move snake in its direction at 1 pixel per frame
//resolve collision with background
if (snake.phi_timer == 0) //end of post-hit invincibility
snake.state = SLITHERING;
//exit routine
if (snake.state == SLITHERING)
//randomly move about at .5 pixels per frame, changing directions every second
//resolve collision with the background
else if (snake.state == ATTACKING)
if (player.hb_y < snake.y)
snake.dir = UP;
//move snake up 1 pixel per frame
//resolve collision with background
else if (player.y > snake.hb_y)
snake.dir = DOWN;
//move snake down 1 pixel per frame
//resolve collision with background
else if (player.hb_x < snake.x)
snake.dir = LEFT;
//move snake left 1 pixel per frame
//resolve collision with background
else if (player.x > snake.hb_x)
snake.dir = RIGHT;
//move snake right 1 pixel per frame
//resolve collision with background
else
if (snake collided with player's weapon)
snake.state = RETREATING;
snake.phi_timer = 60;
//set snake direction to opposite of player's direction
//hurt snake, play a sound effect, etc
else
//snake collided with player
//hurt player, put player into post-hit invincibility, play a sound effect, etc
To be honest, I've never gotten far enough in a project to have to worry about how enemies and such behave, so I don't really know what good AI logic looks like. I understand it's different depending on the game and what the entity is actually doing, but I feel like my approach is really redundant. Having multiple entity collision checks that are the same, albeit in different states, just seems incorrect, but I don't know how I'd go about making it only need to happen once without sacrificing the readability of my asm code. I guess what I'm asking for is tips on how you guys go about writing AI code, as I feel like I'm just confusing myself when I don't need to be.