Hi. i need some help with this game i want to simulate with c++ (with the graphics.h library). i want to make a replica of Pacman. i already built the map, but now i got stuck:
#1. i don't know how can i avoid the walls/obstacles (i have a blurry idea of an array (but i don't know if the array will suite the map i've drawn);
#2. i can't get the arrow input. for ex. if the user presses the right arrow, the appropriate drawing function will be called...

i've attached the code too
ty

Attachments
#include<graphics.h>
#include<conio.h>
#include<iostream.h>
#include<dos.h> noecho()

void map(){
        //setlinestyle(0, 0, 3);
	line(310, 202, 330, 202);
	setcolor(1);
	setbkcolor(0);
	//setlinestyle(0, 1, 3);
	setfillstyle(1, 1);
	//liniile groase - desenare;

	line(470, 205, 470, 165);//dreapta mid
	line(470, 165, 545, 165);//dreapta
	line(545, 165, 545, 30);
	line(545, 30, 330, 30);//dreapta sus
	line(330, 30, 330, 84);
	line(330, 84, 310, 84);
	line(310, 84, 310, 30);
	line(310, 30, 95, 30);//stanga sus
	line(95, 30, 95, 165);//stanga
	line(95, 165, 170, 165);//stanga mid
	line(170, 165, 170, 235);
	line(170, 235, 170, 275);
	line(170, 275, 95, 275);
	line(95, 275, 95, 325);
	line(95, 325, 115, 325);
	line(115, 325, 115, 340);
	line(115, 340, 95, 340);
	line(95, 340, 95, 400);
	line(95, 400, 545, 400);//jos
	line(545, 400, 545, 340);
	line(545, 340, 525, 340);
	line(525, 340, 525, 325);
	line(525, 325, 545, 325);
	line(545, 325, 545, 275);//dreapta
	line(545, 275, 470, 275);
	line(470, 275, 470, 235);
	line(470, 235, 470, 205);//dreapta mid

	//T's
	//#1(sus)-dreapta
	line(445, 205, 445, 110);//1
	line(445, 110, 430, 110);//2-lateral(sus)
	line(430, 110, 430, 165);//3
	line(445, 205, 430, 205);//4-lateral(jos)
	line(430, 205, 430, 180);//5
	line(355, 165, 355, 180);//6-exterior(stanga)
	line(355, 165, 430, 165);//7-exterior(sus)
	line(355, 180, 430, 180);//8-exterior(jos)
	floodfill(440, 200, 1);
	//#2-centru
	line(405, 110, 235, 110);//1-sus
	line(405, 110, 405, 136);//2-lateral(dreapta)
	line(405, 136, 330, 136);//3-interior(dreapta)
	line(330, 136, 330, 180);
	line(330, 180, 310, 180);//5-exterior(jos)
	line(310, 180, 310, 136);
	line(310, 136, 235, 136);
	line(235, 136, 235, 110);//8-lateral(stanga)
	floodfill(400, 115, 1);
	//#3-stanga
	line(195, 205, 210, 205);//1-exterior(jos)
	line(195, 205, 195, 110);//2-lateral(stanga)
	line(195, 110, 210, 110);//3-exterior(sus)
	line(210, 110, 210, 165);//4-interior
	line(210, 165, 285, 165);
	line(285, 165, 285, 180);
	line(285, 180, 210, 180);
	line(210, 180, 210, 205);//8-interior(dreapta-jos)
	floodfill(200, 200, 1);
	//#4(jos)-centru
	line(235, 275, 235, 260);//#1-stanga
	line(235, 260, 405, 260);//#2-sus
	line(405, 260, 405, 275);//#3-dreapta
	line(405, 275, 325, 275);
	line(325, 275, 325, 305);//#5-centru-dreapta
	line(325, 305, 315, 305);
	line(315, 305, 315, 275);
	line(235, 275, 315, 275);
	floodfill(300, 270, 1);
	//#5(jos)-centru
	line(235, 345, 235, 335);//#1-stanga
	line(235, 335, 405, 335);
	line(405, 335, 405, 345);
	line(405, 345, 325, 345);
	line(325, 345, 325, 370);
	line(325, 370, 315, 370);
	line(315, 370, 315, 345);
	line(315, 345, 235, 345);
	floodfill(300, 340, 1);
	//#6(jos)-stanga
	line(195, 335, 210, 335);
	line(210, 335, 210, 370);
	line(210, 370, 290, 370);
	line(290, 370, 290, 380);
	line(290, 380, 120, 380);
	line(120, 380, 120, 370);
	line(120, 370, 195, 370);
	line(195, 370, 195, 335);
	floodfill(200, 340, 1);
	//#7(jos) - dreapta
	line(430, 335, 445, 335);
	line(445, 335, 445, 370);
	line(445, 370, 525, 370);
	line(525, 370, 525, 380);
	line(525, 380, 350, 380);
	line(350, 380, 350, 370);
	line(350, 370, 430, 370);
	line(430, 370, 430, 335);
	floodfill(438, 340, 1);











	setlinestyle(0, 1, 1);
	//liniile subtiri - desenare

	line(475, 200, 475, 170);
	line(475, 170, 550, 170);
	line(550, 170, 550, 25);//sus
	line(550, 25, 90, 25);
	line(90, 25, 90, 170);
	line(90, 170, 165, 170);
	line(165, 170, 165, 240);//stanga
	line(165, 240, 165, 270);
	line(165, 270, 90, 270);
	line(90, 270, 90, 405);
	line(90, 405, 550, 405);//jos
	line(550, 405, 550, 270);//dreapta
	line(550, 270, 475, 270);
	line(475, 270, 475, 240);
	line(475, 240, 475, 200);

	//

	//setlinestyle(0, 1, 3);
	rectangle(470, 56, 520, 84);
		floodfill(475, 60, 1);
	rectangle(470, 110, 520, 136);
		floodfill(475, 120, 1);
	rectangle(355, 56, 444, 84);
		floodfill(360, 60, 1);
	rectangle(195, 56, 285, 84);
		floodfill(200, 60, 1);
	rectangle(120, 56, 170, 84);
		floodfill(130, 60, 1);
	rectangle(120, 110, 170, 136);
		floodfill(130, 120, 1);

	//dreptunghiuri - mid
	rectangle(430, 235, 445, 275);//dreapta
		floodfill(435, 240, 1);
	rectangle(195, 235, 210, 275);//stanga
        	floodfill(200, 250, 1);
	//jos
	rectangle(195, 300, 285, 310);
		floodfill(200, 305, 1);
	rectangle(355, 300, 445, 310);
		floodfill(370, 305, 1);
	//centru
	rectangle(395, 235, 245, 205);



	//dreptunghiuri - jos
	//#1-dreapta
	line(470, 295, 520, 295);
	line(520, 295, 520, 305);
	line(520, 305, 500, 305);
	line(500, 305, 500, 340);
	line(500, 340, 470, 340);
	line(470, 340, 470, 295);
        floodfill(480, 300, 1);
	//#2-stanga
	line(170, 295, 120, 295);
	line(120, 295, 120, 305);
	line(120, 305, 140, 305);
	line(140, 305, 140, 340);
	line(140, 340, 170, 340);
	line(170, 340, 170, 295);
	floodfill(160, 300, 1);


	//setfillstyle(1, YELLOW);
	//pieslice(184, 260, 315, 35, 12);



}

void dreapta(int x, int y, int sta, int end, int r){


	do{


	map();
	setcolor(YELLOW);
	setfillstyle(1, YELLOW);
	pieslice(x, y, sta, end, r);
	x+=5;
	if (x>=639) x=0;
	delay(150);
	getch();
	cleardevice();
	}while (!kbhit());
}




void main(){

	int gd=DETECT, gm, input;
	initgraph(&gd, &gm,"c:\\borlandc\\bgi");

	//dreapta(108, 43, 325, 35, 11);


	//if ((input==getch())==27) do{
	//dreapta(105, 43, 325, 35, 11);
	  //	}while(input!='27');
	    map();
	    getch();




	closegraph();




}

How is your array defined? How does it reflect your map?

well that's what i'm trying to find out... because at this moment i really don't know how to do it. i'm guessing that it'll have to be something like this:
-1 where is an obstacle
0 where is a clear path
1 where i'll fill the empty path with those little squares you have to collect while moving around the map (and evetualy, 1 will turn to 0)

-but i have no idea how to implement those coordinates into an array-

Create a two dimensional array for the level (0 = empty block, 1 = wall, 2 = pacman, 3 = enemy) and then create a two dimensional array for the bit's that pacman eats (1 for exists, 2 = eaten)

If you check the block that you are trying to move pacman into before you move you can deal with walls, enemies and things to eat all in one go.

Make pacman have a direction. 1 = up, 2 = right, 3 = down, 4 = left.

based on direction check what pacman is trying to move into...

something like (c++ is not my language so it might be inperfect)

If (PacDir == 1)
{
if (LevelArray[PacPosX, PacPosY - 1] == 1)
{
// A wall coant move
}
elseif (LevelArray[PacPosX, PacPosY- 1] == 3)
{
// Hit an enemy!
}
elseif (LevelArray[PacPosX, PacPosY] == 0)
{
// empty block, move pacman and check to see if the block has a thing to eat
PacPosY--;
}
}

Hope that helps, you can check out my ISO3D pacman game here : http://www.qb64.net/forum/index.php?topic=2903.msg25520#msg25520

yup... that's right about what i was thinking too... and i think i discovered my main problem with my project (and being unable to build the array): it's the map, it's filled with irregular forms and this makes me really difficult for writing it...
if i don't get this done until tomorrow, i think i'll empty all the map and fill it only with some squares... this way writting the 2d array would be easier...

can anyone let me know if what i'm doing here (the collision checking) it's ok??
the code looks something like this:

#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77

void right(int &x, int &y, int sta, int end, int r){
do{

map();
	setcolor(YELLOW);
	setfillstyle(1, YELLOW);
	pieslice(x, y, sta, end, r);
	x+=5;
	delay(100);
	cleardevice();
	}while (!kbhit());  //i need to know over here too what to modify
}

do{
		
		for(i=1; i<=21; i++){
		for(j=1; j<=25; j++)
		 input=getch();
		 if (input==RIGHT)
				if(a[i][j+1]==0) right(i*20+5, j*20+95, 100, 100, r);									      //else - do nothing, it's a wall
				if (input==LEFT)
				if(a[i][j-1])==0) left(
				.......//and so on
		
		}while(input!=27); //stop when ESC is pressed

can anyone tell me how can i modify this drawing function:

void right(int& x, int y, int sta, int end, int r){


	do{


	map();
	setcolor(YELLOW);
	setfillstyle(1, YELLOW);
	pieslice(x, y, sta, end, r);
	x+=5;
	delay(100);
	cleardevice();
	}while (!kbhit());  //i need to know over here what to modify
}

so that in the main program:

do{
	input=getch();
	
		if (input==RIGHT && a[pozx(xi)][pozy(yi)]==0) do{
			right(xi, yi, 320, 50, r);
			
				}while(a[pozx(xi)][pozy(yi)]==0); [B][I]<----this while is never checked!!!!!!!!![/I][/B]
	
		}while(input!=27);

Edited 5 Years Ago by chiste91: *bad spelling of a word

can anyone let me know if what i'm doing here (the collision checking) it's ok??
the code looks something like this:

#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77

void right(int &x, int &y, int sta, int end, int r){
do{

map();
	setcolor(YELLOW);
	setfillstyle(1, YELLOW);
	pieslice(x, y, sta, end, r);
	x+=5;
	delay(100);
	cleardevice();
	}while (!kbhit());  //i need to know over here too what to modify
}

do{
		
		for(i=1; i<=21; i++){
		for(j=1; j<=25; j++)
		 input=getch();
		 if (input==RIGHT)
				if(a[i][j+1]==0) right(i*20+5, j*20+95, 100, 100, r);									      //else - do nothing, it's a wall
				if (input==LEFT)
				if(a[i][j-1])==0) left(
				.......//and so on
		
		}while(input!=27); //stop when ESC is pressed

Not really.
You don't need 2 loops. One will suffice. Inside that loop:

If kbhit() returns TRUE
   get a character (getch())
   if character = '\0'  -- this will indicate a function key has been pressed
      get a character
      set up a switch on the character
         case of UP,DOWN,LEFT,RIGHT - process the direction key
      endswitch
   else
      process a non-function key
   endif
endif
do{
			if (kbhit()!='\0') input=getch(); //function key
			if (input=='\0') {
					  input=getch();
	  switch (input){
	  case 1: if (input==RIGHT && a[pozx(y)][pozy(x)+1]==0)
	  do{
			if (a[pozx(y)][pozy(x)+1]==0){
			map_fill(dot);
			setcolor(YELLOW);
			setfillstyle(1, YELLOW);
			pieslice(x, y, 320, 50, r);
			x+=5;
			delay(100);
			cleardevice();}
			  }while(a[pozx(y)][pozy(x)+1]==0);
	  case 2: if (input==LEFT && a[pozx(y)][pozy(x)+1]==0)
	  do{
			if (a[pozx(y)][pozy(x)-1]==0){
			map_fill(dot);
			setcolor(YELLOW);
			setfillstyle(1, YELLOW);
			pieslice(x, y, 320, 50, r);
			x-=5;
			delay(100);
			cleardevice();}
			  }while(a[pozx(y)][pozy(x)-1]==0);
	  case 3: if (input==UP && a[pozx(y)-1][pozy(x)]==0)
	  do{
			if (a[pozx(y)][pozy(x)-1]==0){
			map_fill(dot);
			setcolor(YELLOW);
			setfillstyle(1, YELLOW);
			pieslice(x, y, 320, 50, r);
			y-=5;
			delay(100);
			cleardevice();}
			  }while(a[pozx(y)-1][pozy(x)]==0);
	  case 4: if (input==DOWN && a[pozx(y)-1][pozy(x)]==0)
	  do{
			if (a[pozx(y)+1][pozy(x)]==0){
			map_fill(dot);
			setcolor(YELLOW);
			setfillstyle(1, YELLOW);
			pieslice(x, y, 320, 50, r);
			y+=5;
			delay(100);
			cleardevice();}
				  }while(a[pozx(y)+1][pozy(x)]==0);
			}
		
		}
		}while(input!=27);

that's what i understood...
and i don't get what's with this " if character = '\0' -- this will indicate a function key has been pressed"

and i don't get what's with this " if character = '\0' -- this will indicate a function key has been pressed"

A function key is actually 2 characters. Try this code:

#include <stdio.h>
#include <conio.h>
int main()
{
    int ch;
    
    puts("Hit Keys: ");
    do
    {
        ch = getch();
        printf(" <%02X>", ch);
    }  while (ch != 0x20);
    return 0;
}

Press SPACE to exit

You should write small snippets like this to test stuff you are unsure of. It saves time and you learn a lot more by writing even more code.

i got it working :D:D, sort of...

do{
			input=getch();
 	  switch (input){
	  case RIGHT: if (a[pozx(y)][pozy(x)+1]==0)
	  do{
			if (a[pozx(y)][pozy(x)+1]==0){
			map_fill(dot);
			setcolor(YELLOW);
			setfillstyle(1, YELLOW);
			pieslice(x, y, 320, 50, r);
			x+=5;
			delay(100);
			cleardevice();}
			  }while(a[pozx(y)][pozy(x)+1]==0);
			  break;
	  case LEFT: if (a[pozx(y)][pozy(x)-1]==0)
	  do{
			if (a[pozx(y)][pozy(x)-1]==0){
			map_fill(dot);
			setcolor(YELLOW);
			setfillstyle(1, YELLOW);
			pieslice(x, y, 320, 50, r);
			x-=5;
			delay(100);
			cleardevice();}
			  }while(a[pozx(y)][pozy(x)-1]==0);
			break;
	  case UP: if (a[pozx(y)-1][pozy(x)]==0)
	  do{
			if (a[pozx(y)-1][pozy(x)]==0){
			map_fill(dot);
			setcolor(YELLOW);
			setfillstyle(1, YELLOW);
			pieslice(x, y, 320, 50, r);
			y-=5;
			delay(100);
			cleardevice();}
			  }while(a[pozx(y)-1][pozy(x)]==0);
			break;
	  case DOWN: if (a[pozx(y)+1][pozy(x)]==0)
	  do{
			if (a[pozx(y)+1][pozy(x)]==0){
			map_fill(dot);
			setcolor(YELLOW);
			setfillstyle(1, YELLOW);
			pieslice(x, y, 320, 50, r);
			y+=5;
			delay(100);
			cleardevice();}
				  }while(a[pozx(y)+1][pozy(x)]==0);
			break;
		}
		
		}while(input!=0x20);

hi, i need some advice again :|
with pacman's movement... i have managed to make it move, but not the way it should...
if i press right, it keeps moving right until it reaches a wall, no matter wheter i press another direction key, and i want to be able to change it's direction anytime i want&can... i hope i made it clear

case RIGHT: if (a[pozx(y)][pozy(x)+1]==0)
	  do{
			
			map_fill(dot);
			map();
			setcolor(YELLOW);
			setfillstyle(1, YELLOW);
			pieslice(x, y, 320, 50, r);
			x+=10;
			delay(150);
			cleardevice();
			
			}while(a[pozx(y)][pozy(x)+1]==0);
			  break;

note: it's the same for the other 3 directions;
thank you

Edited 5 Years Ago by chiste91: n/a

Sound suspiciously so that you enter loop at keydown and don't exit it at keyup.

sorry, but i don't get your point... :/

You maybe react to key going down and enter continuous loop. Exit condition of the loop does not include the event when key is going up. Result is that lifting up finger of key does not exit the loop. This is just from listening the effect of bug, debugging if this is correct is your job as you know your code best.

You maybe react to key going down and enter continuous loop. Exit condition of the loop does not include the event when key is going up. Result is that lifting up finger of key does not exit the loop. This is just from listening the effect of bug, debugging if this is correct is your job as you know your code best.

oh, you're saying the problem is that the fact that the key-event is not included in my exit condition of the loop?

@tonyjv thank you a lot :D
i almost did it...

case RIGHT: if (a[pozx(y)][pozy(x)+1]==0)
	  do{
			if (a[pozx(y)][pozy(x)-1]==0 && kbhit()) input=getch();//check if left tile is walkable, if so and the user presses LEFT, the pacman starts going that way
			if (a[pozx(y)-1][pozy(x)]==0 && kbhit()) input=getch();//UP direction checking;
			if (a[pozx(y)+1][pozy(x)]==0 && kbhit()) input=getch();//DOWN direction checking;
			map_fill(dot);
			map();
			setcolor(YELLOW);
			setfillstyle(1, YELLOW);
			pieslice(x, y, 320, 50, r);
			x+=10;
			delay(150);
			cleardevice();
			}while(a[pozx(y)][pozy(x)+1]==0 && input==RIGHT);
			  break;

but (i hope i'm not starting to get annoying), now if i press a direction key and it hits a wall it stops... and, like the actual game i'd like pacman to continue it's movement until the next key is pressed or it hits a wall...

hi again :D

almost everything is solved, except the fact that now i don't know how to implement the "ghosts"...

any indication would be useful

whooa... i'm mind blown after that article and all those strategies for ghosts...

http://gameinternals.com/post/2072558330/understanding-pac-man-ghost-behavior

i don't think i'll use any of that, my game is not that complex(i'm not trying to make it an exact replica)... my pacman game doesn't even have "power-pills"(or w/e they're called)...
but,i think i'll make 2-3 ghosts, which will have the same movement system, but place them in different parts of the map, and i'm thinking to use graphs for calculating the shortest path towards pacman(i dunno if it's a good idea or not)
i hope this will work

Simply calculating recursively distance from pacman to every square is more than enough. Only problem is that this is too tough, you must 'stupidify' the ghosts logic, say they can not 'smell' the pacman from too far.

Simply calculating recursively distance from pacman to every square is more than enough. Only problem is that this is too tough, you must 'stupidify' the ghosts logic, say they can not 'smell' the pacman from too far.

I wouldn't do anything recursively in this program. Since the goal is to stay away from the ghosts, you'll eat up all your memory recursively trying to get them to Pacman.
Each time through your process loop, calculate the direction to Pacman and move in that general direction. If there's a decision point, randomly choose the direction toward him.

I did not mean recursive movement but distance array from current location of pacman to each non-wall location. Then you can move to one closer squares to 'zoom-in'. Need to only refresh once for each movement of PacMan which is of course ages for computer (1 second at 1 GHz computer life is 1 Gs = 1000000000/60/60/24/365 = 31.7 years 1 Hz human scale)

for ghosts, i'd start with the simplest thing first, and get that working. pseudocode:

next_ghost_pos = updateGhostPos();
  while (next_ghost_pos == wall) {
      ghost_direction = rand() % 4;
      next_ghost_pos = updateGhostPos();
  }
  ghost_pos = next_ghost_pos;

This will have a ghost move in one direction until it hits a wall, then spin around randomly until it finds a direction to go (turn a corner or go back the way it came). You can add more smarts by checking if there's more than one option (where a path opens to the left or right while there's still a path straight ahead), or weight your choice of direction towards the pacman.

You will also need a check (somewhere, either for the pacman move or the ghost move, or both) for when the pacman collides with a ghost.

Hope you're having fun with this!

i think i almost found an algorithm for ghosts, but now i'm working on finding a way to alternate the moves for both player and ghosts... i mean, where i'm standing now with the code, the player moves until he hits a wall, and only then the ghost starts moving...

my code looks something like this:

do{
input=getch();
//then I have a test upon the input

switch(input)

}while(ESC key is pressed) //this is the main loop, where everything happens

and i don't know where to place the code for ghosts....
ty

You must have main loop offering one step of action for all activities going irrespective to key presses or not. In addition to recognize keydown you must also stop action on keyup. Each step should not take too long and loop should wait by sleep not busy wait.

i think i'm about to quit...i knew this part was going to be hard, but it's almost 2 days since i didn't do any progress regarding the ghosts' movement on map... the only reachable thing i managed to think, is to make ghost movement similar to pacman's, and by that i mean, to make a "switch", but instead of testing user input, to have a random(3) function (0-UP, 1-RIGHT, 2-DOWN, 3-LEFT)... and here where the problems are starting:
-if one of them pacman/ghost start moving, they'd have to wait for the other to finish it's loop until being able to move...
----------------
one of the big problems, after which i stopped developing this idea...

my mind is really scrambled regarding the main loop and how to manage all those events...

You need to do it like tonyjv is suggesting. The movements shouldn't need individual loops for each object only one main loop is needed. In english it should look kinda like this.

main loop for game starts
ex. while true

check for events here send important events to objects like pacman and ghosts
ex. w key pressed pacman.movement('w')

after events you can probably squeeze in time for collision checks here or let the objects themselves do it.
movment()
w
if hits wall or ghost do this

restart loop

This article has been dead for over six months. Start a new discussion instead.