TGC Codebase Backup



Simple AI by Jcamden

19th Oct 2011 15:37
Summary

Simple 2d style AI Movement



Description

The AI.h header contains very simple AI movement using dbSprite and dbMoveSprite functions. You can use any image for your player and enemy. This is just for testing so anyone can understand the basic functions. The MoveEnemy(e) function does not have any collision detection but the MoveEnemyWithAngle(e) does.



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    // AI header file //
// This is a very basic AI enemy that locates a player //

#define NONE			(-1)
#define PLAYER_ID		(1)
#define ENEMY_ID		(2)

#define RIGHT_ANGLE		(270)
#define LEFT_ANGLE		(90)
#define RESET_ANGLE		(0)

typedef struct Enemy_
{
	WORD id;				// Enemy id, usually same as image id
	WORD x;					// x coord of enemy
	WORD y;					// y coord of enemy
	float speed;			// velocity if we are using dbMoveSprite

	WORD Player_To_Follow;	// Player Id to follow
}Enemy;

void InitializeEnemy(Enemy *e, WORD Id, WORD x, WORD y, float vel)	// Initializes the starting points for the enemy
{
	e->id				= Id;
	e->x				= x;
	e->y				= y;
	e->speed			= vel;
	e->Player_To_Follow = NONE;
	dbSprite(e->id,e->x,e->y,e->id);
	// Need to offset the sprite so that we can rotate at its center.
	dbOffsetSprite(e->id,(dbSpriteWidth(e->id) / 2), (dbSpriteHeight(e->id) / 2));
}

void UpdateEnemyPosition(Enemy *e)
{
	e->x = dbSpriteX(e->id);
	e->y = dbSpriteY(e->id);
}

void FollowPlayer(Enemy *e, WORD Player) // Sets the Pid of that player to follow
{
	e->Player_To_Follow = Player;
}

void FreeMemory(Enemy *e)
{
	dbDeleteSprite(e->id);		// this deletes the image we allocated
	dbDeleteSprite(PLAYER_ID);	// We need to delete the player id sprite to free the memory
	free(e);					// this deletes the memory we allocated
}


// So there are a few ways to track a player //
// you can use the traditional way with dbSprite //
// Or you can use dbMoveSprite for better looking movement //

void MoveEnemy(Enemy *e)
{
	if(dbSpriteX(e->Player_To_Follow) > e->x)// so player 1 x coord is greater than the enemy's coord 
	{
		// now we need to increase the x coord of the enemy to get to the player
		// remember that we need to rotate the sprite in order to go right and left
		e->x++;
		dbRotateSprite(e->id, RIGHT_ANGLE);
		dbSprite(e->id,e->x,e->y,ENEMY_ID);
		dbRotateSprite(e->id, RESET_ANGLE);
	}
	if(dbSpriteX(e->Player_To_Follow) < e->x)// Player 1 coord is less than the enemy so we need to move the other way now
	{
		e->x--;
		dbRotateSprite(e->id, LEFT_ANGLE);
		dbSprite(e->id,e->x,e->y,ENEMY_ID);
		dbRotateSprite(e->id, RESET_ANGLE);
	}
	if(dbSpriteY(e->Player_To_Follow) > e->y)
	{
		e->y++;
		dbSprite(e->id, e->x, e->y, ENEMY_ID);
	}
	if(dbSpriteY(e->Player_To_Follow) < e->y)
	{
		e->y--;
		dbSprite(e->id, e->x, e->y, ENEMY_ID);
	}
}


// So in this function we will get the angle of the player for a more fluid movement
void MoveEnemyWithAngle(Enemy *e)
{
	int PlayerX = dbSpriteX(e->Player_To_Follow);
	int PlayerY = dbSpriteY(e->Player_To_Follow);
	float Angle = dbWrapValue(dbAtanFull(PlayerX - e->x, e->y - PlayerY));
	dbRotateSprite(e->id, Angle);

	if(dbSpriteCollision(e->id, e->Player_To_Follow) == 1)
	{
		// if the enemy sprite collides with the player sprite we need to stop it
		dbMoveSprite(e->id, 0);
	}
	else
	{
		// if the enemy isn't colliding with any sprites let's move!
		dbMoveSprite(e->id, e->speed);
	}
	
}

#include "DarkGDK.h"
#include "AI.h"
#include "Movement.h"


void DarkGDK ( void )
{
	dbSyncOn();
	dbSyncRate(60);
	dbDisableEscapeKey();
	dbSetImageColorKey( 255, 0, 255 );

	// Allocate memory for our Player structure
	Player *p = (Player*) malloc(sizeof(Player));
	Enemy  *e = (Enemy*)  malloc(sizeof(Enemy));

	// Load the image
	dbLoadImage("Player.bmp", PLAYER_ID);
	dbLoadImage("Enemy.bmp", ENEMY_ID);
	// Initialize the player on the screen
	InitializePlayer(p,PLAYER_ID,200,200,PLAYER_SPEED);
	// Initialize the enemy on the screen
	InitializeEnemy(e,ENEMY_ID,50,50,ENEMY_SPEED);
	// this sets the pid of the player to follow
	FollowPlayer(e,PLAYER_ID);

	while ( LoopGDK ( ) )
	{
		UpdateEnemyPosition(e); // Updates enemy x and y coord
		MoveEnemyWithAngle(e);  // Moves the enemy to the player

		MovePlayerWithAngle(p); // Moves player using keys, rotates player with the mouse
		if ( dbEscapeKey ( ) )
			break;

		dbSync();
	}

	// Make sure we delete all images and free memory here
	FreePlayerMemory(p);
	FreeMemory(e);
	return;
}