Code archives/Algorithms/Pac Man

This code has been declared by its author to be Public Domain code.

Download source code

Pac Man by Vic 3 Babes2007
Based on an old Phillips Console version that I used to love, and which was later updated on the Amiga as the excellent Deluxe Pac Man.

This is just the basic game engine. There are only 11 levels, but I have also provided a level editor which saves the levels as data statements that you can paste - see Pac Man Editor in the Code Archives. It takes - ooh - about a minute to design a level :)

I wrote this for a tutorial - but when I have time, I may actually turn it into a proper game - with the bonus items that appear in the middle like

E - X - T - R - A (collect 'em all for extra life (Mr Do?))
Slow Down
Speed Up
Glue (Freezes ghosts)
Gun (Rack-up big scores)
etc.

---

Each array element has its bits set as follows:

bit 0 - Wall North
bit 1 - Wall East
bit 2 - Wall South
bit 3 - Wall West
------------------------------------------
bit 4 - This array element is Ghost-pen if set
bit 5 - Pill in this square
bit 6 - Power-pill in this square
bit 7 - Chomped ghosts move down here to enter pen at funny x-co-ordinate
------------------------------------------
bit 8 - Pen is North from here
bit 9 - Pen is East from here
bit 10- Pen is South from here
bit 11- Pen is West from here
------------------------------------------
bit 12- Pac Man is North from here
bit 13- Pac Man is East from here
bit 14- Pac Man is South from here
bit 15- Pac Man is West from here
------------------------------------------
bit 16- Warp Square - array elements off sides of screen
bit 17- Illegal - array element is outside play area

---

The AI with regard to the path-finding feels about right - as far as the feel of the older games go - but at one point, instead of compass direction to Pac Man, I had bit 18 onwards holding a value that showed how many squares away Pac Man was. I then got the ghosts to alter the values in the path as they went along - causing ghosts behind them to split-up in a different direction - made the game a lot harder, and made the ghosts look like they knew what they were doing - however, altering the path as they went along also caused it to affect ghosts coming from other directions as well - which wasn't good. For this reason, I took it out - and tried an alternative.

I tried to get the ghosts to set bits 18-21 to indicate that they had entered this square from a certain direction, so that ghosts thinking of entering the square from the same direction might think twice about it, causing them to split-up - whereas ghosts entering from a different direction would be unaffected. Results are encouraging, but it needs more work, because you have to determine how long it should be before those bits are cleared.

---

It was taking 3 milliseconds (2 without debugging) to draw the level, including the walls and pills - so I decided to go oldskool. Since the walls never need redrawing, and only the pill that Pac Man eats needs removing, the code grabs the background before drawing the characters, and then puts it back before moving them. Now takes 0 milliseconds per frame - even with debugging on.

---

You can view path data at any time by pressing the appropriate function key - F9 shows the pre-calculated path back to the Ghost Pen for when a ghost has been chomped (done by the Editor). F10 shows the current path to Pac Man. The code then waits for a keypress - so if you press the same function key again, you can advance the path information. The path to Pac Man is updated every 16 pixels, so that the square that Pac Man is moving into gets set as the new start position for the path. The path isn't updated if Pac Man doesn't move.

You can also turn collision-detection off with F5.

---

Could have used a viewport - but too much mucking about when drawing score and stuff - so black rectangles drawn either side of level to cover characters moving off and on.

---

The final version should use banks for the levels - that way you can warp to certain levels, without having loads of Restore commands in a Select Map Number thingy. Will also use a bank for the path-finding (instead of types).

---

Can't supply the GFX, so had to create them, and take out references to animation frame numbers - oh - and it's better with sound, natch! If you want to add and play sfx, and have suitable wavs lying around, they should be played in the following functions

Dead() - you know the sound
Move_PacMan() - eat pill, and eat powerpill
Check_Collided() - eat ghost noise

Plus any others you might want to add.

The max-multiplier bonus starts at 1000. Each time you complete a level with maximum points, without dying, the max-multiplier is doubled - 2000, 4000, 8000 etc. Die, or fail to get max points, and the max-multiplier goes back to 1000. Maximum points is:

(numpills * 10) + (numpowers * 10) + ((3 ghosts) * numpowers)

Game is probably too fast if your monitor refreshes at more than 60hz - so you'll need to change it to do a flip false on a timer - but looks horribly jittery - I tried it.

I know that one of the ghosts should have rgb values of 255,0,255, but I prefer purple.

And it's good fun to play - but needs joypad support adding.
;Harlequin Software 2007

;#######################################
;REMEBER TO KEEP NUM_MAPS IN SYNC WITH ANY YOU ADD REMOVE!!
;The game loops back to level 1 when you get to the end - could write some code
;to reduce the amount of time that gosts are scared SCARED_TIME every time the levels loop

;CONSTANTS YOU CAN EASILY CHANGE
Const SCARED_TIME=350	;number of frames ghosts should be scared after Pac eats powerpill
Const NUM_LIVES=3		;drawing more than 3 will overwrite help-text on screen
Const NUM_MAPS=11		;if you also have the level editor
Const TIMEWARP=16		;number of frames ghosts spend in warp tunnel - 16 allows pac man to get an extra square
						;away from them - but if you start to put it too high, then pathfinding will be affected
						;because would need to take into account time taken to warp - YOU'LL HAVE TO ADJUST THE
						;RELEVANT CODE IN MOVE_GHOSTS() IF YOU WANT A TIMEWARP OF ZERO.  Oh, Rocky!
Const VWAIT_DELAY=10	;amount to delay before asking if vertical blank - don't put it higher
;than the time between monitor refreshes i.e.
;At 60hz refresh rate - monitor refreshes every 1000/60 = 16.666 millisecs - so 14 is probably safe - but no higher
;it helps to keep CPU usage down - Ctrl-Alt-Del - Performance Tab
;You could take the Vwait out and do a flip false on a timer if you prefer - game is probably too fast at more than 60hz

;Don't change any other constants unless modifying the code
Const DIRECTIONS$="NE S   W      P"
Const NORTH=1, EAST=2, SOUTH=4, WEST=8
Const GHOSTPEN=$10, PILL=$20, POWERPILL=$40, ABOVEPEN=$80
Const ANY_PILLS=$60

Const NOT_NORTH=$E, NOT_EAST=$D, NOT_SOUTH=$B, NOT_WEST=$7

Const NORTHEAST=$3, SOUTHEAST=$6, SOUTHWEST=$C, NORTHWEST=$9
;used for ghost pen pathfinding
Const PENSHIFT=8
Const PEN_NORTH = NORTH Shl PENSHIFT
Const PEN_EAST  = EAST  Shl PENSHIFT
Const PEN_SOUTH = SOUTH Shl PENSHIFT
Const PEN_WEST  = WEST  Shl PENSHIFT
Const PAVED=$F00, NOT_PAVED=$FF0FF

Const HORIZONTAL=EAST Or WEST, VERTICAL = NORTH Or SOUTH

Const NO_PILLS=$FFF9F
;used for Pac Man pathfinding
Const PACSHIFT=12
Const PAC_NORTH = NORTH Shl PACSHIFT
Const PAC_EAST  = EAST  Shl PACSHIFT
Const PAC_SOUTH = SOUTH Shl PACSHIFT
Const PAC_WEST  = WEST  Shl PACSHIFT
Const PACPAVED=$F000, NOT_PACPAVED=$3F0FFF

Const WARP=$10000
Const ILLEGAL=$20000
;used in do_paths()
Const NORTHorPACPAVEDorILLEGAL = NORTH Or PACPAVED Or ILLEGAL
Const EASTorPACPAVEDorILLEGAL  = EAST Or PACPAVED Or ILLEGAL
Const SOUTHorPACPAVEDorILLEGAL = SOUTH Or PACPAVED Or ILLEGAL
Const WESTorPACPAVEDorILLEGAL  = WEST Or PACPAVED Or ILLEGAL
;bits for splitting up
Const SPLITSHIFT=18
Const SPLIT_NORTH = NORTH Shl SPLITSHIFT
Const SPLIT_EAST  = EAST  Shl SPLITSHIFT
Const SPLIT_SOUTH = SOUTH Shl SPLITSHIFT
Const SPLIT_WEST  = WEST  Shl SPLITSHIFT
Const SPLIT_PAVED = $3C0000, NOT_PACSPLITPAVED=$30FFF

Const RIGHTARROW=205, LEFTARROW=203, UPARROW=200, DOWNARROW=208
Const F5=63, F9=67, F10=68, ENTER=28

Const PACSTARTX=176, PACSTARTY=160
Const STATIC=0

;ghost states
Const SCARED=1, NORMAL=2, PENNED=4, CHOMPED=$10

Const QUITTED=1, DIED=2, COMPLETED=4, ESCAPED=8, EXITMAINLOOP=$F, ESCAPEHIT=9

Dim level(11,9)
;pacx and pacy are screen co-ordinates - px and py are array co-ordinates that get calculated
;as soon as pacx or pacy change becasue they are used in so many places - better than using px
;every time we need the array position - which is quite a lot
Global pacx, pacy, px, py, pacdir, pacframe, mapnum
Global lives, score, oldscore, ghostschomped, bonus
Global wallcolour, framecount, action
Global numpills, numpowers, leveltotal, levelmax, maxmultiplier
Global staticcount
Global show_paths, collisionoff
Global titletext$, titles

AppTitle "Pac Man"
Graphics 384,320

Global pacman=CreateImage(22,22)
Global spooks=CreateImage(22,22,4)
Global Hwalls=CreateImage(26,4,6)
Global Vwalls=CreateImage(4,26,6)
Global eyes=CreateImage(6,6)
Global pillpics=CreateImage(8,8,8)
Global bg=CreateImage(22,22,3)
Global pacbg=CreateImage(22,22)
Global cover=CreateImage(32,23)
Global scoreboard=CreateImage(150,28)

HandleImage pacman,-5,-5
HandleImage pacbg,-5,-5
HandleImage spooks,-5,-5
HandleImage bg,-5,-5

Type square	;used for flood-fill pathfinding
	Field x, y
End Type

Type ghost
	Field x, y, direction, state, frame, num, xadd, yadd
	Field safe, chompcount, warpcount, scarecount, pencount
	Field warping
End Type

setup_ghosts()
create_tiles()
SetBuffer BackBuffer()
wallcolour=-1: mapnum=1
Repeat
	Cls
	action=False
	Restore titlescreen
	For titles=0 To 17
		If titles=7 Then Color 255,255,0
		Read titletext$
		Text 192*(titles<9),16+(titles Shl 4),titletext$,titles<9,False
	Next
	DrawBlock scoreboard,0,0
	Flip
	Color 255,255,255
	FlushKeys()
	Repeat
		Delay 1
		If KeyHit(QUITTED) Then action=QUITTED
	Until KeyHit(ENTER) Or action
	If action<>QUITTED Then new_game()
	While ((action And ESCAPEHIT)=False) And (lives>0)
		new_level()
		Delay 1000
		Repeat
			If framecount<15 Then framecount=framecount+1 Else framecount=0
			If KeyHit(F10) Then show_paths=1
			If KeyHit(F9) Then show_paths=2
			move_pacman()
			move_ghosts()
			If Not(collisionoff) Then check_collided()
			draw_game()
			If KeyHit(QUITTED) Then action=ESCAPED
			If KeyHit(F5) Then collisionoff=Not(collisionoff)
		Until action And EXITMAINLOOP
		If action=DIED
			dead()
		Else
			If action=COMPLETED
				score=score+leveltotal
				score=score+(500 * lives)
				If leveltotal=levelmax
					score=score+(1000 Shl maxmultiplier)
					maxmultiplier=maxmultiplier+1
				Else
					maxmultiplier=0
				EndIf
			EndIf
		EndIf
	Wend
Until action=QUITTED
End
;####################################
Function check_collided()
If action=COMPLETED Then Return
	For ghosts.ghost=Each ghost
		If RectsOverlap(pacx+9,pacy+9,14,14,ghosts\x+9,ghosts\y+9,14,14)
			Select ghosts\state
				Case SCARED
					ghostschomped=ghostschomped+1
					leveltotal=leveltotal+(100 Shl ghostschomped)
					If ghostschomped=3 Then ghostschomped=0
					ghosts\state=CHOMPED
					ghosts\x=ghosts\x And $FFC	;align to 4 pixels for new movement rate
					ghosts\y=ghosts\y And $FFC
					ghosts\scarecount=0
					ghosts\xadd=4
					ghosts\yadd=4
					ghosts\safe=True
					If ghosts\warping
						ghosts\warping=False
						ghosts\warpcount=0
					EndIf
				Case NORMAL
					If ghosts\warping=False Then action=DIED
			End Select
		EndIf
	Next
Return
End Function
;####################################
Function create_tiles()
Local r, g, b, index
SetBuffer ImageBuffer(pacman)
	Color 255,255,0
	Oval 0,0,22,22
Restore colours
For index=0 To 3
	Read r, g, b
	SetBuffer ImageBuffer(spooks,index)
	Color r, g, b
	Oval 0,0,22,22
	Rect 0,11,22,11
Next
	Color 0,8,0
	Oval 2,2,18,18
	Rect 2,11,18,9
For index=0 To 5
	Read r,g,b
	SetBuffer ImageBuffer(Hwalls,index)
	ClsColor r,g,b
	Cls
	Color r*1.5,g*1.5,b*1.5
	Line 0,2,25,2
	Color r*2,g*2,b*2
	Line 0,1,25,1
	SetBuffer ImageBuffer(Vwalls,index)
	ClsColor r,g,b
	Cls
	Color r*1.5,g*1.5,b*1.5
	Line 1,0,1,25
	Color r*2,g*2,b*2
	Line 2,0,2,25
	SetBuffer ImageBuffer(pillpics,index)
	Color r,g,b
	Oval 0,0,8,8
	Color r*1.5,g*1.5,b*1.5
	Oval 1,1,6,6
	Color r*2,g*2,b*2
	Rect 4,2,2,2
	WritePixel 5,2,$FFFFFF
Next
SetBuffer ImageBuffer(pillpics,6)
	Color 255,255,255
	Oval 2,2,4,4
SetBuffer ImageBuffer(pillpics,7)
	Color 255,255,0
	Oval 0,0,8,8
SetBuffer ImageBuffer(eyes)
	Color 255,255,255
	Oval 0,0,6,6
	Color 0,8,0
	Rect 2,2,2,2
SetBuffer ImageBuffer(scoreboard)
	Color 0,255,0
Return
End Function
;####################################
Function dead()
	Delay 500
	;PlaySound(diedsnd)
	draw_walls()
	Flip False
	DrawImage pacman,pacx,pacy
	For framecount=1 To 11
		DrawBlockRect pacbg,pacx,pacy,0,0,22,framecount Shl 1
		Flip False
		Delay 100
	Next
	score=score+leveltotal
	lives=lives-1: leveltotal=0: maxmultiplier=0
Return
End Function
;####################################
Function do_paths()
Local x, y, numsquares, remove
	;remove=NOT_PACSPLITPAVED Else remove=NOT_PACPAVED
	For y=1 To 8
		For x=0 To 11
			level(x,y)=level(x,y) And NOT_PACPAVED	;lose old path info
		Next
	Next
	;When pacman is half-in one square and half in another - change the start position
	;of the path to the tile he is moving into - this function called every 16 pixels moved
	Select pacdir
		Case NORTH	ty=(pacy+(pacy And $10)) Shr 5: tx=pacx Shr 5
		Case EAST	tx=(pacx+(pacx And $10)) Shr 5: ty=pacy Shr 5
		Case SOUTH	ty=(pacy-(pacy And $10)) Shr 5: tx=pacx Shr 5
		Case WEST	tx=(pacx-(pacx And $10)) Shr 5: ty=pacy Shr 5
		Default
			tx=pacx Shr 5: ty=pacy Shr 5
	End Select
	level(tx,ty)=level(tx,ty) Or PACPAVED	;temporarily set these bits in pac's square so not affected below
	squares.square=New square
	squares\x=tx
	squares\y=ty
	numsquares=1
	Repeat
		squares.square=First square
		x=squares\x: y=squares\y
		Delete squares
		numsquares=numsquares-1
		;test north
		If (level(x,y-1) And SOUTHorPACPAVEDorILLEGAL)=False
		;looks really long but is really just If (level(x,y) and $60004)=False
		;which means wall south, already paved or outside play area
			level(x,y-1)=level(x,y-1) Or PAC_SOUTH
			squares.square=New square
			squares\x=x
			squares\y=y-1
			numsquares=numsquares+1
		EndIf
		;test west
		If x>0
			If (level(x-1,y) And EASTorPACPAVEDorILLEGAL)=False
				level(x-1,y)=level(x-1,y) Or PAC_EAST
				squares.square=New square
				squares\x=x-1
				squares\y=y
				numsquares=numsquares+1
			EndIf
		Else	;warp exit
			If level(x,y) And WARP
				If (level(11,4) And PACPAVED)=False
					level(11,4)=level(11,4) Or PAC_EAST
					squares.square=New square
					squares\x=11
					squares\y=4
					numsquares=numsquares+1
				EndIf
			EndIf
		EndIf
		;test south
		If (level(x,y+1) And NORTHorPACPAVEDorILLEGAL)=False
			level(x,y+1)=level(x,y+1) Or PAC_NORTH
			squares.square=New square
			squares\x=x
			squares\y=y+1
			numsquares=numsquares+1
		EndIf
		;test east
		If x<11
			If (level(x+1,y) And WESTorPACPAVEDorILLEGAL)=False
				level(x+1,y)=level(x+1,y) Or PAC_WEST
				squares.square=New square
				squares\x=x+1
				squares\y=y
				numsquares=numsquares+1
			EndIf
		Else	;warp exit
			If level(x,y) And WARP
				If (level(0,4) And PACPAVED)=False
					level(0,4)=level(0,4) Or PAC_WEST
					squares.square=New square
					squares\x=0
					squares\y=4
					numsquares=numsquares+1
				EndIf
			EndIf
		EndIf
	Until numsquares=0
Return
End Function
;####################################
Function draw_game()
Local x, y, tile, xpos, ypos, eyenum, pathdir, eyex, eyey
	DrawImage pacman,pacx,pacy
	Select pacdir
		Case NORTH	DrawImage eyes,pacx+9,pacy+9
		Case EAST	DrawImage eyes,pacx+17,pacy+9
		Case SOUTH	DrawImage eyes,pacx+9,pacy+17
		Case WEST	DrawImage eyes,pacx+9,pacy+9
		Case STATIC DrawImage eyes,pacx+9,pacy+9
					DrawImage eyes,pacx+17,pacy+9
	End Select
	For ghosts.ghost=Each ghost
		If Not(ghosts\warping)
			If ghosts\state < CHOMPED Then DrawImage spooks,ghosts\x,ghosts\y,ghosts\frame
			DrawImage eyes,ghosts\x+9,ghosts\y+10
			DrawImage eyes,ghosts\x+17,ghosts\y+10
		EndIf
	Next
	If Not(action=died)	;cover side exits with a black tile
		DrawBlock cover,0,132
		DrawBlock cover,350,132
	EndIf
	If (score+leveltotal)>oldscore Then draw_score()
	If show_paths
		For y=1 To 9
			For x=0 To 11
				If Not(level(x,y) And ILLEGAL)
					If show_paths=1
						pathdir=(level(x,y) And PACPAVED) Shr PACSHIFT
					Else
						pathdir=(level(x,y) And PAVED) Shr PENSHIFT
					EndIf
					Text x Shl 5,y Shl 5,Mid$(DIRECTIONS$,pathdir,1)
				EndIf
			Next
		Next
	EndIf
	Delay VWAIT_DELAY
	Flip
	If show_paths
		FlushKeys()
		WaitKey()
		show_paths=False
		draw_walls()
	EndIf
Return
End Function
;####################################
Function draw_score()
	oldscore=(score+leveltotal)
	SetBuffer ImageBuffer(scoreboard)
	Cls
	Text 0,0,"Score: "+oldscore
	Text 0,14,"Level: "+(mapnum-1)+"  MMx"+maxmultiplier
	SetBuffer BackBuffer()
	DrawBlock scoreboard,0,0
Return
End Function
;####################################
Function draw_walls()
Local x, y
Cls
For y=1 To 9
	ypos=y Shl 5
	For x=1 To 11
		DrawBlock pillpics,(x Shl 5)-4,ypos-4,wallcolour
	Next
Next
For y=1 To 8
	ypos=y Shl 5
	For x=1 To 10
		tile=level(x,y)
		xpos=x Shl 5
		If tile And NORTH Then DrawBlock Hwalls,xpos+3,ypos-2,wallcolour
		If tile And WEST Then DrawBlock Vwalls,xpos-2,ypos+3,wallcolour
		If tile And ANY_PILLS Then DrawBlock pillpics,xpos+12,ypos+12,((tile Shr 6) And 1)+6
	Next
Next
For x=1 To 10
	DrawBlock Hwalls,(x Shl 5)+3,286,wallcolour
Next
For y=1 To 8
	If tile And EAST Then DrawBlock Vwalls,350,(y Shl 5)+3,wallcolour
Next
For x=1 To lives
	DrawBlock pacman,2+((x-1) * 25),290
	DrawImage eyes,19+((x-1) * 25),299
Next
DrawBlock cover,176,120
DrawBlock cover,350,133
draw_score()
Text 200,0,"F5  - collision on/off"
Text 90,290,"F9  - Show directions to ghost-pen"
Text 90,304,"F10 - Show directions to Pac Man"
Return
End Function
;####################################
Function get_new_ghost_dir(sign, x, y, direction)
Local n, e, s, w, z, tile, pacdirection
	tile=level(x,y)
	pacdirection=(tile And PACPAVED) Shr PACSHIFT
	; Is there a wall in this dir?     Can't reverse direction unless no alternative
	n=(((tile And NORTH)>0) * 1000) + ((direction=SOUTH) * 500)
	      ;+1/-1 not scared/scared			   moving in opposite direction - can't reverse unless no choice
	n=n+ ( sign * (((tile And PAC_NORTH)=0) + ( (direction Or pacdirection)=VERTICAL  )) )

	e=(((tile And EAST )>0) * 1000) + ((direction=WEST ) * 500)
	e=e+ ( sign * (((tile And PAC_EAST )=0) + ( (direction Or pacdirection)=HORIZONTAL)) )

	s=(((tile And SOUTH)>0) * 1000) + ((direction=NORTH) * 500)
	s=s+ ( sign * (((tile And PAC_SOUTH)=0) + ( (direction Or pacdirection)=VERTICAL  )) )
	
	w=(((tile And WEST )>0) * 1000) + ((direction=EAST ) * 500)
	w=w+ ( sign * (((tile And PAC_WEST )=0) + ( (direction Or pacdirection)=HORIZONTAL)) )
	z=n: direction=NORTH
	If e<z Then z=e: direction=EAST
	If s<z Then z=s: direction=SOUTH
	If w<z Then z=w: direction=WEST
Return direction
End Function
;####################################
Function get_next_map()
Local x, y
	numpills=0: numpowers=0
	For y=0 To 9
		For x=0 To 11
			Read level(x,y)
			If (level(x,y) And PILL) Then numpills=numpills+1 ElseIf (level(x,y) And POWERPILL) Then numpowers=numpowers+1
		Next
	Next
	levelmax=(numpills * 10) + (numpowers * 50) + (1400 * numpowers)
Return
End Function
;####################################
Function move_ghosts()
Local newdir, walls, x, y, canchangedir
For ghosts.ghost=Each ghost
	x=ghosts\x Shr 5: y=ghosts\y Shr 5	;makes lines shorter, and speeds up variable accessing
	newdir=ghosts\direction
	canchangedir=False

	If (Not((ghosts\x And $1F) Or (ghosts\y And $1F)))	;aligned to centre of a tile?
		If level(x,y) And WARP
			If Not(ghosts\warping)
				ghosts\warping=True
				ghosts\warpcount=TIMEWARP
				newdir=STATIC
			Else
				ghosts\warpcount=ghosts\warpcount-1
				If ghosts\warpcount=0
					ghosts\warping=False
					If x = 0
						newdir=WEST: ghosts\x=352: x=11
					Else
						newdir=EAST: ghosts\x=0: x=0
					EndIf
				EndIf
			EndIf
		Else
			canchangedir=True
		EndIf
	Else
		If (ghosts\direction=NORTH) And (ghosts\x=176)	;exiting pen
			If ghosts\y=96
				newdir=(level(5,3) And PACPAVED) Shr PACSHIFT
			EndIf
		EndIf
	EndIf

	Select ghosts\state
		Case NORMAL
			If canchangedir Then newdir=get_new_ghost_dir(1,x,y,newdir)
		Case SCARED
			ghosts\scarecount=ghosts\scarecount-1
			If (ghosts\scarecount=0)
				ghosts\frame=ghosts\num-1
				ghosts\state=NORMAL
				ghosts\x=ghosts\x And $3FE	;realign to even number pixels - or they'll bugger off
				ghosts\y=ghosts\y And $3FE
				If (Not((ghosts\x And $1F) Or (ghosts\y And $1F))) And (ghosts\warping =False) Then canchangedir=True Else canchangedir=False
				ghosts\xadd=2
				ghosts\yadd=2
				If canchangedir Then newdir=get_new_ghost_dir(1,x,y,newdir)
			Else
				If ghosts\scarecount<100
					If ghosts\scarecount And ((ghosts\scarecount / 25) + 1)
						ghosts\frame=ghosts\num-1
					Else
						ghosts\frame=3
					EndIf
				EndIf
				If canchangedir Then newdir=get_new_ghost_dir(-1,x,y,newdir)
			EndIf
		Case CHOMPED
			If level(x,y) And ABOVEPEN
				If ghosts\x=176
					newdir=SOUTH
				Else
					If canchangedir Then newdir=(level(x,y) And PAVED) Shr PENSHIFT
				EndIf
			Else
				If level(x,y) And GHOSTPEN
					ghosts\state=PENNED
					ghosts\frame=ghosts\num-1
					ghosts\chompcount=0
					ghosts\pencount=ghosts\num * 4
					newdir=EAST
					ghosts\xadd=2
					ghosts\yadd=2
				Else
					If canchangedir Then newdir=(level(x,y) And PAVED) Shr PENSHIFT
				EndIf
			EndIf
		Case PENNED
			If ghosts\x=176
				ghosts\pencount=ghosts\pencount-1
				If ghosts\pencount=0
					newdir=NORTH
					ghosts\state=NORMAL
					ghosts\safe=False
				EndIf
			Else
				If canchangedir Then newdir=ghosts\direction Xor HORIZONTAL
			EndIf
	End Select
	ghosts\direction=newdir
	Select newdir
		Case NORTH	ghosts\y=ghosts\y - ghosts\yadd
		Case EAST	ghosts\x=ghosts\x + ghosts\xadd
		Case SOUTH	ghosts\y=ghosts\y + ghosts\yadd
		Case WEST	ghosts\x=ghosts\x - ghosts\xadd
	End Select
	GrabImage bg,ghosts\x,ghosts\y,ghosts\num-1
Next
Return
End Function
;####################################
Function move_pacman()
Local key, x, y
	DrawBlock pacbg,pacx,pacy
	For ghosts.ghost=Each ghost
		DrawBlock bg,ghosts\x,ghosts\y,ghosts\num-1
	Next
	Select pacdir
		Case NORTH	pacy=pacy-2: staticcount=0
		Case EAST	pacx=pacx+2: staticcount=0
		Case SOUTH	pacy=pacy+2: staticcount=0
		Case WEST	pacx=pacx-2: staticcount=0
		Case STATIC staticcount=staticcount+1
	End Select
	px=pacx Shr 5: py=pacy Shr 5
	If KeyDown(UPARROW) Then key=NORTH
	If KeyDown(RIGHTARROW) Then key=EAST
	If KeyDown(DOWNARROW) Then key=SOUTH
	If KeyDown(LEFTARROW) Then key=WEST
	If key
		If (key And VERTICAL)
			If Not(pacx And $1F)
				If key=NORTH
					If Not(level(px,py) And NORTH) Then pacdir=NORTH
				Else
					If Not(level(px,py) And SOUTH) Then pacdir=SOUTH
				EndIf
			EndIf
		Else
			If Not(pacy And $1F)
				If key=EAST
					If Not(level(px,py) And EAST) Then pacdir=EAST
				Else
					If Not(level(px,py) And WEST) Then pacdir=WEST: pacframe=12
				EndIf
			EndIf
		EndIf
	EndIf
	If Not((pacx And $1F) Or (pacy And $1F))	;centre of a square
		If level(px, py) And WARP
			If px=0 Then pacx=352: px=11 Else pacx=0: px=0
		EndIf
		If level(px,py) And ANY_PILLS
			If level(px,py) And POWERPILL
				For ghosts.ghost=Each ghost
					If Not(ghosts\safe)
						ghosts\state=SCARED
						ghosts\frame=3
						ghosts\scarecount=ghosts\scarecount+SCARED_TIME
						ghosts\xadd=1
						ghosts\yadd=1
					EndIf
				Next
				leveltotal=leveltotal+50
				numpowers=numpowers-1
			Else
				leveltotal=leveltotal+10
				numpills=numpills-1
			EndIf
			level(px,py)=level(px,py) And NO_PILLS
			SetBuffer ImageBuffer(pacbg)
			Cls
			SetBuffer BackBuffer()
			DrawBlock pacbg,pacx,pacy
			If (numpills + numpowers)=0 Then action=COMPLETED
		EndIf
		If (pacdir<>STATIC) Or (staticcount=16) Then do_paths()
		If level(px, py) And pacdir Then pacdir=STATIC
	EndIf
	If ((pacx And $1F)=$10) Or ((pacy And $1F)=$10) Then do_paths()	;after moving every 16 pixels
	GrabImage pacbg,pacx,pacy
Return
End Function
;####################################
Function new_game()
Local ghostnum, backgrounds
	lives=NUM_LIVES: score=0: oldscore=0
	mapnum=1
	action=False
	maxmultiplier=0
Return
End Function
;####################################
Function new_level()
	FlushKeys()
	leveltotal=0
	If (action<>DIED)
		If ((mapnum-1) Mod NUM_MAPS) =0 Then Restore leveldata
		get_next_map()
		mapnum=mapnum+1
	EndIf
	action=False
	SeedRnd MilliSecs()
	For ghosts.ghost=Each ghost
		ghosts\x=160+((ghosts\num-1) Shl 4)
		ghosts\y=128
		ghosts\state=PENNED
		If ghosts\num=1 Then ghosts\direction=WEST Else ghosts\direction=EAST
		ghosts\xadd=2
		ghosts\yadd=2
		ghosts\frame=ghosts\num-1
		ghosts\warping=False
		ghosts\safe=True
		ghosts\chompcount=0
		ghosts\scarecount=0
		ghosts\warpcount=0
		ghosts\pencount=1+((ghosts\num>1)*ghosts\num)	;delay exits so not bunched
		SetBuffer ImageBuffer(bg,ghosts\num-1)
		Cls
	Next
	SetBuffer ImageBuffer(pacbg)
	Cls
	SetBuffer BackBuffer()
	ghostschomped=0
	wallcolour=(mapnum - 1) Mod 5
	pacdir=EAST
	framecount=0
	pacx=PACSTARTX: pacy=PACSTARTY
	px=pacx Shr 5: py=pacy Shr 5
	draw_walls()
	GrabImage pacbg,pacx,pacy
	For ghosts.ghost=Each ghost
		GrabImage bg,ghosts\x,ghosts\y,ghosts\num-1
	Next
	draw_game()
Return
End Function
;####################################
Function setup_ghosts()
Local ghostnum
For ghostnum=0 To 2
	ghosts.ghost=New ghost
	ghosts\num=ghostnum+1
Next
Return
End Function
;####################################
.colours
Data 255,0,0, 0,160,0, 192,0,255, 128,128,255
Data 64,64,127
Data 96,32,127
Data 127,64,64
Data 64,127,64
Data 127,127,127
Data 127,80,50
.titlescreen
Data "PAC MAN"
Data "Harlequin Software 2007"
Data ""
Data "ENTER TO PLAY"
Data "ESCAPE TO QUIT"
Data ""
Data "KEYS"
Data "UP, DOWN, LEFT, RIGHT"
Data ""
Data "  Pills                 + 10 points"
Data "  Power-pills           + 50 points"
Data "  Eat Ghosts            + 200, 400, 800"
Data "  Bonus for Max points  + 1000 Shl Multiplier"
Data "  Lives remaining       + 500 points each"
Data ""
Data "  F5  - turn off collision detection"
Data "  F9  - show pre-calced path to ghost-pen"
Data "  F10 - show real-time calced path to Pac Man"
.leveldata
;level 1
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00249,$00225,$00225,$00225,$00421,$00421,$00825,$00825,$00825,$00843,$20000
Data $20000,$0042A,$00229,$00225,$00421,$00826,$0022C,$00421,$00825,$00823,$0042A,$20000
Data $20000,$0042A,$0012A,$00229,$00220,$002A5,$008A5,$00820,$00823,$0012A,$0042A,$20000
Data $1020D,$00220,$00220,$00126,$0012A,$0001D,$00017,$0012A,$0012C,$00820,$00820,$10807
Data $20000,$0012A,$00128,$00823,$00128,$00825,$00225,$00122,$00429,$00122,$0012A,$20000
Data $20000,$0012A,$0012A,$0022C,$00120,$00825,$00225,$00120,$00826,$0012A,$0012A,$20000
Data $20000,$0012A,$0012C,$00225,$00124,$00823,$00229,$00124,$00825,$00826,$0012A,$20000
Data $20000,$0014C,$00825,$00225,$00225,$00124,$00124,$00825,$00825,$00825,$00146,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
;level 2
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00249,$00225,$00225,$00421,$00825,$00225,$00421,$00825,$00825,$00843,$20000
Data $20000,$0012A,$00229,$00221,$00220,$00423,$00429,$00820,$00821,$00823,$0012A,$20000
Data $20000,$00228,$00124,$00126,$00228,$002A4,$008A4,$00822,$0012C,$00824,$00822,$20000
Data $1020D,$00220,$00225,$00225,$00122,$0001D,$00017,$00128,$00825,$00825,$00820,$10807
Data $20000,$00128,$00821,$00423,$00128,$00825,$00225,$00122,$00429,$00821,$00122,$20000
Data $20000,$0012A,$0022C,$00224,$00122,$00429,$00423,$00128,$00824,$00826,$0012A,$20000
Data $20000,$00128,$00225,$00225,$00124,$00824,$00224,$00124,$00825,$00825,$00822,$20000
Data $20000,$0012C,$00825,$00825,$00825,$00847,$0024D,$00225,$00225,$00225,$00126,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
;level 3
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00249,$00221,$00421,$00825,$00823,$00229,$00225,$00421,$00821,$00843,$20000
Data $20000,$00128,$00126,$0022C,$00423,$0012C,$00126,$00429,$00826,$0012C,$00822,$20000
Data $20000,$00228,$00423,$00229,$00220,$002A5,$008A5,$00820,$00823,$00429,$00822,$20000
Data $1020D,$00122,$0022C,$00126,$0012A,$0001D,$00017,$0012A,$0012C,$00826,$00128,$10807
Data $20000,$0012A,$00229,$00423,$00128,$00821,$00221,$00122,$00429,$00823,$0012A,$20000
Data $20000,$00128,$00126,$0022C,$00120,$00826,$0012C,$00120,$00826,$0012C,$00822,$20000
Data $20000,$00128,$00423,$00229,$00126,$00429,$00423,$0012C,$00823,$00429,$00822,$20000
Data $20000,$0024C,$00224,$00124,$00825,$00826,$0022C,$00225,$00124,$00824,$00846,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
;level 4
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00249,$00225,$00421,$00825,$00421,$00421,$00825,$00421,$00825,$00843,$20000
Data $20000,$00128,$00823,$0022C,$00421,$00826,$0022C,$00421,$00826,$00229,$00122,$20000
Data $20000,$0012A,$0022C,$00423,$00228,$002A5,$008A5,$00822,$00429,$00826,$0012A,$20000
Data $1020D,$00220,$00225,$00422,$0012A,$0001D,$00017,$0012A,$00428,$00825,$00820,$10807
Data $20000,$00228,$00225,$00220,$00120,$00825,$00225,$00120,$00820,$00825,$00822,$20000
Data $20000,$0012A,$00229,$00126,$0012C,$00823,$00229,$00126,$0012C,$00823,$0012A,$20000
Data $20000,$0012A,$0012C,$00823,$00229,$00124,$00124,$00823,$00229,$00126,$0012A,$20000
Data $20000,$0014C,$00825,$00124,$00124,$00825,$00225,$00124,$00824,$00825,$00146,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
;level 5
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00249,$00225,$00423,$00429,$00825,$00225,$00423,$00429,$00825,$00843,$20000
Data $20000,$00228,$00225,$00220,$00224,$00423,$00429,$00824,$00820,$00825,$00822,$20000
Data $20000,$0012C,$00823,$0012A,$00229,$002A4,$008A4,$00823,$0012A,$00229,$00126,$20000
Data $1020D,$00225,$00122,$0012A,$0012A,$0001D,$00017,$0012A,$0012A,$00128,$00825,$10807
Data $20000,$00229,$00126,$0012A,$0012C,$00821,$00221,$00126,$0012A,$0012C,$00423,$20000
Data $20000,$00228,$00221,$00124,$00221,$00126,$0012C,$00821,$00124,$00821,$00822,$20000
Data $20000,$0012A,$0012C,$00823,$0012C,$00823,$00229,$00126,$00229,$00126,$0012A,$20000
Data $20000,$0014C,$00825,$00124,$00225,$00124,$00124,$00825,$00124,$00825,$00146,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
;level 6
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00249,$00225,$00423,$00429,$00825,$00225,$00423,$00429,$00825,$00843,$20000
Data $20000,$0012A,$00229,$00420,$00824,$00825,$00225,$00224,$00420,$00823,$0012A,$20000
Data $20000,$00228,$00126,$00228,$00221,$002A5,$008A5,$00821,$00822,$0012C,$00822,$20000
Data $1020D,$00122,$00229,$00126,$0012A,$0001D,$00017,$0012A,$0012C,$00823,$00128,$10807
Data $20000,$0022C,$00120,$00823,$00128,$00825,$00225,$00122,$00429,$00120,$00826,$20000
Data $20000,$00229,$00122,$00228,$00126,$00429,$00423,$0012C,$00822,$00128,$00823,$20000
Data $20000,$0012A,$0012C,$00120,$00825,$00822,$00228,$00225,$00120,$00826,$0012A,$20000
Data $20000,$0014C,$00225,$00124,$00825,$00824,$00124,$00225,$00124,$00825,$00846,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
;level 7
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00249,$00225,$00421,$00825,$00825,$00225,$00225,$00421,$00825,$00843,$20000
Data $20000,$00128,$00823,$00428,$00825,$00825,$00225,$00225,$00422,$00229,$00122,$20000
Data $20000,$0012A,$0012A,$0022C,$00225,$002A5,$008A5,$00825,$00826,$0012A,$0012A,$20000
Data $1020D,$00120,$00824,$00823,$0042B,$0001D,$00017,$0042B,$00229,$00124,$00120,$10807
Data $20000,$00128,$00823,$0012C,$00820,$00825,$00225,$00220,$00126,$00229,$00122,$20000
Data $20000,$0012A,$00128,$00825,$00824,$00823,$00229,$00124,$00225,$00122,$0012A,$20000
Data $20000,$0012A,$0012A,$00429,$00821,$00126,$0012C,$00821,$00423,$0012A,$0012A,$20000
Data $20000,$0014C,$00824,$00826,$0012C,$00825,$00225,$00126,$0022C,$00124,$00146,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
;level 8
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00249,$00421,$00225,$00421,$00825,$00225,$00421,$00825,$00421,$00843,$20000
Data $20000,$0042A,$0042A,$00429,$00826,$00429,$00423,$0022C,$00423,$0042A,$0042A,$20000
Data $20000,$00228,$00224,$00224,$00221,$002A4,$008A4,$00821,$00824,$00824,$00822,$20000
Data $1020D,$00124,$00823,$00229,$00122,$0001D,$00017,$00128,$00823,$00429,$00124,$10807
Data $20000,$00229,$00224,$00122,$0012C,$00821,$00221,$00126,$00128,$00824,$00823,$20000
Data $20000,$00128,$00225,$00124,$00821,$00126,$0012C,$00821,$00124,$00825,$00822,$20000
Data $20000,$0012A,$00229,$00225,$00120,$00825,$00225,$00120,$00825,$00823,$0012A,$20000
Data $20000,$0014C,$00824,$00225,$00124,$00825,$00225,$00124,$00825,$00824,$00146,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
;level 9
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00449,$00225,$00225,$00221,$00423,$00429,$00825,$00825,$00421,$00843,$20000
Data $20000,$00228,$00225,$00421,$00826,$0022C,$00224,$00421,$00825,$00826,$0042A,$20000
Data $20000,$00228,$00423,$0042A,$00229,$002A5,$008A5,$00824,$00825,$00825,$00826,$20000
Data $1020D,$00224,$00224,$00224,$00126,$0001D,$00017,$00229,$00221,$00225,$00221,$10207
Data $20000,$00229,$00225,$00221,$00423,$00229,$00221,$00126,$0012C,$00221,$00122,$20000
Data $20000,$0012A,$00229,$00126,$0022C,$00122,$0012C,$00225,$00225,$00126,$0012A,$20000
Data $20000,$00128,$00124,$00225,$00423,$00128,$00825,$00423,$00229,$00225,$00122,$20000
Data $20000,$0024C,$00225,$00225,$00224,$00124,$00225,$00224,$00124,$00225,$00146,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
;level 10
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00249,$00221,$00221,$00421,$00825,$00225,$00421,$00821,$00821,$00843,$20000
Data $20000,$0012A,$0012A,$0012A,$00428,$00825,$00225,$00422,$0012A,$0012A,$0012A,$20000
Data $20000,$0012A,$0012A,$0012A,$00228,$002A5,$008A5,$00822,$0012A,$0012A,$0012A,$20000
Data $1020D,$00422,$0042A,$0042A,$0012A,$0001D,$00017,$0012A,$0042A,$0042A,$00428,$10807
Data $20000,$00228,$00224,$00224,$00120,$00821,$00221,$00120,$00824,$00824,$00822,$20000
Data $20000,$00128,$00225,$00225,$00122,$0012A,$0012A,$00128,$00825,$00825,$00822,$20000
Data $20000,$00128,$00225,$00225,$00122,$0012A,$0012A,$00128,$00825,$00825,$00822,$20000
Data $20000,$0014C,$00225,$00225,$00124,$00824,$00124,$00124,$00825,$00825,$00846,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
;level 11
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000
Data $20000,$00249,$00221,$00221,$00221,$00421,$00421,$00821,$00821,$00821,$00843,$20000
Data $20000,$00228,$00220,$00220,$00220,$00420,$00420,$00820,$00820,$00820,$00822,$20000
Data $20000,$00228,$00220,$00220,$00220,$002A4,$008A4,$00820,$00820,$00820,$00822,$20000
Data $1020D,$00120,$00120,$00122,$0012A,$0001D,$00017,$0012A,$00128,$00820,$00820,$10807
Data $20000,$00128,$00120,$00122,$0012C,$00825,$00225,$00126,$00128,$00820,$00822,$20000
Data $20000,$00128,$00120,$00120,$00821,$00821,$00221,$00221,$00120,$00820,$00822,$20000
Data $20000,$00128,$00120,$00120,$00820,$00820,$00120,$00120,$00120,$00820,$00822,$20000
Data $20000,$0014C,$00124,$00124,$00824,$00824,$00124,$00124,$00124,$00824,$00846,$20000
Data $20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000,$20000

Comments

Chroma2007
Very nice work there!


Dustin2007
Vic's having a little trouble logging in so he asked me to mention that there are 2 bugs. But he'll be posting an update soon with changes in the path finding as well as things like power-ups.

It's a great piece of work in a short amount of code. Looking forward to the update!


Vic 3 Babes2007
Thanks Dustin - AVG seems to be stopping me logging in, so I'm using a different PC.

Although the updated version (available as Pac Man Update) is much better, I thought you might want to know what the bugs were in this one, and how to fix them.

-------------

There is a bug in the move_ghosts() function. Ghosts can normally only ever change direction when they are exactly in the centre of a square - but the one exception to this rule is when they are entering/exiting the ghost pen. This is easily taken care of when entering the pen, and I thought taken care of when exiting, however, if there are no NORTH walls in the two squares above the ghost-pen, and the square on the left if pointing NORTH to Pac Man, then the ghost will start moving North, and will then never change direction, because it will never be aligned with the centre of a square.

This is a quick-fix which works fine - but might not send the ghost in the optimum direction on all occasions. Replace the Else clause at the end of the first IF with the following.

	Else
		If (ghosts\direction=NORTH) And (ghosts\x=176)	;exiting pen
			If ghosts\y=96
				If pacx > 176 Then newdir=EAST Else newdir=WEST
			EndIf
		EndIf
	EndIf


This wasn't a problem in the version that used a count method for the path to Pac Man, because the ghost simply took the path with the lowest count above the ghost-pen (left or right).

-------------

There is a bug in the Select clause at the top of the do_paths() function - nothing serious - in fact I doubt anyone noticed, but you can see the bug if you press F10 and watch the path data when Pac Man moves North or South - though it works for East and West. The focus square for the path-finding is supposed to be the square that Pac Man is mostly in - and so changes when he has moved across or down a square by 16 pixels. In the Select list, the + and - signs for NORTH and SOUTH should be the other way around.

However, the first call to do_paths() at the end of the move_pacman() function is redundant (see below), and can be removed, which means you can change the select in do_paths() to the following.

Select pacdir
Case NORTH ty=py : tx=px
Case EAST tx=(pacx Shr 5) +1 : ty=pacy Shr 5
Case SOUTH ty=(pacy Shr 5) +1 : tx=pacx Shr 5
Case WEST tx=px : ty=py
End Select

-------------

If (pacdir<>STATIC) Or (staticcount=16) Then do_paths()

The first call to do_paths() at the end of the move_pacman() function is redundant (shown above). Although this version sets bits to indicate NESW directions, the previous (and now revised) version stored a count in bits 18 onwards to indicate how many square away Pac Man was. I also had the ghosts altering these values so that ghosts following them would split-up in a different direction. Calling do_paths() reset the paths that the ghosts had altered - but if Pac Man wasn't moving, the call to do_paths() wasn't made, and this had sorts of weird effects.

For this reason, I added the staticcount variable, and called do_paths() if Pac Man didn't move after a certain amount of time. But after changing the code so that ghosts didn't alter the paths, this call became redundant.

The second call to do_paths is the only one necessary - and calls the function whenever Pac Man is 16 pixels across or down the current 32x32 square.

This means you can remove the staticcount variable, and all references to it.

-------------

There is a field in the Ghost Type that is no longer used, so you can remove it, and references to it.

ghosts\chompcount

---------

The fields, xadd and yadd in the Ghost Type can be amalgamated into one variable - pixeladd, and the code altered accordingly. This is because the ghosts only ever move North or South, never both, so there was no need for two variables.

---------

I've got that many different versions of this game that I'm not sure about this one - better check the version that I posted - but

check_collided() called before characters moved in main loop - should be after

---------

The Last level can't be completed. It could be completed with the path recording method used previously - i.e. storing the count of how many squares away Pac Man was in bits 18 onwards - but when I changed it to NESW, it meant that you could no longer lure the ghosts to the right on the final level, before moving off to the left.

Now that I have gone back to the original method of path storing - the last level can be completed in the updated version.


Vic 3 Babes2007
This is an updated version which goes back to using a count method for the path-finding. The count of how many squares away an array element is from Pac Man's position is stored in bits 18 onwards, and bits 12-15 are no longer usedl.

I've also added a few bonus items. I only posted this because of the bugs in the first version, and won't be posting any more. However you might like to know that I've also added a new power-up to the full version of the game that I've decided to make.

The editor locks certain walls so that you can't draw or erase them - like the warp exits/ghost-pen. The Editor previously removed this information when it exported the data for the game. I've now altered this slightly, and added a new power-up which gives Pac Man ghost-like abilities - i.e. he can pass through walls - but not locked walls, like the perimter etc. The walls are drawn transparently, and flash briefly when Pac Man is returning to normal.

The power-up in the version below though, is just the mega-pill, which automatically chomps any ghosts on the level. You can also collect EXTRA letters for an extra life.




Code Archives Forum