Sign in to follow this  
Alvin31

Artificial Intelligence Problem With SDL?

Recommended Posts

any SDL expert please help

i am creating 2d graphical game with SDL.but i got a problem with setting artificial intelligence character on it.my enemy/AI character always following player character around scrolling screen/camera area where my player character walk.i mean the enemy did not walk in his own coordinate and perimeter instead of following my character walking everywhere.

this is the code :


#include "SDL.h"
#include "SDL_image.h"
#include <string>

//Screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The frames per second
const int FRAMES_PER_SECOND = 5;

//The dimenstions of the stick figure
const int FOO_WIDTH = 80;
const int FOO_HEIGHT = 160;

const int NANDA_WIDTH = 80;
const int NANDA_HEIGHT = 160;

const int LEVEL_WIDTH = 1900;
const int LEVEL_HEIGHT = 960;

//The direction status of the stick figure
const int FOO_RIGHT = 0;
const int FOO_LEFT = 1;
const int FOO_FRONT = 2;
const int FOO_BACK = 3;
const int NANDA_RIGHT = 0;
const int NANDA_LEFT = 1;
const int NANDA_FRONT = 2;
const int NANDA_BACK = 3;

//The surfaces
SDL_Surface *foo = NULL;
SDL_Surface *enemy = NULL;
SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;

//The event structure
SDL_Event event;

//The areas of the sprite sheet
SDL_Rect clipsRight[ 2 ];
SDL_Rect clipsLeft[ 2 ];
SDL_Rect clipsFront[ 2 ];
SDL_Rect clipsBack[ 2 ];

SDL_Rect camera = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
SDL_Rect wall;
SDL_Rect tree;
SDL_Rect treef;
SDL_Rect treeb;

//The stick figure
class Foo
{
private:
//The offset
SDL_Rect box;

//Its rate of movement
int xVel, yVel;

//Its current frame
int frame;

//Its animation status
int status;

public:
//Initializes the variables
Foo();

//Handles input
void handle_events();

//Moves the stick figure
void move();

//Shows the stick figure
void show();

void set_camera();
};

class Enemy
{
private:
SDL_Rect musuh;

int xVel, yVel;

int frame;

int status;

public:
Enemy();

void move();

void show();

};

//The timer
class Timer
{
private:
//The clock time when the timer started
int startTicks;

//The ticks stored when the timer was paused
int pausedTicks;

//The timer status
bool paused;
bool started;

public:
//Initializes variables
Timer();

//The various clock actions
void start();
void stop();
void pause();
void unpause();

//Gets the timer's time
int get_ticks();

//Checks the status of the timer
bool is_started();
bool is_paused();
};

SDL_Surface *load_image( std::string filename )
{
//The image that's loaded
SDL_Surface* loadedImage = NULL;

//The optimized surface that will be used
SDL_Surface* optimizedImage = NULL;

//Load the image
loadedImage = IMG_Load( filename.c_str() );

//If the image loaded
if( loadedImage != NULL )
{
//Create an optimized surface
optimizedImage = SDL_DisplayFormat( loadedImage );

//Free the old surface
SDL_FreeSurface( loadedImage );

//If the surface was optimized
if( optimizedImage != NULL )
{
Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF );

//Color key surface
SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );
}
}

//Return the optimized surface
return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )
{
//Holds offsets
SDL_Rect offset;

//Get offsets
offset.x = x;
offset.y = y;

//Blit
SDL_BlitSurface( source, clip, destination, &offset );
}

void set_clips()
{
//Clip the sprites
clipsRight[ 0 ].x = 0;
clipsRight[ 0 ].y = 480;
clipsRight[ 0 ].w = FOO_WIDTH;
clipsRight[ 0 ].h = FOO_HEIGHT;

clipsRight[ 1 ].x = FOO_WIDTH;
clipsRight[ 1 ].y = 480;
clipsRight[ 1 ].w = FOO_WIDTH;
clipsRight[ 1 ].h = FOO_HEIGHT;

clipsLeft[ 0 ].x = 0;
clipsLeft[ 0 ].y = 320;
clipsLeft[ 0 ].w = FOO_WIDTH;
clipsLeft[ 0 ].h = FOO_HEIGHT;

clipsLeft[ 1 ].x = FOO_WIDTH;
clipsLeft[ 1 ].y = 320;
clipsLeft[ 1 ].w = FOO_WIDTH;
clipsLeft[ 1 ].h = FOO_HEIGHT;

clipsBack[ 0 ].x = 0;
clipsBack[ 0 ].y = 160;
clipsBack[ 0 ].w = FOO_WIDTH;
clipsBack[ 0 ].h = FOO_HEIGHT;

clipsBack[ 1 ].x = FOO_WIDTH;
clipsBack[ 1 ].y = 160;
clipsBack[ 1 ].w = FOO_WIDTH;
clipsBack[ 1 ].h = FOO_HEIGHT;

clipsFront[ 0 ].x = 0;
clipsFront[ 0 ].y = 0;
clipsFront[ 0 ].w = FOO_WIDTH;
clipsFront[ 0 ].h = FOO_HEIGHT;

clipsFront[ 1 ].x = FOO_WIDTH;
clipsFront[ 1 ].y = 0;
clipsFront[ 1 ].w = FOO_WIDTH;
clipsFront[ 1 ].h = FOO_HEIGHT;
}

bool check_collision( SDL_Rect A, SDL_Rect B )
{
//The sides of the rectangles
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;

//Calculate the sides of rect A
leftA = A.x;
rightA = A.x + A.w;
topA = A.y;
bottomA = A.y + A.h;

//Calculate the sides of rect B
leftB = B.x;
rightB = B.x + B.w;
topB = B.y;
bottomB = B.y + B.h;

//If any of the sides from A are outside of B
if( bottomA <= topB )
{
return false;
}

if( topA >= bottomB )
{
return false;
}

if( rightA <= leftB )
{
return false;
}

if( leftA >= rightB )
{
return false;
}

//If none of the sides from A are outside B
return true;
}


bool init()
{
//Initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
return false;
}

//Set up the screen
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

//If there was an error in setting up the screen
if( screen == NULL )
{
return false;
}

//Set the window caption
SDL_WM_SetCaption( "Animation Test", NULL );

//If everything initialized fine
return true;
}

bool load_files()
{
//Load the sprite sheet
foo = load_image( "player.png" );

enemy = load_image( "enemy.png" );

background = load_image( "ground.png" );

//If everything loaded fine
return true;
}

void clean_up()
{
//Free the surface
SDL_FreeSurface( background );
SDL_FreeSurface( foo );
SDL_FreeSurface( enemy );

//Quit SDL
SDL_Quit();
}

Foo::Foo()
{
//Initialize movement variables
box.x = 0;
box.y = 250;
box.w = FOO_WIDTH;
box.h = FOO_HEIGHT;

xVel = 0;
yVel = 0;

//Initialize animation variables
frame = 0;
status = FOO_RIGHT;
}

Enemy::Enemy()
{
musuh.x = 100;
musuh.y = 200;
musuh.w = NANDA_WIDTH;
musuh.h = NANDA_HEIGHT;

xVel = 0;
yVel = 0;

frame = 1;
status = NANDA_RIGHT;
}

void Foo::handle_events()
{
//If a key was pressed
if( event.type == SDL_KEYDOWN )
{
//Set the velocity
switch( event.key.keysym.sym )
{
case SDLK_RIGHT: xVel += FOO_WIDTH / 2; break;
case SDLK_LEFT: xVel -= FOO_WIDTH / 2; break;
case SDLK_UP: yVel -= FOO_HEIGHT / 2; break;
case SDLK_DOWN: yVel += FOO_HEIGHT / 2; break;
}
}
//If a key was released
else if( event.type == SDL_KEYUP )
{
//Set the velocity
switch( event.key.keysym.sym )
{
case SDLK_RIGHT: xVel -= FOO_WIDTH / 2; break;
case SDLK_LEFT: xVel += FOO_WIDTH / 2; break;
case SDLK_UP: yVel += FOO_HEIGHT / 2; break;
case SDLK_DOWN: yVel -= FOO_HEIGHT / 2; break;
}
}
}

void Foo::move()
{
//Move
box.x += xVel;

//Keep the stick figure in bounds
if( ( box.x < 0 ) || ( box.x + FOO_HEIGHT > LEVEL_HEIGHT ) ||
( check_collision( box, wall ) ) || ( check_collision( box, tree ) ) ||
( check_collision( box, treef ) ) || ( check_collision( box, treeb ) ) )
{
box.x -= xVel;
}

box.y += yVel;

if( ( box.y < 0 ) || ( box.y + FOO_HEIGHT > LEVEL_HEIGHT ) ||
( check_collision( box, wall ) ) || ( check_collision( box, tree ) ) ||
( check_collision( box, treef ) ) || ( check_collision( box, treeb ) ) )
{
box.y -= yVel;
}
}

void Enemy::move()
{
musuh.x += xVel;

if(musuh.x == 100 AND musuh.y == 200)
{
xVel += NANDA_WIDTH / 2;
}

if(musuh.x == 400 AND musuh.y == 200)
{
xVel -= NANDA_WIDTH / 2;
}
}

void Foo::show()
{
//If Foo is moving left
if( xVel < 0 )
{
//Set the animation to left
status = FOO_LEFT;

//Move to the next frame in the animation
frame++;
}
//If Foo is moving right
else if( xVel > 0 )
{
//Set the animation to right
status = FOO_RIGHT;

//Move to the next frame in the animation
frame++;
}

else if(yVel > 0)
{
status = FOO_FRONT;

frame++;
}

else if(yVel < 0)
{
status = FOO_BACK;

frame++;
}
//If Foo standing
else
{
//Restart the animation
frame = 0;
}

//Loop the animation
if( frame >= 2 )
{
frame = 0;
}

//Show the stick figure
if( status == FOO_RIGHT )
{
apply_surface( box.x - camera.x, box.y - camera.y, foo, screen, &clipsRight[ frame ] );
}
else if( status == FOO_LEFT )
{
apply_surface( box.x - camera.x, box.y - camera.y, foo, screen, &clipsLeft[ frame ] );
}
else if( status == FOO_FRONT )
{
apply_surface( box.x - camera.x, box.y - camera.y, foo, screen, &clipsFront[ frame ] );
}
else if( status == FOO_BACK )
{
apply_surface( box.x - camera.x, box.y - camera.y, foo, screen, &clipsBack[ frame ] );
}
}

void Enemy::show()
{
if( xVel < 0 )
{
status = NANDA_LEFT;

frame++;
}

else if( xVel > 0 )
{
status = NANDA_RIGHT;

frame++;
}

if( frame >= 2 )
{
frame = 0;
}

if( status == NANDA_RIGHT )
{
apply_surface( musuh.x, musuh.y, enemy, screen, &clipsRight[ frame ] );
}
else if( status == NANDA_LEFT )
{
apply_surface( musuh.x, musuh.y, enemy, screen, &clipsLeft[ frame ] );
}
}

void Foo::set_camera()
{
camera.x = (box.x + FOO_WIDTH/2) - SCREEN_WIDTH/2;
camera.y = (box.y + FOO_HEIGHT/2) - SCREEN_HEIGHT/2;

//Keep the camera in bounds.
if( camera.x < 0 )
{
camera.x = 0;
}
if( camera.y < 0 )
{
camera.y = 0;
}
if( camera.x > LEVEL_WIDTH - camera.w )
{
camera.x = LEVEL_WIDTH - camera.w;
}
if( camera.y > LEVEL_HEIGHT - camera.h )
{
camera.y = LEVEL_HEIGHT - camera.h;
}
}

Timer::Timer()
{
//Initialize the variables
startTicks = 0;
pausedTicks = 0;
paused = false;
started = false;
}

void Timer::start()
{
//Start the timer
started = true;

//Unpause the timer
paused = false;

//Get the current clock time
startTicks = SDL_GetTicks();
}

void Timer::stop()
{
//Stop the timer
started = false;

//Unpause the timer
paused = false;
}

void Timer::pause()
{
//If the timer is running and isn't already paused
if( ( started == true ) && ( paused == false ) )
{
//Pause the timer
paused = true;

//Calculate the paused ticks
pausedTicks = SDL_GetTicks() - startTicks;
}
}

void Timer::unpause()
{
//If the timer is paused
if( paused == true )
{
//Unpause the timer
paused = false;

//Reset the starting ticks
startTicks = SDL_GetTicks() - pausedTicks;

//Reset the paused ticks
pausedTicks = 0;
}
}

int Timer::get_ticks()
{
//If the timer is running
if( started == true )
{
//If the timer is paused
if( paused == true )
{
//Return the number of ticks when the timer was paused
return pausedTicks;
}
else
{
//Return the current time minus the start time
return SDL_GetTicks() - startTicks;
}
}

//If the timer isn't running
return 0;
}

bool Timer::is_started()
{
return started;
}

bool Timer::is_paused()
{
return paused;
}

int main( int argc, char* args[] )
{
//Quit flag
bool quit = false;

//Initialize
if( init() == false )
{
return 1;
}

//Load the files
if( load_files() == false )
{
return 1;
}

wall.x = 800;
wall.y = 30;
wall.w = 60;
wall.h = 200;

tree.x = 400;
tree.y = 50;
tree.w = 60;
tree.h = 200;

treef.x = 1400;
treef.y = 200;
treef.w = 120;
treef.h = 500;

treeb.x = 1500;
treeb.y = 500;
treeb.w = 400;
treeb.h = 150;

//Clip the sprite sheet
set_clips();

//The frame rate regulator
Timer fps;

//The stick figure
Foo walk;

Enemy lawan;

//While the user hasn't quit
while( quit == false )
{
//Start the frame timer
fps.start();

//While there's events to handle
while( SDL_PollEvent( &event ) )
{
//Handle events for the stick figure
walk.handle_events();

//If the user has Xed out the window
if( event.type == SDL_QUIT )
{
//Quit the program
quit = true;
}
}

//Move the stick figure
walk.move();
lawan.move();

walk.set_camera();

//Fill the screen white
SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) );

//Show the stick figure on the screen
apply_surface( 0, 0, background, screen, &camera );

walk.show();
lawan.show();

//Update the screen
if( SDL_Flip( screen ) == -1 )
{
return 1;
}

//Cap the frame rate
if( fps.get_ticks() < 500 / FRAMES_PER_SECOND )
{
SDL_Delay( ( 700 / FRAMES_PER_SECOND ) - fps.get_ticks() );
}
}

//Clean up
clean_up();

return 0;
}




there are two class : Foo class for player character and Enemy class for enemy character.look at int main section,i am not set camera function on enemy class but why the enemy character always follow the player scrolling camera,strange.how to fixed it?

[edit: broke a couple of really long lines to make it fit in browser - IF]

[Edited by - InnocuousFox on December 1, 2010 12:13:39 PM]

Share this post


Link to post
Share on other sites
If you think you have an AI problem with SDL, there's something very wrong with how you are thinking about your program. SDL is a library that allows access to the hardware, AI is something that deals with the logic of your game, and the two of them should never be in the same sentence. You should have a game state that is independent of the particulars of how you render your world, and the AI should only have to deal with that.

I was too lazy to read your question when you posted it on the Graphics Programming and Theory forum, and I can't be bother reading it now either.

Share this post


Link to post
Share on other sites
frankly i don't get with your meaning

yes i know SDL library and i prefer like it rather than OpenGL because it's relatively easy to use
what do you mean with game state.shall i use this to make AI movement?

Share this post


Link to post
Share on other sites
Quote:
Original post by Alvin31
frankly i don't get with your meaning
I think what he's getting at is that SDL and AI really have nothing to do with one another. If it really is an AI-related problem you have, then it's not an SDL expert that you need.

That said, from reading your post it sounds like more of a rendering and/or program logic problem than an AI problem; if that is the case, this probably isn't the best forum for the question.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this