Skip to content

Commit 74bb4b5

Browse files
committed
Added ghosts with primitive chase AI
Added a set of four semi-transparent ghost snakes that chase Pacsnake's position with random mistakes. ? The ghost snakes themselves were pretty easy to put in - they're just another kind of snake that moves through the space. Thinking about how they would choose their movement involved me reading an in-depth article about Pacman ghost AI from here: http://gameinternals.com/post/2072558330/understanding-pac-man-ghost-behavior And eventually deciding (I think?) that it's overkill to try to replicate the actual AIs from Pacman. But that's not settled yet and I think I'll need to write some stuff about that. ? One issue that actually playing around in the level with the ghosts is that I'm much less clear on the dynamics between Pacsnake and the ghosts. Does Pacsnake eat them by eating a powerpill and changing the mode? Or do they dies on contact with Pacsnake's body? (and each other's?) in which case the 'power' of the power pellet is about being longer and thus potentially more dangerous to the ghosts (but then also to yourself). ? The fact the ghost snakes are semitransparent (and known as ghosts) makes it seem impossible that they could crash into the Pacsnake's body. But then on the other hand in Pacman he can EAT them and they can KILL him, so they clearly have SOME kind of tangibility and connection to the physical realm right? They can't even pass through walls. Are those things EVEN GHOSTS AT ALL? So there's some decision making involved in that. If everyone can collide with everyone's body I think it will lead to utter carnage? But that may be funny... it may be that pulling the gameplay _away_ from Pacman original is a good solution to the issues around Ghost AI? (Although I may be shooting myself in the foot massively? Although I guess ghosts would just respawn in their little closet so it would be fine? Actually it seems complicated.)
1 parent eea920f commit 74bb4b5

File tree

6 files changed

+96
-23
lines changed

6 files changed

+96
-23
lines changed

snakes/Missssssile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ BasicGame.Missssssile.prototype.tick = function () {
4040
};
4141

4242
BasicGame.Missssssile.prototype.addMissile = function () {
43-
var missile = new Snake(this,this.WALL_LEFT + 1 + Math.floor(Math.random() * (this.WALL_RIGHT - 1 - this.WALL_LEFT)),this.WALL_TOP + 1);
43+
var missile = new Snake(this.game,this.WALL_LEFT + 1 + Math.floor(Math.random() * (this.WALL_RIGHT - 1 - this.WALL_LEFT)),this.WALL_TOP + 1);
4444
missile.target = this.apples.getRandom();
4545
while (!missile.target.alive) {
4646
missile.target = this.apples.getRandom();

snakes/Msss.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ BasicGame.Msss.prototype.create = function () {
2323
[0,0,1,2,2,2,2,1,2,2,2,1,1,2,2,2,1,2,2,2,2,1,0,0],
2424
[0,0,1,1,2,1,1,1,1,1,0,1,1,0,1,1,1,1,1,2,1,1,0,0],
2525
[1,1,1,1,2,2,2,1,0,0,0,0,0,0,0,0,1,2,2,2,1,1,1,1],
26-
[0,0,0,0,0,1,2,1,0,1,1,0,0,1,1,0,1,2,1,0,0,0,0,0],
26+
[0,0,0,0,0,1,2,1,0,1,0,1,1,0,1,0,1,2,1,0,0,0,0,0],
2727
[1,1,1,1,1,1,2,0,0,1,0,0,0,0,1,0,0,2,1,1,1,1,1,1],
2828
[0,0,0,0,0,1,2,1,0,1,1,1,1,1,1,0,1,2,1,0,0,0,0,0],
2929
[1,1,1,1,0,1,2,1,0,0,0,0,0,0,0,0,1,2,1,0,1,1,1,1],
@@ -51,14 +51,23 @@ BasicGame.Msss.prototype.create = function () {
5151

5252
// this.snake.y = (this.WALL_BOTTOM)*GRID_SIZE;
5353

54-
55-
this.ghost = null;
56-
// this.createGhost();
54+
this.createGhosts();
5755

5856
// Name the state for resetting purposes
5957
this.stateName = "Msss";
6058
};
6159

60+
BasicGame.Msss.prototype.createGhosts = function () {
61+
this.ghosts = this.game.add.group();
62+
for (var i = 0; i < 4; i++) {
63+
var ghost = new Snake(this.game,this.WALL_LEFT + 9 + i,this.WALL_TOP + 12);
64+
ghost.bodyPiecesToAdd = ghost.NEW_BODY_PIECES_PER_APPLE;
65+
ghost.target = this.snake.head;
66+
ghost.alpha = 0.5;
67+
this.ghosts.add(ghost);
68+
}
69+
};
70+
6271
BasicGame.Msss.prototype.createApples = function () {
6372
this.apples = this.game.add.group();
6473
this.miniApples = this.game.add.group();
@@ -85,15 +94,14 @@ BasicGame.Msss.prototype.tick = function () {
8594
BasicGame.SnakeBaseGame.prototype.tick.call(this);
8695

8796
// Wrap the snake around the edges, as per Pacman Physical Reality
88-
if (this.snake.head.x >= this.game.width) {
89-
this.snake.head.x = 0;
90-
}
91-
else if (this.snake.head.x < 0) {
92-
this.snake.head.x = this.game.width - GRID_SIZE;
93-
}
97+
this.snake.wrap();
9498

95-
// this.ghost.chase();
96-
// this.ghost.move();
99+
this.ghosts.forEach(function (ghost) {
100+
ghost.chaseMaze(this.map);
101+
ghost.grow();
102+
ghost.move();
103+
ghost.wrap();
104+
},this);
97105
};
98106

99107
BasicGame.Msss.prototype.checkAppleCollision = function () {
@@ -112,12 +120,6 @@ BasicGame.Msss.prototype.checkAppleCollision = function () {
112120

113121
};
114122

115-
BasicGame.Msss.prototype.createGhost = function () {
116-
this.ghost = new Snake(this,0,this.WALL_TOP + 10);
117-
this.immigrant.target = this.snake.head;
118-
this.game.add.sprite(this.ghost);
119-
};
120-
121123
BasicGame.Msss.prototype.gameOver = function () {
122124

123125
};

snakes/Papersss.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ BasicGame.Papersss.prototype.checkAppleCollision = function () {
8888
};
8989

9090
BasicGame.Papersss.prototype.createImmigrant = function () {
91-
this.immigrant = new Snake(this,0,this.WALL_TOP + 10);
91+
this.immigrant = new Snake(this.game,0,this.WALL_TOP + 10);
9292
this.immigrantApple = this.game.add.sprite((this.WALL_RIGHT+1)*GRID_SIZE,(this.WALL_TOP + 10)*GRID_SIZE,'apple');
9393
this.immigrant.target = this.immigrantApple;
9494
this.game.add.sprite(this.immigrant);

snakes/Snake.js

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Snake = function (game,x,y) {
33
Phaser.Group.call(this, game);
44

5+
this.game = game;
56
this.SNAKE_START_LENGTH = 4;
67
this.NEW_BODY_PIECES_PER_APPLE = 3;
78
this.SNAKE_FLICKER_SPEED = 0.2;
@@ -117,7 +118,7 @@ Snake.prototype.checkBodyCollision = function () {
117118
return false;
118119
};
119120

120-
Snake.prototype.chase = function () {
121+
Snake.prototype.chaseLinear = function () {
121122
// If we have reached the target, we stop
122123
if (this.target.position.equals(this.head.position)) {
123124
this.stop();
@@ -166,6 +167,76 @@ Snake.prototype.chase = function () {
166167
}
167168
};
168169

170+
Snake.prototype.chaseMaze = function (map) {
171+
// If we have reached the target, we stop
172+
if (this.target.position.equals(this.head.position)) {
173+
this.stop();
174+
return;
175+
}
176+
177+
var mapX = this.head.x / GRID_SIZE;
178+
var mapY = this.head.y / GRID_SIZE;
179+
180+
var openMoves = [];
181+
if (mapX - 1 >= 0) {
182+
if (map[mapY][mapX - 1] != 1 && this.next.x <= 0) {
183+
openMoves.push(new Phaser.Point(-GRID_SIZE,0));
184+
}
185+
}
186+
if (mapX + 1 >= 0) {
187+
if (map[mapY][mapX + 1] != 1 && this.next.x >= 0) {
188+
openMoves.push(new Phaser.Point(GRID_SIZE,0));
189+
}
190+
}
191+
if (mapY - 1 >= 0) {
192+
if (map[mapY - 1][mapX] != 1 && this.next.y <= 0) {
193+
openMoves.push(new Phaser.Point(0,-GRID_SIZE));
194+
}
195+
}
196+
if (mapY + 1 >= 0) {
197+
if (map[mapY + 1][mapX] != 1 && this.next.y >= 0) {
198+
openMoves.push(new Phaser.Point(0,GRID_SIZE));
199+
}
200+
}
201+
202+
var next = null;
203+
openMoves.forEach(function (m) {
204+
if (this.head.x < this.target.x && m.x > 0) {
205+
next = m;
206+
}
207+
else if (this.head.x > this.target.x && m.x < 0) {
208+
next = m;
209+
}
210+
else if (this.head.y < this.target.y && m.y > 0) {
211+
next = m;
212+
}
213+
else if (this.head.y > this.target.y && m.y < 0) {
214+
next = m;
215+
}
216+
},this);
217+
218+
if (openMoves.length == 0) {
219+
// console.log("OH NO! HOW THE HELL HAS THIS HAPPENED???");
220+
// console.log(this.next);
221+
// console.log(this.head.x,this.head.y);
222+
}
223+
else if (next != null && Math.random() < 0.75) {
224+
this.next = next;
225+
}
226+
else {
227+
this.next = openMoves[Math.floor(Math.random() * openMoves.length)];
228+
}
229+
};
230+
231+
Snake.prototype.wrap = function () {
232+
if (this.head.x >= this.game.width) {
233+
this.head.x = 0;
234+
}
235+
else if (this.head.x < 0) {
236+
this.head.x = this.game.width - GRID_SIZE;
237+
}
238+
};
239+
169240
Snake.prototype.die = function () {
170241
this.hitSFX.play();
171242
this.dead = true;

snakes/SnakeBaseGame.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ BasicGame.SnakeBaseGame.prototype = {
129129
},
130130

131131
createSnake: function () {
132-
this.snake = new Snake(this,this.SNAKE_START_X,this.SNAKE_START_Y);
132+
this.snake = new Snake(this.game,this.SNAKE_START_X,this.SNAKE_START_Y);
133133
},
134134

135135
createApple: function () {

snakes/Sssensssible.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ BasicGame.Sssensssible.prototype.createSnake = function() {
8484
this.SNAKE_TWO_START_X = this.SNAKE_START_X;
8585
this.SNAKE_TWO_START_Y = this.WALL_BOTTOM - this.SNAKE_START_Y + this.WALL_TOP + 1;
8686

87-
this.snakeTwo = new Snake(this,this.SNAKE_TWO_START_X,this.SNAKE_TWO_START_Y);
87+
this.snakeTwo = new Snake(this.game,this.SNAKE_TWO_START_X,this.SNAKE_TWO_START_Y);
8888
};
8989

9090

0 commit comments

Comments
 (0)