• Advertisement
Sign in to follow this  

sdl 1.2 pacman problems

This topic is 760 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, guys, I'm making a progress with my Pacman game. I now made the map using tiles and reading from file, and I made the collision. But now I have another problem.

The problem is the following:

 

 

In the original Pacman game, as you know, when you press an arrow key to make a turn AND you can't make the turn right now ( because there are walls around you ), the game SAVES your last pressed arrow key AND after 1 or 2 seconds, when you can actually make the turn, it makes it for you, depending on the last key you pressed. See the pictures below:

 

[attachment=30361:Pac_Before.png]            [attachment=30362:Pac_After.png]

Ok, 1st step is to save the last pressed arrow key. I made an int arrow which saves the arrow keys like this:
if( SDLK_RIGHT ) { arrow = RIGHT } 

if( SDLK_LEFT ) { arrow = LEFT }   etc...

 

So now my last arrow key is saved.

Now I wrote this.

if ( hit_wall() == true )

{

   if ( arrow = RIGHT )

   {

      velocityX = SPEED_NORMAL;

      velocityY = 0;

   }
etc... for all the other key presses
So now it will change the direction later when there is a space to make the turn, BUT....

But now the problem is that the ONLY time pacman makes a turn is when there is a collision.

 

Ok, see the left picture is when Up is PRESSED.

 

[attachment=30363:pac_bugged_before.png]      [attachment=30364:pac_bugged_after.png]

 

 

So this is definitely not the solution.

 

I have the SDL_Rect get_tilebox() function which returns the tile rect, but when I actually call it, how can I check tilebox.x and tilebox.y.
I have ideas but the code is very very ugly, so I need something simple and efficient. so...as you can see by my username, I need Heelp!!!
 

( Here is a link to the original game - http://www.webpacman.com )

and here is all my code ( You want to see the pacman::movement stuff and pacman::handle_events maybe )

 
//The header files
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
#include "SDL/SDL_mixer.h"
#include <string>
#include <iostream>
 
//Screen dimensions
const int SCREEN_WIDTH = 630;
const int SCREEN_HEIGHT = 630;
const int SCREEN_BPP = 32;
 
//The frames per second
const int FRAMES_PER_SECOND = 100;
 
//Pacman stuff
const int PAC_DIAMETER = 23;
const int SPEED_NORMAL = 1;
 
//The direction status of the Pac
const int PAC_RIGHT = 1;
const int PAC_DOWN = 2;
const int PAC_LEFT = 3;
const int PAC_UP = 4;
 
//The different tile sprites
const int TILE_BLACK = 0;
const int TILE_BLUE = 1;
 
//The different TYPES of tiles
const int TILE_SPRITES = 2;
 
//Tile dimensions and number
const int TILE_WIDTH = 30;
const int TOTAL_TILES = 441;
 
SDL_Surface *screen = NULL;
SDL_Surface *tileSheet = NULL;
 
//In-game sprite surfaces
SDL_Surface *pacRight = NULL;
SDL_Surface *pacDown = NULL;
SDL_Surface *pacLeft = NULL;
SDL_Surface *pacUp = NULL;
 
//The event structure
SDL_Event event;
 
//
SDL_Rect clips[ TILE_SPRITES ];
 
//The font
TTF_Font *font = NULL;
 
//The color of the font
SDL_Color color[2] = { { 255, 255, 255 }, { 255, 0, 0 } };
 
class Tile
{
private:
    //The attributes of the tile
    SDL_Rect tilebox;
 
    //The type of tile
    int type;
 
public:
    //Initialize the variables
    Tile( int x, int y, int tileType );
 
    //Show the tile
    void show();
 
    //Get the tile type
    int get_type();
 
    //Get the collision box
    SDL_Rect get_tilebox();
 
};
 
class Pacman
{
 
private:
    //The Rect of Pacman
    SDL_Rect pacbox;
 
    //The offsets
    float offsetX;
    float offsetY;
 
    //The speed of moving
    float velocityX;
    float velocityY;
 
    //The position of pacman
    int arrow;
    int turnpac;
    int walkstatus;
    int transition;
 
 
public:
 
    //The constructor
    Pacman();
 
    //Handle input
    void handle_events();
 
    //Change the coordinates of Pacman when moving
    void movement( Tile *tiles[] );
 
    //Handles Pacman animation when walking
    void walk_anim();
 
    //\ Pacman on screen
    void show();
 
};
 
bool set_tiles( Tile *tiles[] )
{
    //The tile offsets
    int x = 0, y = 0;
 
    //Opening the text file with the 0s and 1s
    FILE* filePointer;
    filePointer = fopen("Pics/pacmanWholemap.txt", "rt");
 
    if( filePointer == NULL )
    {
        return false;
    }
 
    int t = 0, counter = 0, tileType = 0;
 
    //While going through all the characters...
    while( ( t = getc( filePointer ) )!= EOF )
        //If it sees zero, put 1st tile
    {
        if( t == '0' || t == '1' )
        {
            //Make the type of the tile = 0
            tileType = t - '0';
            tiles[ counter ] = new Tile ( x, y, tileType );
            counter++;
            if( counter == TOTAL_TILES )
            {
                break;
            }
 
            //Move to the next tile coordinates
            x += TILE_WIDTH;
 
            //If you are out of screen
            if( x >= 21*TILE_WIDTH )
            {
                x = 0;
                y += TILE_WIDTH;
            }
 
            if( y >= 21*TILE_WIDTH )
            {
                return true;
            }
        }
    }
}
 
class Timer
{
    private:
    //The clock time when the timer started
    int startTicks;
 
    //The timer status
    bool started;
 
    public:
    //Initializes variables
    Timer();
 
    //The various clock actions
    void start();
    void stop();
 
    //Gets the timer's time
    int get_ticks();
 
    //Checks the status of the timer
    bool is_started();
};
 
Timer::Timer()
{
    //Initialize the variables
    startTicks = 0;
    started = false;
}
 
void Timer::start()
{
    //Start the timer
    started = true;
 
    //Get the current clock time
    startTicks = SDL_GetTicks();
}
 
void Timer::stop()
{
    //Stop the timer
    started = false;
}
 
int Timer::get_ticks()
{
    //If the timer is running
    if( started == true )
    {
        //Return the current time minus the start time
        return SDL_GetTicks() - startTicks;
    }
 
    //If the timer isn't running
    return 0;
}
 
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 loading the screen
    if( screen == NULL )
    {
        return false;
    }
 
    //Initialize SDL_ttf
    if( TTF_Init() == -1 )
    {
        return false;
    }
 
    //Set the window caption
    SDL_WM_SetCaption( "Pacman", NULL );
 
    //If everything initialized fine
    return true;
}
 
SDL_Surface * load_image( std::string filename )
{
    //The image that's loaded
    SDL_Surface* loadedImage = NULL;
 
    //The optimized surface
    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 )
        {
            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0, 0 ) );
        }
    }
    //Return the optimized surface
    return optimizedImage;
}
 
bool load_files()
{
    //Load the font
    font = TTF_OpenFont( "lazy.ttf", 38 );
 
    //Load the background
 
    //Load the tiles sheet
    tileSheet = load_image( "Pics/blue red.png");
 
    //Load the pacman images
    pacRight = load_image( "Pics/pac_right.png" );
    pacDown = load_image( "Pics/pac_down.png" );
    pacLeft = load_image( "Pics/pac_left.png" );
    pacUp = load_image( "Pics/pac_up.png" );
 
    //If there was a problem in loading the sprites
 
 
    if( pacRight == NULL || pacDown == NULL || pacLeft == NULL || pacUp == NULL )
    {
        return false;
    }
 
    if( tileSheet == NULL )
    {
        return false;
    }
 
    //If everything loaded fine
    return true;
}
 
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;
}
 
void clip_tiles()
{
    //Clip the sprite sheet
    clips[ TILE_BLACK ].x = 0;
    clips[ TILE_BLACK ].y = 0;
    clips[ TILE_BLACK ].w = TILE_WIDTH;
    clips[ TILE_BLACK ].h = TILE_WIDTH;
 
    clips[ TILE_BLUE ].x = TILE_WIDTH;
    clips[ TILE_BLUE ].y = 0;
    clips[ TILE_BLUE ].w = TILE_WIDTH;
    clips[ TILE_BLUE ].h = TILE_WIDTH;
 
}
 
bool hit_wall( SDL_Rect box, Tile *tiles[] )
{
    for( int t = 0; t < TOTAL_TILES; t++ )
    {
        if( tiles[ t ]->get_type() == TILE_BLUE )
        {
            if( check_collision( box, tiles[ t ]->get_tilebox() ) )
            {
                return true;
            }
        }
    }
    //If no collision was found
    return false;
}
 
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 close_all( Tile *tiles[] )
void close_all( Tile *tiles[] )
{
    //Free the pacman surfaces
    SDL_FreeSurface( pacRight );
    SDL_FreeSurface( pacDown );
    SDL_FreeSurface( pacLeft );
    SDL_FreeSurface( pacUp );
 
    //Free the background and tiles surfaces
    SDL_FreeSurface( tileSheet );
 
    //Free the tiles
    for( int t = 0; t < TOTAL_TILES; t++ )
    {
        delete tiles[ t ];
    }
 
    //Close Font
    TTF_CloseFont( font );
 
    //Quit SDL_ttf
    TTF_Quit();
 
    //Quit SDL
    SDL_Quit();
 
}
 
Pacman::Pacman()
{
    //Initialize the Rect variables
    pacbox.x = 63;
    pacbox.y = 33;
    pacbox.w = PAC_DIAMETER;
    pacbox.h = PAC_DIAMETER;
 
    //Initialize movement variables
    velocityX = SPEED_NORMAL;
    velocityY = 0;
    walkstatus = PAC_RIGHT;
 
    arrow = 0;
    transition = 0;
}
 
void Pacman::handle_events()
{
    //If a key was pressed
    if( event.type == SDL_KEYDOWN )
    {
        //Set the velocity
        if( event.key.keysym.sym == SDLK_RIGHT )
        {
            arrow = PAC_RIGHT;
        }
        if( event.key.keysym.sym == SDLK_DOWN )
        {
            arrow = PAC_DOWN;
        }
 
        if( event.key.keysym.sym == SDLK_LEFT )
        {
            arrow = PAC_LEFT;
        }
 
        if( event.key.keysym.sym == SDLK_UP )
        {
            arrow = PAC_UP;
        }
    }
}
 
void Pacman::movement( Tile *tiles[] )
{
    //Move
    pacbox.x += velocityX;
    pacbox.y += velocityY;
 
    for( int t = 0; t < TOTAL_TILES; t++ )
    {
        if( tiles[ t ]->get_type() == TILE_BLACK )
        {
 
        }
    }
 
 
    //Check Pac - walls collision
    if( hit_wall( pacbox, tiles ) )
    {
        if( velocityX != 0 && velocityY == 0 )
        {
            pacbox.x -= velocityX;
        }
 
        if( velocityY != 0 && velocityX == 0 )
        {
            pacbox.y -= velocityY;
        }
 
        if( arrow == PAC_RIGHT )
        {
            velocityX = SPEED_NORMAL;
            velocityY = 0;
 
        }
 
        if( arrow == PAC_DOWN )
        {
            velocityX = 0;
            velocityY = SPEED_NORMAL;
            arrow = 0;
        }
 
        if( arrow == PAC_LEFT )
        {
            velocityX = -SPEED_NORMAL;
            velocityY = 0;
            arrow = 0;
        }
 
        if( arrow == PAC_UP )
        {
            velocityX = 0;
            velocityY = -SPEED_NORMAL;
            arrow = 0;
        }
}
 
    //Keep the Pac in bounds
    if( pacbox.x < - PAC_DIAMETER )
    {
        if( transition == 0 )
        {
            pacbox.x = SCREEN_WIDTH;
            transition ++;
        }
    }
 
    if( pacbox.x > SCREEN_WIDTH )
    {
        if( transition == 0 )
        {
            pacbox.x = -PAC_DIAMETER;
            transition ++;
        }
    }
    else
    {
        if( transition == 1 )
        {
            transition = 0;
        }
    }
 
    if( pacbox.y < 0 || pacbox.y + PAC_DIAMETER > SCREEN_HEIGHT )
    {
        pacbox.y -= velocityY;
    }
 
 
    //Check velocity and set position
    //If Pacman is moving left
    if( velocityX > 0 )
    {
        //Set the animation to left
        walkstatus = PAC_RIGHT;
    }
 
    if( velocityX < 0 )
    {
        //Set the animation to left
        walkstatus = PAC_LEFT;
    }
 
    if( velocityY < 0 )
    {
        //Set the animation to left
        walkstatus = PAC_UP;
    }
 
    if( velocityY > 0 )
    {
        //Set the animation to left
        walkstatus = PAC_DOWN;
    }
}
 
void Pacman::show()
{
    if( walkstatus == PAC_RIGHT )
    {
        apply_surface( pacbox.x, pacbox.y, pacRight, screen );
    }
 
    if( walkstatus == PAC_DOWN )
    {
        apply_surface( pacbox.x, pacbox.y, pacDown, screen );
    }
 
    if( walkstatus == PAC_LEFT )
    {
        apply_surface( pacbox.x, pacbox.y, pacLeft, screen );
    }
 
    if( walkstatus == PAC_UP )
    {
        apply_surface( pacbox.x, pacbox.y, pacUp, screen );
    }
}
 
Tile::Tile( int x, int y, int tileType )
{
    //Get the offsets
    tilebox.x = x;
    tilebox.y = y;
 
    //Set the collision box
    tilebox.w = TILE_WIDTH;
    tilebox.h = TILE_WIDTH;
 
    //Get the tile type
    type = tileType;
}
 
void Tile::show()
{
    //Show the tile
    apply_surface( tilebox.x, tilebox.y, tileSheet, screen, &clips[ type ] );
}
 
int Tile::get_type()
{
    return type;
}
 
SDL_Rect Tile::get_tilebox()
{
    return tilebox;
}
 
int main( int argc, char* args[] )
{
 
    bool quit = false;
 
    Tile *tiles[ TOTAL_TILES ];
 
    //The tiles that will be used
    for( int t = 0; t < TOTAL_TILES; t++ )
    {
        tiles[t] = NULL;
    }
 
    //Initialize the SDL stuff
    if( init() == false )
    {
        return 1;
    }
 
    //Load the files
    if( load_files() == false )
    {
        return 2;
    }
 
    //Clip the tile sheet
    clip_tiles();
 
    //Set the tiles
    set_tiles( tiles );
 
    //The timer
    Timer fps;
 
    //The pacman
    Pacman pacman1;
 
    //While the user hasn't quit
    while( quit == false )
    {
        //While there's events to handle
        while( SDL_PollEvent( &event ) )
        {
            pacman1.handle_events();
            //If the user has pressed Esc or X
            if( event.type == SDL_QUIT || event.key.keysym.sym == SDLK_ESCAPE )
            {
                //Quit the program
                quit = true;
            }
        }
 
        //Moves Pac
        pacman1.movement( tiles );
 
 
        //Apply the tiles as background
        for( int t = 0; t < TOTAL_TILES; t++ )
        {
            if( tiles[ t ] != NULL )
            {
                tiles[ t ]->show();
            }
        }
 
        //Show the Pac on the screen
        pacman1.show();
 
        //Update the screen
        if( SDL_Flip( screen ) == -1 )
        {
            return 1;
        }
 
        //Cap the frame rate
        if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
        {
            SDL_Delay( 1000 / FRAMES_PER_SECOND  - fps.get_ticks() - 7 );
        }
    }
 
    //Clean up
    close_all( tiles );
 
    return 0;
}
 
Edited by Heelp

Share this post


Link to post
Share on other sites
Advertisement

Perhaps instead of using traditional collision consider using a "rail" system and responding to directional input by setting an "intent" direction?

 

Without having looked at the code I'm guessing that your entity is experiencing a variant of the bullet-through-paper problem, where there's no frame during which he's perfectly aligned with the intersection in order to be able to make his turn.

Share this post


Link to post
Share on other sites

This is not the reason because const int NORMAL_SPEED is set to 1, so the pacman can go through every possible coordinate. The problem is that I just don't know how to say: Scan for a possible road where you can make a turn, and if there is such a road, make the turn you wanted to make earlier

Edited by Heelp

Share this post


Link to post
Share on other sites
I know there are many ways you can do these things but if I decided to do a pacman game I would have made much more use of the fact that it's a tile-based game. The way I see it pacman's movement is from the center of one tile to the center of another tile.

Each time pacman reach the center of a tile I would check to see if it is possible to start move pacman in the new direction. If not, then continue in the current direction if possible.
 
if center of tile has been reached
	if can move in new direction
		start move in new direction
	else if can move in current direction
		continue moving in current direction
	else
		stop

Note that when you check to see if it is possible to move from one tile to the next you don't need to do full-blown collision detection. If you know the coordinates of the tile you're on you can easily calculate the coordinates of the next tile and check what type it is (walkable or not).

Share this post


Link to post
Share on other sites
Store your pacman position in grid coordinates only. Animation moves pacman between grid coordinates, using interpolation to move between the centre of each grid coordinate.

At any time, you can change direction where permitted so if you're about to hit a ghost you could double back.

Collision is still checked each frame to detect eating of pills, fruit and being killed by a ghost.

I implemented a similar rail system for the crates in my puzzle game last year in C++. The crates move automatically but can have their direction changed at junctions based on player input same basically as you're trying to do here.

Let me know if this helps!

Share this post


Link to post
Share on other sites

In the original game there was a little more to the controller then what has been presented here.  One of my AI projects in collage was to recreate the AI of pac-man.  For those interested here is the link I found on the article I used to research the game:

 

http://www.gamasutra.com/view/feature/132330/the_pacman_dossier.php

 

Now then if my memory serves me Pac-Man had a small advantage because he could pre-turn before the turn so that he would gain 3-4 pixels on a ghost.  This was a small advantage that many players would take advantage so their could either eat a ghost or evade one.  So just doing a simple rail detection on Pac-Man isn't fair to the player.

 

So here is how I did it with my project.  I create a grid in the game so that Pac-Man could wonder the map and hit collisions.  Once I had the grid made it was a matter of either using an A* algorithm to create a generic path from where I was to the direction I wanted to turn.  The hard part is finding the next square in the direction you want to turn but this was done by getting the row or column of the direction I wanted to move.  Then just moving in the same velocity of Pac-Man to find the next grid path.  Once you calculate the path it should be easy for the game to handle the animation and the turn properly.  This is more of a predictive algorithm idea instead of a reactive.  If you want some code example let me know I'll try and dig up my old project.

 

Also as a small optimization on my A* algorithm I only supported 4 direction to be able to move on Pac-Man and 3 on the ghosts.  According to the dossier it explains that the ghosts don't reverse their direction.

Edited by lede

Share this post


Link to post
Share on other sites

Ok guys, I finally made it after nearly 4 hours of suffering, but the problem is my CODE IS UGLY AS HELL. I can't even believe it's me who wrote this code. I saw that you wanted from me to implement some rail system and grid.... I tried, but - too hard for me......and this 'interpolation' stuff ( searched google, no idea what this is ),. So I actually made a 'for' loop that checks all the tiles, and if there is a RED tile( I can move on red tiles, walls are blue ), yeah, if there is a RED tile near my coordinates ( not too far and not too close!! ) then I check If there is a intentKey saved ( I called it 'arrow' ) and if the intention is to go on this way, go. I will post my code, if you can just skim through the code and see if you can do it in less ugly way, I'll be grateful.

void Pacman::make_turn( Tile *tiles[] )
{
    //Making a Rectangle that takes the nearest tile coordinates
    SDL_Rect roadbox;
 
    //Goes through all the tiles on the map
    for( int t = 0; t < TOTAL_TILES; t++ )
    {
        //If there is a red tile
        if( tiles[ t ]->get_type() == TILE_RED )
        {
            //Assign this tile's coordinates to SDL_Rect roadbox
            roadbox = tiles[ t ]->get_tilebox();
            
            //Checking if there is a tile above pacman
            //Check if the x coordinates are the same and if the tile is not too far
            if( roadbox.x == pacbox.x && roadbox.y >= pacbox.y - ( 4*TILE_WIDTH )/3 )
            {
                //Check if the tile is not too close
                /*If I don't make this check, the tile on which Pacman is stepping NOW
                gets into the equation and it doesn't work at all as expected */
                if( roadbox.y <= pacbox.y - ( 2*TILE_WIDTH )/3 && arrow == PAC_UP )
                {
                    //If there is a tile above Pacman, not too close, not too far, lower the Y so pacman goes up
                    velocityX = 0;
                    velocityY = -SPEED_NORMAL;
                    break;
                }
            }
 
            //Now following the same logic, I do it for all the other directions
            //If there is a tile below the Pac guy
            if( roadbox.x == pacbox.x && roadbox.y <= pacbox.y + ( 4*TILE_WIDTH )/3 )
            {
                if( roadbox.y >= pacbox.y + ( 2*TILE_WIDTH )/3 && arrow == PAC_DOWN )
                {
                    velocityX = 0;
                    velocityY = SPEED_NORMAL;
                    break;
                }
            }
 
            //If there is a tile on the left of Pacman
            if( roadbox.y == pacbox.y && roadbox.x >= pacbox.x - ( 4*TILE_WIDTH )/3 )
            {
                if( roadbox.x <= pacbox.x - ( 2*TILE_WIDTH )/3 && arrow == PAC_LEFT )
                {
                    velocityX = -SPEED_NORMAL;
                    velocityY = 0;
                }
            }
 
            if( roadbox.y == pacbox.y && roadbox.x <= pacbox.x + ( 4*TILE_WIDTH )/3 )
            {
                if( roadbox.x >= pacbox.x + ( 2*TILE_WIDTH )/3 && arrow == PAC_RIGHT )
                {
                    velocityX = SPEED_NORMAL;
                    velocityY = 0;
                }
            }
        }
    }
}
Edited by Heelp

Share this post


Link to post
Share on other sites

Yeah, and the code is speed dependant. The speed needs to be divisible by the TILE_WIDTH which is 30 or its gonna miss the if( something==something ) stuff, bullet-through-paper, as someone said earlier. BAD
Moreover, the code works only if you have pressed an arrow before the turn, if you actually haven't pressed anything, and the pacman stops at some particular wall, you can't make a turn now because you missed the if( a == b) stuff, and now you are bugged and you can't move.So it is ugly code and it also doesn't work.

Edited by Heelp

Share this post


Link to post
Share on other sites

If the player hasn't made choice by the time they reach a junction you could Make one for them. Always choose for example the next clockwise direction so there's some gameplay mechanical pattern to it.

What does original pacman do?

 

It just keeps moving in the original direction.  If Pac-Man runs into a wall then he just stops until the player presses a new direction.

Share this post


Link to post
Share on other sites

In the original Pacman, if you miss the == and the pacman is stopped by a wall, he just stops, and you can then choose where to go, and it goes.
So I actually joined my code with my 1st code with the collision stuff ( you can see it in my 1st post, on the top of this page ), and now it works, you can make an intent, but if you don't make, the Pacman collides with a wall, and my first code made it to turn wherever it wants when there is a collision with wall, so in this case : 1 ugly bad code + 1 ugly bad code == 'somehow works' code.

Edited by Heelp

Share this post


Link to post
Share on other sites

So for starters this algorithm will work but it is the brute force way of finding what you want.  The first thing you should figure out is how to access this array as a 2D array.  This doesn't mean you need a 2D array just figure out how to access it as if it were one.  I will show this in code when we get to that section.

 

So for this problem we need to define a few things that will be required to figure out how to do grid prediction.  The first thing we will need is the current position on the game field that Pac-Man is located.  Next we need to know his velocity aka the direction we are moving him in currently.  Last we will need to know the direction we will want to move or the new velocity of Pac-Man.  Once we know these things we can then do a quick search for a sqaure ID that is in the new direction.

// For now we will assume the grid is a global variable.  Now we will look for the square id
int GetNextSquare(Vector2D pacPos, Vector2D velocity, Vector2D newDir)
{
	// Create a default next id
	int nextId = -1;
	// First we need to figure out Pac-Man's current position ID
	int pacId = pacPos.x + (pacPos.y * CellsInRow);
	
	// Define some local values to control where we are going
	Vector2D pos = pacPos;
	
	// Now to start searching for the turn we want
	while(nextId == -1)
	{
		Vector2D tilePos = pos + newDir; // Should be same as tilePos.x = pos.x + newDir.x; and tilePos.y = pos.y + newDir.y;
		int tileId = tilePos.x + (tilePos.y * CellsInRow);
		if(tiles[tileId] == TILE_RED)
		{
			// We found our next tile!!!!
			nextId = tileId;
			break;
		}

		pos += velocity;// Should be the same as pos.x += velocity.x; pos.y += velocity.y;
		// Calculate new tile ID
		int posId = pos.x + (pos.y * CellsInRow);
		if(tiles[posId] == TILE_BLUE) break; // We hit a wall! Ouch that hurts
	}
	
	return nextId;
}

Please don't hate me for not optimizing this function, I wrote this more for conceptual ideas to show the idea of how to find something without having to brute force your way.

 

Now with that out of the way in this algorithm we are just going to keep moving in the direction pacman was already going and keep looking for the tile where we can change directions.  Once we have found that the tileID will be returned.  If we hit a wall -1 will be returned which means there was no intersection that we could turn in that direction.

 

Once we have the tile where we are allowed to turn we can pass that back to the animation system and let it animate pacman to the intersection where we will turn.  Hope this helps.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement