Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 1509 lines (1314 sloc) 56.281 kb
b68496b Mike first commit
authored
1 #!/usr/bin/env python
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
2 # A Snakey clone made with Pygame.
3 # Includes various fruits with different effects in regards to score,
4 # snake size, and other in-game effects.
5 # Includes various Snake AIs and game modes (Arcade, Duel, Party).
b68496b Mike first commit
authored
6
7 import random, pygame, sys
8 from pygame.locals import *
9
10 WINDOWWIDTH = 640
11 WINDOWHEIGHT = 480
6c613da Mike Worked on AI; added crude apple detection.
authored
12 FPS = 12
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
13 MIN_FPS = 3
14 MAX_FPS = 60
b68496b Mike first commit
authored
15 CELLSIZE = 20
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
16 TOP_BUFFER = CELLSIZE * 1 # displays in-game info
b68496b Mike first commit
authored
17 assert WINDOWWIDTH % CELLSIZE == 0, "Window width must be a multiple of cell size."
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
18 assert (WINDOWHEIGHT - TOP_BUFFER) % CELLSIZE == 0, "Window height must be a multiple of cell size."
b68496b Mike first commit
authored
19 CELLWIDTH = int(WINDOWWIDTH / CELLSIZE)
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
20 CELLHEIGHT = int((WINDOWHEIGHT - TOP_BUFFER) / CELLSIZE)
b68496b Mike first commit
authored
21
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
22 # colors - (R G B)
b68496b Mike first commit
authored
23 WHITE = (255, 255, 255)
24 BLACK = (0, 0, 0)
25 RED = (255, 0, 0)
26 GREEN = (0, 255, 0)
27 BLUE = (0, 0, 255)
28 DARKGRAY = (40, 40, 40)
29 HONEYDEW = (240, 255, 240)
30 MINTGREEN = (189, 252, 201)
31 SEAGREEN = (84, 255, 159)
32 EMERALDGREEN = (0, 201, 87)
33 FORESTGREEN = (34, 139, 34)
34 COBALTGREEN = (61, 145, 64)
35 GREENYELLOW = (173, 255, 47)
36 OLIVEGREEN = (107, 142, 35)
37 IVORY = (205, 205, 193)
38 LIGHTYELLOW = (238, 238, 209)
39 YELLOW = (238, 238, 0)
40 KHAKI = (255, 246, 143)
41 GOLDENROD = (218, 165, 32)
42 CORAL = (255, 127, 80)
43 SIENNA = (255, 130, 71)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
44 ORANGE = (255, 127, 0)
b68496b Mike first commit
authored
45 PURPLE = (142, 56, 142)
46 MAROON = (255, 52, 179)
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
47 BACKGROUNDCOLOR = BLACK
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
48 BUTTONCLR = GREEN
49 BUTTONTXT = DARKGRAY
c9dd311 Mike added tron(y) mode.
authored
50 BUTTONCLR_SL = COBALTGREEN
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
51 BUTTONTXT_SL = GOLDENROD
ef0acb2 Mike consolidated game over sequence.
authored
52 MESSAGE_COLOR = GREEN
b68496b Mike first commit
authored
53
6c613da Mike Worked on AI; added crude apple detection.
authored
54 # for consistency in direction types
b68496b Mike first commit
authored
55 UP = 'up'
56 DOWN = 'down'
57 LEFT = 'left'
58 RIGHT = 'right'
59
6c613da Mike Worked on AI; added crude apple detection.
authored
60 # for consistency in snake names
6127227 Mike Added more selection for Duel Mode.
authored
61 SNAKEY = 'snakey'
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
62 WIGGLES = 'wiggles'
63 GIGGLES = 'giggles'
64 LINUS = 'linus'
65
6c613da Mike Worked on AI; added crude apple detection.
authored
66 # index of snake's head
67 HEAD = 0
b68496b Mike first commit
authored
68
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
69 # minimum and maximum frames fruit remains on screen - determined randomly
70 POISONTIMER = (100, 200)
71 ORANGETIMER = (35, 65)
72 RASPBERRYTIMER = (30, 45)
73 BLUEBERRYTIMER = (20, 40)
74 LEMONTIMER = (100, 100)
75
76 FREEZING_POINT = 8
faa87d1 Mike added Snake, Fruit, Tally classes
authored
77
78 POISONBONUS = 7
79 ORANGEBONUS = 8
80 RASPBERRYBONUS = 9
81 BLUEBERRYBONUS = 10
82 LEMONBONUS = 11
b68496b Mike first commit
authored
83
84
85 class Snake:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
86 """
87 Snake class houses all information for a particular snake.
88 player - if snake is the player. Player snake is also referenced directly when player snake object is created.
6d8cfaf Mike set-up ai
authored
89 name - name of snake.
faa87d1 Mike added Snake, Fruit, Tally classes
authored
90 alive - if snake is alive. Rather than delete, this allows snake to slowly shrink to the point of where it died.
91 coords - a list of dictionaries containing coordinates 'x' and 'y'. A special global variable HEAD (0).
92 direction - where snake moves for every game iteration ('left', 'up', etc).
93 color - body of snake's color.
94 colorBorder - outline of body.
95 growth - when a snake is to grow, this is stored in this buffer so that every game iteration can add one growth, only.
96 multiplier - all fruit eaten which cause points to be scored are multiplied by this.
97 multipliertimer - number of game iterations multiplier stays in effect.
98 score - the number of points snake has accumulated.
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
99 place - used to determine death order.
faa87d1 Mike added Snake, Fruit, Tally classes
authored
100 """
6127227 Mike Added more selection for Duel Mode.
authored
101 def __init__(self, n=SNAKEY, c=False, sc=GREEN, sb=COBALTGREEN):
6d8cfaf Mike set-up ai
authored
102 self.name = n
6127227 Mike Added more selection for Duel Mode.
authored
103 if self.name == SNAKEY:
104 self.player = True
105 else:
106 self.player = False
b68496b Mike first commit
authored
107 self.alive = True
6127227 Mike Added more selection for Duel Mode.
authored
108
109 if c == False:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
110 self.coords = getStartCoords(1)
6127227 Mike Added more selection for Duel Mode.
authored
111 else:
112 self.coords = c
b68496b Mike first commit
authored
113 # ensure snake length
114 assert len(self.coords) > 1
6127227 Mike Added more selection for Duel Mode.
authored
115
116 # determine direction -- currently only supports right or left
117 if self.coords[0]['x'] > self.coords[1]['x']:
118 self.direction = RIGHT
119 else:
120 self.direction = LEFT
b68496b Mike first commit
authored
121 self.color = sc
4ae7881 Mike Fixed grid and snake color changes.
authored
122 self.colorCurrent = self.color
b68496b Mike first commit
authored
123 self.colorBorder = sb
4ae7881 Mike Fixed grid and snake color changes.
authored
124 self.colorBorderCurrent = self.colorBorder
b68496b Mike first commit
authored
125 self.growth = 0
126 self.multiplier = 1
127 self.multipliertimer = 0
128 self.score = 0
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
129 self.place = False
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
130 self.fruitEaten = {'apple':0, 'poison':0, 'orange':0,
131 'raspberry':0, 'blueberry':0, 'lemon':0}
faa87d1 Mike added Snake, Fruit, Tally classes
authored
132
133 def updateScore(self, points_input):
134 """
135 This updates score of snake, factoring multiplier.
136 """
137 self.score = self.score + (points_input * self.multiplier)
138
139 def updateGrowth(self, growth_input):
140 """
141 This updates growth "owed" to snake, allowing amount to stack.
142 """
143 self.growth = self.growth + growth_input
144
145 def updateMultiplier(self, multiplier_input, timer_input):
146 """
147 This updates multiplier value and time (game iterations) multiplier is active. Only time stacks.
148 """
149 # multiplier value does not stack, but time does
150 self.multiplier = multiplier_input
151 self.multipliertimer = self.multipliertimer + timer_input
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
152
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
153 def getPlace(self, totaldead, totalsnakes):
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
154 """
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
155 Returns a string containing the 'place' of a snake (longest lasting = 1st)
156 If game aborted early, will grant all living snakes '1st (alive)'
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
157 """
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
158 totalalive = totalsnakes - totaldead
159
160 # snake not dead
161 if self.place == False:
162 return '1st (alive)'
163 # if not aborted early
164 elif totalalive == 0:
165 if self.place == totalsnakes:
166 return '1st'
167 elif self.place + 1 == totalsnakes:
168 return '2nd'
169 elif self.place + 2 == totalsnakes:
170 return '3rd'
171 else:
172 return 'last'
173 # aborted early; factor in living snakes
174 elif self.place == totalsnakes - totalalive:
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
175 return '2nd'
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
176 elif self.place + 1 == totalsnakes - totalalive:
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
177 return '3rd'
178 else:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
179 return 'last'
faa87d1 Mike added Snake, Fruit, Tally classes
authored
180
181 def boundsCollision(self):
182 """
183 This returns True if snake (head) is ever out of grid parameters.
184 """
6d8cfaf Mike set-up ai
authored
185 # check if out of bounds -- offset on on 'y' for buffer.
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
186 if self.coords[HEAD]['x'] == -1 or \
187 self.coords[HEAD]['x'] == CELLWIDTH or \
188 self.coords[HEAD]['y'] == -1 + (TOP_BUFFER / CELLSIZE) or \
189 self.coords[HEAD]['y'] == CELLHEIGHT + (TOP_BUFFER / CELLSIZE):
faa87d1 Mike added Snake, Fruit, Tally classes
authored
190 return True
191 else:
192 return False
193
194 def snakeCollision(self, snake):
195 """
196 This returns True if snake (head) collides with any part of a given snake (outside of own head if checking against self).
197 """
198 if self is snake:
199 # exclude head if checked against self
200 for snakebody in snake.coords[1:]:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
201 if snakebody['x'] == self.coords[HEAD]['x'] and \
202 snakebody['y'] == self.coords[HEAD]['y']:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
203 return True
204 else:
205 for snakebody in snake.coords:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
206 if snakebody['x'] == self.coords[HEAD]['x'] and \
207 snakebody['y'] == self.coords[HEAD]['y']:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
208 return True
209 # no collision
210 return False
211
212 def fruitCollision(self, fruit):
213 """
214 This returns True if snake (head) has collided with a given fruit.
215 """
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
216 if self.coords[HEAD]['x'] == fruit.coords['x'] and \
217 self.coords[HEAD]['y'] == fruit.coords['y']:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
218 return True
219 else:
220 return False
221
c9dd311 Mike added tron(y) mode.
authored
222 def move(self, trailing=False):
faa87d1 Mike added Snake, Fruit, Tally classes
authored
223 """
224 This will update coords for snake, moving it one cell in given direction.
225 It also factors in and updates growth if any growth is "owed" snake (one per game iteration).
226 If snake is dead, will only remove the last segment of snake and ignore direction / not move snake.
227 """
228 if self.alive:
229 # delete last segment first.
230 if self.growth < 0:
231 self.growth = self.growth + 1
232 if len(self.coords) > 3:
233 # implement negative growth by removing last two segments
234 del self.coords[-2:]
235 else:
236 # snake is too short -- remove last segment as normal
237 del self.coords[-1]
238 elif self.growth > 0:
239 # implement positive growth by not deleting last segment
c9dd311 Mike added tron(y) mode.
authored
240 self.growth = self.growth - 1
241 elif trailing == False:
242 # no growth factor, delete last segment if trailing is off
faa87d1 Mike added Snake, Fruit, Tally classes
authored
243 del self.coords[-1]
244
245 # determine new head coordinates by direction
246 if self.direction == UP:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
247 newhead = {'x': self.coords[HEAD]['x'],
248 'y': self.coords[HEAD]['y'] - 1}
faa87d1 Mike added Snake, Fruit, Tally classes
authored
249 elif self.direction == DOWN:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
250 newhead = {'x': self.coords[HEAD]['x'],
251 'y': self.coords[HEAD]['y'] + 1}
faa87d1 Mike added Snake, Fruit, Tally classes
authored
252 elif self.direction == LEFT:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
253 newhead = {'x': self.coords[HEAD]['x'] - 1,
254 'y': self.coords[HEAD]['y']}
faa87d1 Mike added Snake, Fruit, Tally classes
authored
255 elif self.direction == RIGHT:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
256 newhead = {'x': self.coords[HEAD]['x'] + 1,
257 'y': self.coords[HEAD]['y']}
c9dd311 Mike added tron(y) mode.
authored
258
faa87d1 Mike added Snake, Fruit, Tally classes
authored
259 # insert new head segment
260 self.coords.insert(HEAD, newhead)
261
262 # dead snake -- remove last segment as long as it isn't the last
263 elif len(self.coords) > 1:
264 del self.coords[-1]
265
266 def drawSnake(self):
267 """
268 Responsible for drawing snake image to screen.
269 """
270 for coord in self.coords:
271 x = coord['x'] * CELLSIZE
272 y = coord['y'] * CELLSIZE
273 snakeSegmentRect = pygame.Rect(x, y, CELLSIZE, CELLSIZE)
4ae7881 Mike Fixed grid and snake color changes.
authored
274 pygame.draw.rect(DISPLAYSURF, self.colorBorderCurrent, snakeSegmentRect)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
275 snakeInnerSegmentRect = pygame.Rect(x + 4, y + 4, CELLSIZE - 8, CELLSIZE - 8)
4ae7881 Mike Fixed grid and snake color changes.
authored
276 pygame.draw.rect(DISPLAYSURF, self.colorCurrent, snakeInnerSegmentRect)
6d8cfaf Mike set-up ai
authored
277
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
278 def drawScore(self, position, allsnake):
6d8cfaf Mike set-up ai
authored
279 """
280 Responsible for drawing snake score to screen.
281 """
4ae7881 Mike Fixed grid and snake color changes.
authored
282 scoreSurf = BASICFONT.render('%s: %s' % (self.name, self.score), True, self.colorCurrent)
6d8cfaf Mike set-up ai
authored
283 scoreRect = scoreSurf.get_rect()
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
284 scoreRect.topleft = (getPosition(position, allsnake), 1)
6d8cfaf Mike set-up ai
authored
285 DISPLAYSURF.blit(scoreSurf, scoreRect)
286
287
288 class Opponent(Snake):
289 """
290 Derived from Snake class, this adds functionality for determining direction.
291 """
6127227 Mike Added more selection for Duel Mode.
authored
292 def __init__(self, n='bot', c=False, sc=COBALTGREEN, sb=GOLDENROD, r=20, p=10):
293 Snake.__init__(self, n, c, sc, sb)
6d8cfaf Mike set-up ai
authored
294 self.avoidBoundaries = True
c134769 Mike fixed key input bug
authored
295 self.randomness = r
6d8cfaf Mike set-up ai
authored
296 self.preferSameDirection = p
297
298 def updateDirection(self, grid):
299 # all directions have value adjusted
6c613da Mike Worked on AI; added crude apple detection.
authored
300 nextDirection = {LEFT:0, RIGHT:0, UP:0, DOWN:0}
6d8cfaf Mike set-up ai
authored
301
302 # coords of own snake head
303 x = self.coords[HEAD]['x']
304 y = self.coords[HEAD]['y']
305
306 # opposite direction kills snake
307 if self.direction == LEFT:
6c613da Mike Worked on AI; added crude apple detection.
authored
308 nextDirection[RIGHT] = nextDirection[RIGHT] - 100
6d8cfaf Mike set-up ai
authored
309 elif self.direction == RIGHT:
6c613da Mike Worked on AI; added crude apple detection.
authored
310 nextDirection[LEFT] = nextDirection[LEFT] - 100
6d8cfaf Mike set-up ai
authored
311 elif self.direction == UP:
6c613da Mike Worked on AI; added crude apple detection.
authored
312 nextDirection[DOWN] = nextDirection[DOWN] - 100
6d8cfaf Mike set-up ai
authored
313 elif self.direction == DOWN:
6c613da Mike Worked on AI; added crude apple detection.
authored
314 nextDirection[UP] = nextDirection[UP]- 100
6d8cfaf Mike set-up ai
authored
315
316 # avoid boundaries
317 if self.avoidBoundaries == True:
318 if x == 0:
6c613da Mike Worked on AI; added crude apple detection.
authored
319 nextDirection[LEFT] = nextDirection[LEFT] - 100
6d8cfaf Mike set-up ai
authored
320 if x == CELLWIDTH - 1:
6c613da Mike Worked on AI; added crude apple detection.
authored
321 nextDirection[RIGHT] = nextDirection[RIGHT] - 100
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
322 if y == (TOP_BUFFER / CELLSIZE):
6c613da Mike Worked on AI; added crude apple detection.
authored
323 nextDirection[UP] = nextDirection[UP] - 100
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
324 if y == CELLHEIGHT + (TOP_BUFFER / CELLSIZE) - 1:
6c613da Mike Worked on AI; added crude apple detection.
authored
325 nextDirection[DOWN] = nextDirection[DOWN] - 100
6d8cfaf Mike set-up ai
authored
326
327 # prefer same direction
6c613da Mike Worked on AI; added crude apple detection.
authored
328 nextDirection[self.direction] = nextDirection[self.direction] + self.preferSameDirection
6d8cfaf Mike set-up ai
authored
329
330 # avoid immediate snakes
331 if grid.has_key((x-1,y)) and (grid[(x-1,y)] == 'snake'):
6c613da Mike Worked on AI; added crude apple detection.
authored
332 nextDirection[LEFT] = nextDirection[LEFT] - 100
6d8cfaf Mike set-up ai
authored
333 if grid.has_key((x+1,y)) and (grid[(x+1,y)] == 'snake'):
6c613da Mike Worked on AI; added crude apple detection.
authored
334 nextDirection[RIGHT] = nextDirection[RIGHT] - 100
6d8cfaf Mike set-up ai
authored
335 if grid.has_key((x,y-1)) and (grid[(x,y-1)] == 'snake'):
6c613da Mike Worked on AI; added crude apple detection.
authored
336 nextDirection[UP] = nextDirection[UP] - 100
337 if grid.has_key((x,y+1)) and (grid[(x,y+1)] == 'snake'):
338 nextDirection[DOWN] = nextDirection[DOWN] - 100
339
340 # favor direction of apple -- this approach will need to be replaced eventually
341 for cell in grid:
342 if grid[cell] == 'apple':
343 # get x and y differences and favor direction of apple inversely proportionate to distance
344 x_difference = cell[0] - x
345 y_difference = cell[1] - y
346 if x_difference > 0:
347 nextDirection[RIGHT] = nextDirection[RIGHT] + (CELLWIDTH - x_difference)
348 else:
349 nextDirection[LEFT] = nextDirection[LEFT] + (CELLWIDTH - x_difference)
350 if y_difference < 0:
351 nextDirection[UP] = nextDirection[UP] + (CELLHEIGHT - y_difference)
352 else:
353 nextDirection[DOWN] = nextDirection[DOWN] + (CELLHEIGHT - y_difference)
6d8cfaf Mike set-up ai
authored
354
355 # factor in randomness
6c613da Mike Worked on AI; added crude apple detection.
authored
356 for d in nextDirection:
357 nextDirection[d] = nextDirection[d] + random.randint(0,self.randomness)
6d8cfaf Mike set-up ai
authored
358
359 # report if debugging
360 if DEBUG == True:
361 print self.name
6c613da Mike Worked on AI; added crude apple detection.
authored
362 print nextDirection
6d8cfaf Mike set-up ai
authored
363
364 # update snake direction to direction with highest score
6c613da Mike Worked on AI; added crude apple detection.
authored
365 self.direction = max(nextDirection, key=nextDirection.get)
6d8cfaf Mike set-up ai
authored
366
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
367 def getPlace(self, totaldead, totalsnakes):
368 return Snake.getPlace(self, totaldead, totalsnakes)
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
369
6d8cfaf Mike set-up ai
authored
370 def updateScore(self, points_input):
371 Snake.updateScore(self, points_input)
372
373 def updateGrowth(self, growth_input):
374 Snake.updateGrowth(self, growth_input)
375
376 def updateMultiplier(self, multiplier_input, timer_input):
377 Snake.updateMultiplier(self, multiplier_input, timer_input)
378
379 def boundsCollision(self):
380 return Snake.boundsCollision(self)
381
382 def snakeCollision(self, snake):
383 return Snake.snakeCollision(self, snake)
384
385 def fruitCollision(self, fruit):
386 return Snake.fruitCollision(self, fruit)
387
c9dd311 Mike added tron(y) mode.
authored
388 def move(self, trailing):
389 Snake.move(self, trailing)
6d8cfaf Mike set-up ai
authored
390
391 def drawSnake(self):
392 Snake.drawSnake(self)
393
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
394 def drawScore(self, position, allsnake):
395 Snake.drawScore(self, position, allsnake)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
396
b68496b Mike first commit
authored
397
398 class Fruit:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
399 """
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
400 Fruit class houses all information for fruit objects.
401 Base class is not meant to be instantiated, but rather provide base methods shared by all fruit.
faa87d1 Mike added Snake, Fruit, Tally classes
authored
402 """
403 def __init__(self):
404 self.timer = 0
405
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
406 def getRandomLocation(self, allfruit, allsnake, game):
faa87d1 Mike added Snake, Fruit, Tally classes
authored
407 """
408 Returns random coordinates (for fruit to be placed). Ensures that coordinates are not occupied by fruit or snake head.
409 Will keep fruit away from edges (outside 20%) if in an "easy mode" determined in Tally object.
410 """
b68496b Mike first commit
authored
411 while True:
412 conflict = False
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
413 if game.checkEasyTrigger():
b68496b Mike first commit
authored
414 x = random.randint(int(CELLWIDTH/5), CELLWIDTH - int(CELLWIDTH/5) - 1)
415 y = random.randint(int(CELLHEIGHT/5), CELLHEIGHT - int(CELLHEIGHT/5) - 1)
416 else:
417 x = random.randint(0, CELLWIDTH - 1)
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
418 y = random.randint((TOP_BUFFER / CELLSIZE), CELLHEIGHT - 1)
b68496b Mike first commit
authored
419 # ensure coordinates are not already occupied by fruit
420 for fruit in allfruit:
421 if fruit.coords['x'] == x and fruit.coords['y'] == y:
422 conflict = True
423 # ensure coordinates are not already occupied by snake head
424 for snake in allsnake:
425 if snake.coords[HEAD]['x'] == x and snake.coords[HEAD]['y'] == y:
426 conflict = True
427 if conflict == False:
428 return {'x':x, 'y':y}
429
faa87d1 Mike added Snake, Fruit, Tally classes
authored
430 def updateTimer(self):
431 """
432 Returns true and decrements if there is still time left for fruit to be on screen.
433 """
b68496b Mike first commit
authored
434 if self.timer > 0:
435 self.timer = self.timer - 1
436 return True
437 else:
438 return False
439
faa87d1 Mike added Snake, Fruit, Tally classes
authored
440 def drawFruit(self):
441 """
442 Responsible for drawing fruit image to screen.
443 """
444 x = self.coords['x'] * CELLSIZE
445 y = self.coords['y'] * CELLSIZE
446 fruitRect = pygame.Rect(x, y, CELLSIZE, CELLSIZE)
447 pygame.draw.rect(DISPLAYSURF, self.color, fruitRect)
448
449
450 class Apple(Fruit):
451 """
452 Apples are a unique fruit in that they never leave the screen and once one is eaten, it is always replaced with another.
453 They also add points and one growth
454 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
455 def __init__(self, allfruit, allsnake, game):
456 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
457 self.color = RED
458 self.points = 10
459 self.growth = 1
460
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
461 def isEaten(self, snake, game):
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
462 snake.fruitEaten['apple'] = snake.fruitEaten['apple'] + 1
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
463 game.fruitEaten['apple'] = game.fruitEaten['apple'] + 1
faa87d1 Mike added Snake, Fruit, Tally classes
authored
464 snake.updateScore(self.points)
465 snake.updateGrowth(self.growth)
466
467 def drawFruit(self):
468 Fruit.drawFruit(self)
469
470
471 class Poison(Fruit):
472 """
473 Poison will shorten a snake (by adding a negative growth value) and reduce points.
474 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
475 def __init__(self, allfruit, allsnake, game):
476 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
477 self.timer = random.randint(POISONTIMER[0], POISONTIMER[1])
478 self.color = GREEN
479 self.points = -25
480 self.growth = -3
481
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
482 def isEaten(self, snake, game):
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
483 snake.fruitEaten['poison'] = snake.fruitEaten['poison'] + 1
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
484 game.fruitEaten['poison'] = game.fruitEaten['poison'] + 1
faa87d1 Mike added Snake, Fruit, Tally classes
authored
485 snake.updateScore(self.points)
486 snake.updateGrowth(self.growth)
487
488 def updateTimer(self):
489 return Fruit.updateTimer(self)
490
491 def drawFruit(self):
492 Fruit.drawFruit(self)
493
494
495 class Orange(Fruit):
496 """
497 Orange will grow snake substantially and are worth points.
498 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
499 def __init__(self, allfruit, allsnake, game):
500 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
501 self.timer = random.randint(ORANGETIMER[0], ORANGETIMER[1])
502 self.color = ORANGE
503 self.points = 50
504 self.growth = 3
505
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
506 def isEaten(self, snake, game):
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
507 snake.fruitEaten['orange'] = snake.fruitEaten['orange'] + 1
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
508 game.fruitEaten['orange'] = game.fruitEaten['orange'] + 1
faa87d1 Mike added Snake, Fruit, Tally classes
authored
509 snake.updateScore(self.points)
510 snake.updateGrowth(self.growth)
511
512 def updateTimer(self):
513 return Fruit.updateTimer(self)
514
515 def drawFruit(self):
516 Fruit.drawFruit(self)
517
518
519 class Raspberry(Fruit):
520 """
521 Raspberry will set snake's multiplier to two for a period of time.
522 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
523 def __init__(self, allfruit, allsnake, game):
524 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
525 self.timer = random.randint(RASPBERRYTIMER[0], RASPBERRYTIMER[1])
526 self.color = PURPLE
527 self.multiplier = 2
528 self.multipliertimer = 100
529
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
530 def isEaten(self, snake, game):
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
531 snake.fruitEaten['raspberry'] = snake.fruitEaten['raspberry'] + 1
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
532 game.fruitEaten['raspberry'] = game.fruitEaten['raspberry'] + 1
faa87d1 Mike added Snake, Fruit, Tally classes
authored
533 snake.updateMultiplier(self.multiplier, self.multipliertimer)
534
535 def updateTimer(self):
536 return Fruit.updateTimer(self)
537
538 def drawFruit(self):
539 Fruit.drawFruit(self)
540
541
542 class Blueberry(Fruit):
543 """
544 Blueberry will reduce the frame rate (slowing down game iterations) for a period of time.
545 It is also worth a lot of points.
546 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
547 def __init__(self, allfruit, allsnake, game):
548 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
549 self.timer = random.randint(BLUEBERRYTIMER[0], BLUEBERRYTIMER[1])
550 self.color = BLUE
551 self.score = 100
a734fdb Mike Added snake choices for duel mode.
authored
552 self.slowtimer = 80
faa87d1 Mike added Snake, Fruit, Tally classes
authored
553
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
554 def isEaten(self, snake, game):
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
555 snake.fruitEaten['blueberry'] = snake.fruitEaten['blueberry'] + 1
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
556 game.fruitEaten['blueberry'] = game.fruitEaten['blueberry'] + 1
faa87d1 Mike added Snake, Fruit, Tally classes
authored
557 snake.updateScore(self.score)
558
559 def updateTimer(self):
560 return Fruit.updateTimer(self)
561
562 def drawFruit(self):
563 Fruit.drawFruit(self)
564
565
566 class Lemon(Fruit):
ff23b3c Mike Worked on AI.
authored
567 """
4ae7881 Mike Fixed grid and snake color changes.
authored
568 TBD... currently worth 1000 points.
569 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
570 def __init__(self, allfruit, allsnake, game):
571 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
572 self.timer = random.randint(LEMONTIMER[0], LEMONTIMER[1])
573 self.color = YELLOW
574 self.score = 1000
575
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
576 def isEaten(self, snake, game):
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
577 snake.fruitEaten['lemon'] = snake.fruitEaten['lemon'] + 1
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
578 game.fruitEaten['lemon'] = game.fruitEaten['lemon'] + 1
faa87d1 Mike added Snake, Fruit, Tally classes
authored
579 snake.updateScore(self.score)
580
581 def updateTimer(self):
582 return Fruit.updateTimer(self)
583
584 def drawFruit(self):
585 Fruit.drawFruit(self)
586
587
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
588 class GameData:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
589 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
590 Responsible for dynamics for a particular game instance.
faa87d1 Mike added Snake, Fruit, Tally classes
authored
591 fruitEaten - a dictionary containing a numeric tally of each fruit eaten.
592 speedTrigger - the frequency (based on apples consumed) in which gamespeed is increased by one.
593 bonusTrigger - the frequency (based on apples consumed) in which a bonus game - runBonus() - is launched.
594 easyTrigger - a threshold (apples consumed); once reached fruit can be placed anywhere on screen (as opposed to away from edges).
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
595 currentplace - the current 'place' of snake. When snake has died.
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
596 apples - number of apples on screen.
faa87d1 Mike added Snake, Fruit, Tally classes
authored
597 typeMin - the minimum value in determining bonus game type.
598 typeMax - the maximum value in determining bonus game type.
599 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
600 def __init__(self, st=20, bt=10, et=20, a=1, tmin=1, tmax=10):
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
601 self.fruitEaten = {'apple':0, 'poison':0, 'orange':0,
602 'raspberry':0, 'blueberry':0, 'lemon':0}
faa87d1 Mike added Snake, Fruit, Tally classes
authored
603 self.speedTrigger = st
604 self.bonusTrigger = bt
605 self.easyTrigger = et
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
606 self.currentplace = 1
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
607 self.apples = a
faa87d1 Mike added Snake, Fruit, Tally classes
authored
608 self.typeMin = tmin
609 self.typeMax = tmax
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
610 self.basespeed = FPS
611 self.currentspeed = self.basespeed
612 self.slowtimer = 0
c9dd311 Mike added tron(y) mode.
authored
613 self.trailing = False
faa87d1 Mike added Snake, Fruit, Tally classes
authored
614
615 def checkSpeedTrigger(self):
616 """
617 Returns true if number of apples consumed modulo speedTrigger equals zero.
618 """
619 if self.fruitEaten['apple'] % self.speedTrigger == 0:
620 return True
621 else:
622 return False
623
624 def checkBonusTrigger(self):
625 """
626 Returns true if number of apples consumed modulo bonusTrigger equals zero.
627 """
628 if self.fruitEaten['apple'] % self.bonusTrigger == 0:
629 return True
630 else:
631 return False
632
633 def checkEasyTrigger(self):
634 """
635 Returns true if number of apples consumed is less than or equal to easyTrigger.
636 """
637 if self.fruitEaten['apple'] <= self.easyTrigger:
638 return True
639 else:
640 return False
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
641
642 def checkSnakeDeath(self, allsnake):
643 """
644 Returns true if there are no more living snakes.
645 Sets place of snake if recently died.
646 """
647 gameover = True
648 for snake in allsnake:
649 if snake.alive == True:
650 gameover = False
651 elif snake.place == False:
652 snake.place = self.currentplace
653 self.currentplace = self.currentplace + 1
654 return gameover
655
656 def updateBaseSpeed(self, value):
657 """
658 Updates basespeed by value inputted.
659 Checks against parameters
660 """
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
661 if (self.basespeed + value > MIN_FPS) and \
662 (self.basespeed + value < MAX_FPS):
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
663 self.basespeed = self.basespeed + value
664 self.currentspeed = self.basespeed
665
666 def updateCurrentSpeed(self, goal=False, force=False):
667 """
668 Adjusts currentspeed one towards goal.
669 Goal defaults to basespeed.
670 Optional 'force' will set currentspeed to goal instead.
671 """
672 if goal == False:
673 goal = self.basespeed
674
675 if force != False:
676 self.currentspeed = goal
677 else:
678 if self.currentspeed < goal:
679 self.currentspeed = self.currentspeed + 1
680 elif self.currentspeed > goal:
681 self.currentspeed = self.currentspeed - 1
682
683 def checkSlowTimer(self):
684 """
685 Returns true if slowtimer is greater than 0.
686 """
687 if self.slowtimer > 0:
688 return True
689 else:
690 return False
691
692 def updateSlowTimer(self):
693 """
694 Decrements slowtimer by one
695 """
696 self.slowtimer = self.slowtimer - 1
faa87d1 Mike added Snake, Fruit, Tally classes
authored
697
698 def runBonus(self):
699 """
700 Returns a list containing fruit (as strings) to be added to game from bonus game.
701 An integer (determined randomly between typeMin and typeMax) corresponds to bonus game run.
702 A basic set-up would randomly choose between 1 and 10; 6 through 10 initiating a fruit specific bonus.
703 Default will contain an assortment of fruit.
704 """
705 bonus = []
706 type = random.randint(self.typeMin, self.typeMax)
707 if type == LEMONBONUS:
708 bonus.append('lemon')
709 elif type == POISONBONUS:
710 counter = random.randint(20,35)
711 while counter > 0:
712 bonus.append('poison')
713 counter = counter - 1
714 elif type == ORANGEBONUS:
715 counter = random.randint(20,35)
716 while counter > 0:
717 bonus.append('orange')
718 counter = counter - 1
719 elif type == RASPBERRYBONUS:
720 counter = random.randint(20,35)
721 while counter > 0:
722 bonus.append('raspberry')
723 counter = counter - 1
724 elif type == BLUEBERRYBONUS:
725 counter = random.randint(20,30)
726 while counter > 0:
727 bonus.append('blueberry')
728 counter = counter - 1
729 else: # default bonus
730 counter = random.randint(0,3)
731 while counter > 0:
732 bonus.append('poison')
733 counter = counter - 1
734 counter = random.randint(5,20)
735 while counter > 0:
736 bonus.append('orange')
737 counter = counter - 1
738 counter = random.randint(1,4)
739 while counter > 0:
740 bonus.append('raspberry')
741 counter = counter - 1
742 counter = random.randint(0,2)
743 while counter > 0:
744 bonus.append('blueberry')
745 counter = counter - 1
746 return bonus
747
b68496b Mike first commit
authored
748
749 class Button():
6d8cfaf Mike set-up ai
authored
750 """
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
751 A clickable button that is rendered on screen.
752 """
b68496b Mike first commit
authored
753 def __init__(self, text, x, y):
754 self.text = text
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
755 startSurf = BUTTONFONT.render(self.text, True, BUTTONCLR, BUTTONTXT)
b68496b Mike first commit
authored
756 self.rect = startSurf.get_rect()
757 self.rect.center = x,y
758
759 def display(self):
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
760 startSurf = BUTTONFONT.render(self.text, True, BUTTONCLR, BUTTONTXT)
b68496b Mike first commit
authored
761 DISPLAYSURF.blit(startSurf, self.rect)
762
6127227 Mike Added more selection for Duel Mode.
authored
763 def pressed(self, mouse):
b68496b Mike first commit
authored
764 if mouse[0] > self.rect.topleft[0]:
765 if mouse[1] > self.rect.topleft[1]:
766 if mouse[0] < self.rect.bottomright[0]:
767 if mouse[1] < self.rect.bottomright[1]:
768 return True
769 else: return False
770 else: return False
771 else: return False
772 else: return False
773
774
6127227 Mike Added more selection for Duel Mode.
authored
775 class SelectButton(Button):
776 """
777 Selected by color. Clicking will turn active state to True.
778 """
779 def __init__(self, text, x, y, a=False):
780 Button.__init__(self, text, x, y)
781 self.active = a
782
783 def display(self):
784 if self.active == True:
c9dd311 Mike added tron(y) mode.
authored
785 startSurf = BUTTONFONT.render(self.text, True, BUTTONCLR_SL, BUTTONTXT_SL)
6127227 Mike Added more selection for Duel Mode.
authored
786 else:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
787 startSurf = BUTTONFONT.render(self.text, True, BUTTONCLR, BUTTONTXT)
6127227 Mike Added more selection for Duel Mode.
authored
788
789 DISPLAYSURF.blit(startSurf, self.rect)
790
791 def pressed(self, mouse):
792 return Button.pressed(self, mouse)
793
794 def setActive(self, buttonlist):
795 for button in buttonlist:
796 if button == self:
797 self.active = True
798 else:
799 button.active = False
800
801
b68496b Mike first commit
authored
802 def main():
6d8cfaf Mike set-up ai
authored
803 global FPSCLOCK, DISPLAYSURF, BASICFONT, BUTTONFONT, DEBUG
804
805 # for debugging
806 if len(sys.argv) < 2:
807 DEBUG = False
808 else:
809 DEBUG = True
b68496b Mike first commit
authored
810
811 pygame.init()
812 FPSCLOCK = pygame.time.Clock()
813 DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
814 BASICFONT = pygame.font.Font('freesansbold.ttf', 18)
9504e62 Mike added party mode.
authored
815 BUTTONFONT = pygame.font.Font('freesansbold.ttf', 30)
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
816 pygame.display.set_caption('Snakey Party')
b68496b Mike first commit
authored
817
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
818 titleFont = pygame.font.Font('freesansbold.ttf', 64)
819 titleSurf = titleFont.render('Snakey Party', True, WHITE, FORESTGREEN)
820 titleRect = titleSurf.get_rect()
9504e62 Mike added party mode.
authored
821 titleRect.center = (WINDOWWIDTH / 2, WINDOWHEIGHT * 2/8)
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
822
9504e62 Mike added party mode.
authored
823 arcadebutton = Button('(a)rcade mode', WINDOWWIDTH / 2, WINDOWHEIGHT * 3/8)
824 duelbutton = Button('(d)uel mode', WINDOWWIDTH / 2, WINDOWHEIGHT * 4/8)
825 partybutton = Button('(p)arty mode', WINDOWWIDTH / 2, WINDOWHEIGHT * 5/8)
c9dd311 Mike added tron(y) mode.
authored
826 tronybutton = Button('(t)ron-y mode', WINDOWWIDTH / 2, WINDOWHEIGHT * 6/8)
827 instructbutton = Button('(i)nstructions', WINDOWWIDTH / 2, WINDOWHEIGHT * 7/8)
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
828
829 while True: ### need to update this
830
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
831 DISPLAYSURF.fill(BACKGROUNDCOLOR)
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
832 DISPLAYSURF.blit(titleSurf, titleRect)
833 arcadebutton.display()
834 duelbutton.display()
9504e62 Mike added party mode.
authored
835 partybutton.display()
c9dd311 Mike added tron(y) mode.
authored
836 tronybutton.display()
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
837 instructbutton.display()
838
839 for event in pygame.event.get():
840 if event.type == QUIT:
841 terminate()
842 elif event.type == MOUSEBUTTONDOWN:
843 mouse = pygame.mouse.get_pos()
844 if arcadebutton.pressed(mouse):
845 pygame.event.get()
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
846 game = GameData()
6127227 Mike Added more selection for Duel Mode.
authored
847 runGame(game, [SNAKEY])
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
848 showGameOverScreen()
849 elif duelbutton.pressed(mouse):
850 pygame.event.get()
6127227 Mike Added more selection for Duel Mode.
authored
851 players = False
852 players = showSelectPlayersScreen()
853 if players != False:
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
854 game = GameData(10, 10, 9, 2)
6127227 Mike Added more selection for Duel Mode.
authored
855 runGame(game, players)
a734fdb Mike Added snake choices for duel mode.
authored
856 showGameOverScreen()
9504e62 Mike added party mode.
authored
857 elif partybutton.pressed(mouse):
858 pygame.event.get()
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
859 game = GameData(25, 12, 0, 4)
6127227 Mike Added more selection for Duel Mode.
authored
860 runGame(game, [SNAKEY, LINUS, WIGGLES, GIGGLES])
9504e62 Mike added party mode.
authored
861 showGameOverScreen()
c9dd311 Mike added tron(y) mode.
authored
862 elif tronybutton.pressed(mouse):
863 pygame.event.get()
864 game = GameData(25, 12, 0, 0)
865 game.trailing = True
866 runGame(game, [SNAKEY, LINUS, WIGGLES, GIGGLES])
867 showGameOverScreen()
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
868 elif instructbutton.pressed(mouse):
869 showInstructScreen()
870 elif event.type == KEYDOWN:
871 if event.key == K_a:
872 pygame.event.get()
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
873 game = GameData()
6127227 Mike Added more selection for Duel Mode.
authored
874 runGame(game, [SNAKEY])
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
875 showGameOverScreen()
876 elif event.key == K_d:
877 pygame.event.get()
6127227 Mike Added more selection for Duel Mode.
authored
878 players = False
879 players = showSelectPlayersScreen()
880 if players != False:
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
881 game = GameData(10, 10, 9, 2)
6127227 Mike Added more selection for Duel Mode.
authored
882 runGame(game, players)
a734fdb Mike Added snake choices for duel mode.
authored
883 showGameOverScreen()
9504e62 Mike added party mode.
authored
884 elif event.key == K_p:
885 pygame.event.get()
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
886 game = GameData(25, 12, 0, 4)
6127227 Mike Added more selection for Duel Mode.
authored
887 runGame(game, [SNAKEY, LINUS, WIGGLES, GIGGLES])
9504e62 Mike added party mode.
authored
888 showGameOverScreen()
c9dd311 Mike added tron(y) mode.
authored
889 elif event.key == K_t:
890 pygame.event.get()
891 game = GameData(25, 12, 0, 0)
892 game.trailing = True
893 runGame(game, [SNAKEY, LINUS, WIGGLES, GIGGLES])
894 showGameOverScreen()
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
895 elif event.key == K_i:
896 showInstructScreen()
897 elif event.key == K_ESCAPE or event.key == K_q:
898 terminate()
899
6127227 Mike Added more selection for Duel Mode.
authored
900 game = False
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
901 pygame.display.update()
902 FPSCLOCK.tick(FPS)
9504e62 Mike added party mode.
authored
903
b68496b Mike first commit
authored
904
6127227 Mike Added more selection for Duel Mode.
authored
905 def runGame(game, players=[]):
b68496b Mike first commit
authored
906
6d8cfaf Mike set-up ai
authored
907 # in game variables
faa87d1 Mike added Snake, Fruit, Tally classes
authored
908 allsnake = []
909 allfruit = []
6127227 Mike Added more selection for Duel Mode.
authored
910 nextEvent = 0
faa87d1 Mike added Snake, Fruit, Tally classes
authored
911
6127227 Mike Added more selection for Duel Mode.
authored
912 # create snakes based on name. 'player' is set to false initially to handle input
913 player = False
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
914 pos = 1
6127227 Mike Added more selection for Duel Mode.
authored
915 for snake in players:
916 if snake == SNAKEY:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
917 player = Snake(SNAKEY, getStartCoords(pos))
6127227 Mike Added more selection for Duel Mode.
authored
918 allsnake.append(player)
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
919 pos = pos + 1
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
920 elif snake == LINUS:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
921 linus = Opponent(LINUS, getStartCoords(pos), IVORY, COBALTGREEN, 5, 20)
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
922 allsnake.append(linus)
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
923 pos = pos + 1
6127227 Mike Added more selection for Duel Mode.
authored
924 elif snake == WIGGLES:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
925 wiggles = Opponent(WIGGLES, getStartCoords(pos), OLIVEGREEN, PURPLE, 20, 5)
6127227 Mike Added more selection for Duel Mode.
authored
926 allsnake.append(wiggles)
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
927 pos = pos + 1
6127227 Mike Added more selection for Duel Mode.
authored
928 elif snake == GIGGLES:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
929 giggles = Opponent(GIGGLES, getStartCoords(pos), PURPLE, EMERALDGREEN, 10, 10)
6127227 Mike Added more selection for Duel Mode.
authored
930 allsnake.append(giggles)
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
931 pos = pos + 1
b68496b Mike first commit
authored
932
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
933 # create initial apple(s)
934 appleCounter = game.apples
935 while appleCounter > 0:
936 a = Apple(allfruit, allsnake, game)
937 allfruit.append(a)
938 appleCounter = appleCounter - 1
2199376 Mike changed intro menu; added arcade mode & duel mode.
authored
939
faa87d1 Mike added Snake, Fruit, Tally classes
authored
940 # main game loop
941 while True:
6127227 Mike Added more selection for Duel Mode.
authored
942
6d8cfaf Mike set-up ai
authored
943 # get grid representation for AIs
944 grid = getGrid(allsnake, allfruit)
945
6127227 Mike Added more selection for Duel Mode.
authored
946 # event handling loop -- get player's direction choice
947 stop = False
948
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
949 # get events in queue. This updates players direction and other key instructions (quit, debug...)
950 # if the next event after direction update suggests sharp direction change, following direction is stored.
faa87d1 Mike added Snake, Fruit, Tally classes
authored
951 for event in pygame.event.get():
b68496b Mike first commit
authored
952 if event.type == QUIT:
953 terminate()
6127227 Mike Added more selection for Duel Mode.
authored
954 elif nextEvent != 0 and player != False:
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
955 player.direction = nextEvent
956 nextEvent = 0
957 stop = True
6127227 Mike Added more selection for Duel Mode.
authored
958 # check for exit/quit/debug keys
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
959 if event.type == KEYDOWN and \
960 (event.key == K_ESCAPE or event.key == K_q):
6127227 Mike Added more selection for Duel Mode.
authored
961 terminate()
962 elif event.type == KEYDOWN and event.key == K_e:
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
963 showGameStats(allsnake)
6127227 Mike Added more selection for Duel Mode.
authored
964 return 1
965 elif event.type == KEYDOWN and event.key == K_g and DEBUG == True:
966 stop = True
967 debugPrintGrid(grid)
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
968 # if player is dead / does not exist - check for speed controls
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
969 elif event.type == KEYDOWN and event.key == K_f and \
970 (player == False or player.alive == False):
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
971 game.updateBaseSpeed(10)
972 game.updateCurrentSpeed(False, True)
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
973 elif event.type == KEYDOWN and event.key == K_s and \
974 (player == False or player.alive == False):
ef0acb2 Mike consolidated game over sequence.
authored
975 game.updateBaseSpeed(-10)
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
976 game.updateCurrentSpeed(False, True)
6127227 Mike Added more selection for Duel Mode.
authored
977
978 # if player exists - check for direction input
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
979 if event.type == KEYDOWN and \
980 player != False and stop == False:
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
981 if event.key == K_LEFT and player.direction != RIGHT:
6d8cfaf Mike set-up ai
authored
982 player.direction = LEFT
b68496b Mike first commit
authored
983 stop = True
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
984 elif event.key == K_RIGHT and player.direction != LEFT:
6d8cfaf Mike set-up ai
authored
985 player.direction = RIGHT
b68496b Mike first commit
authored
986 stop = True
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
987 elif event.key == K_UP and player.direction != DOWN:
6d8cfaf Mike set-up ai
authored
988 player.direction = UP
b68496b Mike first commit
authored
989 stop = True
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
990 elif event.key == K_DOWN and player.direction != UP:
6d8cfaf Mike set-up ai
authored
991 player.direction = DOWN
6127227 Mike Added more selection for Duel Mode.
authored
992
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
993 # peak into very next event. If key suggests sharp direction change, store in nextEvent
6127227 Mike Added more selection for Duel Mode.
authored
994 elif event.type == KEYDOWN and player != False and nextEvent == 0:
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
995 if event.key == K_LEFT and player.direction != RIGHT:
996 nextEvent = LEFT
997 elif event.key == K_RIGHT and player.direction != LEFT:
998 nextEvent = RIGHT
999 elif event.key == K_UP and player.direction != DOWN:
1000 nextEvent = UP
1001 elif event.key == K_DOWN and player.direction != UP:
1002 nextEvent = DOWN
1003 elif event.key == K_ESCAPE or event.key == K_q:
1004 terminate()
1005 elif event.key == K_g and DEBUG == True:
1006 debugPrintGrid(grid)
6d8cfaf Mike set-up ai
authored
1007
1008 if DEBUG == True:
1009 debugPause()
1010
1011 # update all other snake's direction choice
1012 for snake in allsnake:
1013 if snake.alive and snake.player == False:
1014 snake.updateDirection(grid)
b68496b Mike first commit
authored
1015
6d8cfaf Mike set-up ai
authored
1016 # collision detection
b68496b Mike first commit
authored
1017 for snake in allsnake:
6d8cfaf Mike set-up ai
authored
1018 # check if the snake has hit boundary
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1019 if snake.alive and snake.boundsCollision():
b68496b Mike first commit
authored
1020 snake.alive = False
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1021 # check if snake has hit another snake
1022 for othersnake in allsnake:
1023 if snake.alive and snake.snakeCollision(othersnake):
b68496b Mike first commit
authored
1024 snake.alive = False
1025
1026 # check score - change color accordingly
1027 # only looks at player snake
6127227 Mike Added more selection for Duel Mode.
authored
1028 if player != False:
1029 if player.score > 2000:
1030 player.color = SIENNA
1031 player.colorBorder = CORAL
1032 elif player.score > 1500:
1033 player.color = CORAL
1034 player.colorBorder = GOLDENROD
1035 elif player.score > 1250:
1036 player.color = GOLDENROD
1037 player.colorBorder = EMERALDGREEN
1038 elif player.score > 1000:
1039 player.color = KHAKI
1040 player.colorBorder = LIGHTYELLOW
1041 elif player.score > 750:
1042 player.color = YELLOW
1043 player.colorBorder = GREEN
1044 elif player.score > 500:
1045 player.color = LIGHTYELLOW
1046 player.colorBorder = FORESTGREEN
1047 elif player.score > 400:
1048 player.color = IVORY #change this
1049 player.colorBorder = FORESTGREEN
1050 elif player.score > 300:
1051 player.color = GREENYELLOW
1052 player.colorBorder = OLIVEGREEN
1053 elif player.score > 200:
1054 player.color = HONEYDEW
1055 player.colorBorder = SEAGREEN
1056 elif player.score > 100:
1057 player.color = SEAGREEN
1058 player.colorBorder = EMERALDGREEN
1059 else:
1060 player.color = GREEN
1061 player.colorBorder = COBALTGREEN
b68496b Mike first commit
authored
1062
1063 # check if fruit has been eaten by a snake
1064 for snake in allsnake:
1065 for fruit in allfruit:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1066 if snake.alive and snake.fruitCollision(fruit):
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1067 fruit.isEaten(snake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1068 # apples have special adding properties
1069 if fruit.__class__ == Apple:
b68496b Mike first commit
authored
1070 # check for speed increase
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1071 if game.checkSpeedTrigger():
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1072 game.updateBaseSpeed(1)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1073 # check for bonus drop
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1074 if game.checkBonusTrigger():
1075 bonus = game.runBonus()
1076 for bonusfruit in bonus:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1077 if bonusfruit == 'poison':
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1078 f = Poison(allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1079 elif bonusfruit == 'orange':
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1080 f = Orange(allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1081 elif bonusfruit == 'raspberry':
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1082 f = Raspberry(allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1083 elif bonusfruit == 'blueberry':
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1084 f = Blueberry(allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1085 else:
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1086 f = Lemon(allfruit, allsnake, game)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1087 allfruit.append(f)
1088 # chance of poison drop
b68496b Mike first commit
authored
1089 if random.randint(1,4) == 1:
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1090 p = Poison(allfruit, allsnake, game)
b68496b Mike first commit
authored
1091 allfruit.append(p)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1092 # chance of orange drop
b68496b Mike first commit
authored
1093 if random.randint(1,5) == 1:
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1094 o = Orange(allfruit, allsnake, game)
b68496b Mike first commit
authored
1095 allfruit.append(o)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1096 # chance of raspberry drop
b68496b Mike first commit
authored
1097 if random.randint(1,6) == 1:
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1098 r = Raspberry(allfruit, allsnake, game)
b68496b Mike first commit
authored
1099 allfruit.append(r)
1100 # create new apple
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1101 a = Apple(allfruit, allsnake, game)
b68496b Mike first commit
authored
1102 allfruit.append(a)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1103 elif fruit.__class__ == Blueberry:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1104 # update game frames to be 'slow' by 7 seconds
1105 game.slowtimer = game.slowtimer + game.currentspeed * 7
b68496b Mike first commit
authored
1106 # remove fruit
1107 allfruit.remove(fruit)
1108
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1109 # check for snake death, update place and end game if no more snakes are alive
1110 if game.checkSnakeDeath(allsnake):
6127227 Mike Added more selection for Duel Mode.
authored
1111 showGameStats(allsnake)
1112 return 1
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1113
1114 # check for size changes / move snake
1115 for snake in allsnake:
c9dd311 Mike added tron(y) mode.
authored
1116 snake.move(game.trailing)
b68496b Mike first commit
authored
1117
1118 # check multiplier and adjust color and multiplier as needed
1119 for snake in allsnake:
1120 if snake.multipliertimer > 0:
1121 snake.multipliertimer = snake.multipliertimer - 1
4ae7881 Mike Fixed grid and snake color changes.
authored
1122 snake.colorBorderCurrent = PURPLE
b68496b Mike first commit
authored
1123 else:
4ae7881 Mike Fixed grid and snake color changes.
authored
1124 # make sure multiplier is 1, color is normal
b68496b Mike first commit
authored
1125 snake.multiplier = 1
4ae7881 Mike Fixed grid and snake color changes.
authored
1126 snake.colorBorderCurrent = snake.colorBorder
b68496b Mike first commit
authored
1127
1128 # check slow and adjust color and fps as needed
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1129 if game.checkSlowTimer():
1130 game.updateSlowTimer()
1131 game.updateCurrentSpeed(FREEZING_POINT)
b68496b Mike first commit
authored
1132 for snake in allsnake:
4ae7881 Mike Fixed grid and snake color changes.
authored
1133 snake.colorCurrent = BLUE
b68496b Mike first commit
authored
1134 else:
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1135 game.updateCurrentSpeed()
4ae7881 Mike Fixed grid and snake color changes.
authored
1136 # make sure color is normal
1137 for snake in allsnake:
1138 snake.colorCurrent = snake.color
b68496b Mike first commit
authored
1139
1140 # update timers on fruits, remove if necessary
1141 for fruit in allfruit:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1142 if fruit.__class__ != Apple:
1143 if fruit.updateTimer() == False:
b68496b Mike first commit
authored
1144 allfruit.remove(fruit)
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1145
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1146 DISPLAYSURF.fill(BACKGROUNDCOLOR)
b68496b Mike first commit
authored
1147 drawGrid()
1148 for fruit in allfruit:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1149 fruit.drawFruit()
b68496b Mike first commit
authored
1150 for snake in allsnake:
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1151 snake.drawSnake()
6d8cfaf Mike set-up ai
authored
1152
1153 # print scores
1154 position = 1
1155 for snake in allsnake:
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
1156 snake.drawScore(position, allsnake)
6d8cfaf Mike set-up ai
authored
1157 position = position + 1
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1158 # if player is dead, print extra messages
1159 if player == False or player.alive == False:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1160 endMessage = 'press (e) to end game early'
1161 fastMessage = 'press (f) to fast-forward game'
1162 slowMessage = 'press (s) to slow game'
1163 drawMessage(endMessage, WINDOWWIDTH / 2, WINDOWHEIGHT / 20 * 16)
1164 drawMessage(fastMessage, WINDOWWIDTH / 2, WINDOWHEIGHT / 20 * 17)
1165 drawMessage(slowMessage, WINDOWWIDTH / 2, WINDOWHEIGHT / 20 * 18)
b68496b Mike first commit
authored
1166 pygame.display.update()
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1167 FPSCLOCK.tick(game.currentspeed)
b68496b Mike first commit
authored
1168
1169
1170 def checkForKeyPress():
1171 if len(pygame.event.get(QUIT)) > 0:
1172 terminate()
1173
1174 keyUpEvents = pygame.event.get(KEYUP)
1175 if len(keyUpEvents) == 0:
1176 return None
1177 if keyUpEvents[0].key == K_ESCAPE or keyUpEvents[0].key == K_q:
1178 terminate()
1179 return keyUpEvents[0].key
ef0acb2 Mike consolidated game over sequence.
authored
1180
1181
1182 def waitForInput():
1183 """
1184 Returns when key pressed or mouse clicked.
1185 Escapes/Quits as normal.
1186 """
1187 while True:
1188 for event in pygame.event.get():
1189 if event.type == QUIT:
1190 terminate()
1191 elif event.type == KEYDOWN:
1192 if event.key == K_ESCAPE or event.key == K_q:
1193 terminate()
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1194 else:
ef0acb2 Mike consolidated game over sequence.
authored
1195 return
1196 elif event.type == MOUSEBUTTONDOWN:
1197 if pygame.mouse.get_pressed() != None:
1198 return
b68496b Mike first commit
authored
1199
1200
6127227 Mike Added more selection for Duel Mode.
authored
1201 def showSelectPlayersScreen():
a734fdb Mike Added snake choices for duel mode.
authored
1202 """
6127227 Mike Added more selection for Duel Mode.
authored
1203 Blits player/opponent select onto screen. Returns selection as list.
a734fdb Mike Added snake choices for duel mode.
authored
1204 """
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1205 playerbuttons = []
6127227 Mike Added more selection for Duel Mode.
authored
1206 playersnakeybutton = SelectButton('(s)nakey', WINDOWWIDTH / 3, WINDOWHEIGHT * 2/7, True)
1207 playerbuttons.append(playersnakeybutton)
1208 playerlinusbutton = SelectButton('(l)inus', WINDOWWIDTH / 3, WINDOWHEIGHT * 3/7)
1209 playerbuttons.append(playerlinusbutton)
1210 playerwigglesbutton = SelectButton('(w)iggles', WINDOWWIDTH / 3, WINDOWHEIGHT * 4/7)
1211 playerbuttons.append(playerwigglesbutton)
1212 playergigglesbutton = SelectButton('(g)iggles', WINDOWWIDTH / 3, WINDOWHEIGHT * 5/7)
1213 playerbuttons.append(playergigglesbutton)
1214
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1215 opponentbuttons = []
6127227 Mike Added more selection for Duel Mode.
authored
1216 opponentlinusbutton = SelectButton('(l)inus', WINDOWWIDTH / 3 * 2, WINDOWHEIGHT * 3/7, True)
1217 opponentbuttons.append(opponentlinusbutton)
1218 opponentwigglesbutton = SelectButton('(w)iggles', WINDOWWIDTH / 3 * 2, WINDOWHEIGHT * 4/7)
1219 opponentbuttons.append(opponentwigglesbutton)
1220 opponentgigglesbutton = SelectButton('(g)iggles', WINDOWWIDTH / 3 * 2, WINDOWHEIGHT * 5/7)
1221 opponentbuttons.append(opponentgigglesbutton)
1222
1223
1224 cancelbutton = Button('(e)xit', WINDOWWIDTH / 3, WINDOWHEIGHT * 6/7)
1225 acceptbutton = Button('(d)uel!', WINDOWWIDTH / 3 * 2, WINDOWHEIGHT * 6/7)
a734fdb Mike Added snake choices for duel mode.
authored
1226
1227 while True:
1228
1229 choiceFont = pygame.font.Font('freesansbold.ttf', 36)
1230 choiceSurf = choiceFont.render('Choose Opponent:', True, WHITE, FORESTGREEN)
1231 choiceRect = choiceSurf.get_rect()
1232
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1233 DISPLAYSURF.fill(BACKGROUNDCOLOR)
a734fdb Mike Added snake choices for duel mode.
authored
1234 DISPLAYSURF.blit(choiceSurf, choiceRect)
1235
6127227 Mike Added more selection for Duel Mode.
authored
1236 # display all buttons
1237 for button in playerbuttons:
1238 button.display()
1239 for button in opponentbuttons:
1240 button.display()
a734fdb Mike Added snake choices for duel mode.
authored
1241 cancelbutton.display()
6127227 Mike Added more selection for Duel Mode.
authored
1242 acceptbutton.display()
a734fdb Mike Added snake choices for duel mode.
authored
1243
1244 for event in pygame.event.get():
1245 if event.type == QUIT:
1246 terminate()
1247 elif event.type == MOUSEBUTTONDOWN:
1248 mouse = pygame.mouse.get_pos()
6127227 Mike Added more selection for Duel Mode.
authored
1249 # check each button for player
1250 for button in playerbuttons:
1251 if button.pressed(mouse):
1252 button.setActive(playerbuttons)
1253 # check each button for opponent
1254 for button in opponentbuttons:
1255 if button.pressed(mouse):
1256 button.setActive(opponentbuttons)
1257 # check cancel/accept buttons
1258 if cancelbutton.pressed(mouse):
a734fdb Mike Added snake choices for duel mode.
authored
1259 pygame.event.get()
6127227 Mike Added more selection for Duel Mode.
authored
1260 return False
1261 elif acceptbutton.pressed(mouse):
a734fdb Mike Added snake choices for duel mode.
authored
1262 pygame.event.get()
6127227 Mike Added more selection for Duel Mode.
authored
1263 final = []
1264 if playersnakeybutton.active:
1265 final.append(SNAKEY)
1266 elif playerlinusbutton.active:
1267 final.append(LINUS)
1268 elif playerwigglesbutton.active:
1269 final.append(WIGGLES)
1270 elif playergigglesbutton.active:
1271 final.append(GIGGLES)
1272 if opponentlinusbutton.active:
1273 final.append(LINUS)
1274 elif opponentwigglesbutton.active:
1275 final.append(WIGGLES)
1276 elif opponentgigglesbutton.active:
1277 final.append(GIGGLES)
1278 return final
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1279
a734fdb Mike Added snake choices for duel mode.
authored
1280 elif event.type == KEYDOWN:
6127227 Mike Added more selection for Duel Mode.
authored
1281 if event.key == K_s:
1282 pygame.event.get()
1283 playersnakeybutton.setActive(playerbuttons)
1284 elif event.key == K_l:
a734fdb Mike Added snake choices for duel mode.
authored
1285 pygame.event.get()
6127227 Mike Added more selection for Duel Mode.
authored
1286 opponentlinusbutton.setActive(opponentbuttons)
a734fdb Mike Added snake choices for duel mode.
authored
1287 elif event.key == K_w:
1288 pygame.event.get()
6127227 Mike Added more selection for Duel Mode.
authored
1289 opponentwigglesbutton.setActive(opponentbuttons)
a734fdb Mike Added snake choices for duel mode.
authored
1290 elif event.key == K_g:
1291 pygame.event.get()
6127227 Mike Added more selection for Duel Mode.
authored
1292 opponentgigglesbutton.setActive(opponentbuttons)
1293 elif event.key == K_d:
1294 final = []
1295 if playersnakeybutton.active:
1296 final.append(SNAKEY)
1297 elif playerlinusbutton.active:
1298 final.append(LINUS)
1299 elif playerwigglesbutton.active:
1300 final.append(WIGGLES)
1301 elif playergigglesbutton.active:
1302 final.append(GIGGLES)
1303 if opponentlinusbutton.active:
1304 final.append(LINUS)
1305 elif opponentwigglesbutton.active:
1306 final.append(WIGGLES)
1307 elif opponentgigglesbutton.active:
1308 final.append(GIGGLES)
1309 return final
a734fdb Mike Added snake choices for duel mode.
authored
1310 elif event.key == K_e:
1311 pygame.event.get()
1312 return False
1313 elif event.key == K_ESCAPE or event.key == K_q:
1314 terminate()
1315
1316 pygame.display.update()
1317
1318
b68496b Mike first commit
authored
1319 def showInstructScreen():
6c613da Mike Worked on AI; added crude apple detection.
authored
1320 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1321 Blits instructions onto screen. Returns when exit button clicked / key pressed.
1322 """
b68496b Mike first commit
authored
1323 endinstructbutton = Button('(e)xit', WINDOWWIDTH / 2, WINDOWHEIGHT - 40)
1324
1325 while True:
1326
1327 instruct = pygame.image.load('snakey_party_instructions.png').convert()
1328
1329 DISPLAYSURF.blit(instruct, (54, 10))
1330
1331 endinstructbutton.display()
1332
1333 for event in pygame.event.get():
1334 if event.type == QUIT:
1335 terminate()
1336 elif event.type == MOUSEBUTTONDOWN:
1337 mouse = pygame.mouse.get_pos()
1338 if endinstructbutton.pressed(mouse):
1339 pygame.event.get()
1340 return
1341 elif event.type == KEYDOWN:
1342 if event.key == K_e or event.key == K_i:
1343 pygame.event.get()
1344 return
1345 elif event.key == K_ESCAPE or event.key == K_q:
1346 terminate()
1347
1348 pygame.display.update()
1349
1350
1351 def terminate():
6c613da Mike Worked on AI; added crude apple detection.
authored
1352 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1353 Clean exit from pygame.
1354 """
b68496b Mike first commit
authored
1355 pygame.quit()
1356 sys.exit()
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
1357
1358
1359 def showGameStats(allsnake):
6c613da Mike Worked on AI; added crude apple detection.
authored
1360 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1361 Displays game stats for all snakes at end of game.
1362 Returns when any key pressed.
1363 """
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1364 totaldead = 0 #stil lneeds to be fixed
1365 for snake in allsnake:
1366 if snake.alive == False:
1367 totaldead = totaldead + 1
1368
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
1369 position = 1
1370 for snake in allsnake:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1371 pos_x = getPosition(position, allsnake)
1372 pos_y = WINDOWHEIGHT / 20
1373 drawMessage(snake.name, pos_x, WINDOWHEIGHT / 20 * 3, snake.color)
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1374 if len(allsnake) != 1:
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1375 drawText('place:', snake.getPlace(totaldead, len(allsnake)), pos_x, pos_y * 5, snake.color)
1376 drawText('score:', snake.score, pos_x, pos_y * 6, snake.color)
1377 drawText('apples:', snake.fruitEaten['apple'], pos_x, pos_y * 7, RED)
1378 drawText('poison:', snake.fruitEaten['poison'], pos_x, pos_y * 8, GREEN)
1379 drawText('oranges:', snake.fruitEaten['orange'], pos_x, pos_y * 9, ORANGE)
1380 drawText('raspberries:', snake.fruitEaten['raspberry'], pos_x, pos_y * 10, PURPLE)
1381 drawText('blueberries:', snake.fruitEaten['blueberry'], pos_x, pos_y * 11, BLUE)
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
1382 position = position + 1
1383
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1384 drawMessage('Press any key.', WINDOWWIDTH / 2, pos_y * 19, GOLDENROD)
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
1385 pygame.display.update()
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1386 pygame.time.wait(300)
ef0acb2 Mike consolidated game over sequence.
authored
1387 pygame.event.get() # clear event queue
1388 showGameOverScreen()
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1389 waitForInput()
b68496b Mike first commit
authored
1390
1391
1392 def showGameOverScreen():
6c613da Mike Worked on AI; added crude apple detection.
authored
1393 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1394 Displays 'Game Over' message.
6c613da Mike Worked on AI; added crude apple detection.
authored
1395 Returns when any key pressed.
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1396 """
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1397 gameOverFont = pygame.font.Font('freesansbold.ttf', 48)
1398 gameOverSurf = gameOverFont.render('Game Over', True, WHITE)
1399 gameOverRect = gameOverSurf.get_rect()
1400 gameOverRect.midtop = (WINDOWWIDTH / 2, WINDOWHEIGHT / 3 * 2)
1401
1402 DISPLAYSURF.blit(gameOverSurf, gameOverRect)
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1403 #drawMessage('Press any key.', WINDOWWIDTH / 2, WINDOWHEIGHT / 20 * 19, GOLDENROD)
b68496b Mike first commit
authored
1404 pygame.display.update()
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1405 #pygame.time.wait(100)
b68496b Mike first commit
authored
1406
1407
6d8cfaf Mike set-up ai
authored
1408 def getGrid(allsnake, allfruit):
6c613da Mike Worked on AI; added crude apple detection.
authored
1409 """
c46945d Mike Moved Tally Class into Game Data- now passed from menu. Added support fo...
authored
1410 Returns dictionary representation of all snakes and fruits on screen.
1411 Coordinates are entered as tuple (x,y).
1412 Used by AI when choosing best path.
1413 """
6d8cfaf Mike set-up ai
authored
1414 # refresh grid, dictionary representation of playing board used by AI
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1415 grid = {(x,y):0 for x in range(CELLWIDTH) for y in range(CELLHEIGHT + (TOP_BUFFER / CELLSIZE))}
6d8cfaf Mike set-up ai
authored
1416
1417 # add snakes to grid
1418 for snake in allsnake:
1419 for snakebody in snake.coords:
1420 grid[(snakebody['x'], snakebody['y'])] = 'snake'
6c613da Mike Worked on AI; added crude apple detection.
authored
1421
1422 # add fruits to grid
1423 for fruit in allfruit:
1424 if fruit.__class__ == Apple:
1425 grid[(fruit.coords['x'], fruit.coords['y'])] = 'apple'
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1426 elif fruit.__class__ == Poison:
1427 grid[(fruit.coords['x'], fruit.coords['y'])] = 'poison'
1428 elif fruit.__class__ == Orange:
1429 grid[(fruit.coords['x'], fruit.coords['y'])] = 'orange'
1430 elif fruit.__class__ == Raspberry:
1431 grid[(fruit.coords['x'], fruit.coords['y'])] = 'raspberry'
1432 elif fruit.__class__ == Blueberry:
1433 grid[(fruit.coords['x'], fruit.coords['y'])] = 'blueberry'
1434 elif fruit.__class__ == Lemon:
1435 grid[(fruit.coords['x'], fruit.coords['y'])] = 'lemon'
6c613da Mike Worked on AI; added crude apple detection.
authored
1436
6d8cfaf Mike set-up ai
authored
1437 return grid
b68496b Mike first commit
authored
1438
1439
9504e62 Mike added party mode.
authored
1440 def drawText(text, value, x=1, y=1, color=WHITE, background=BLACK):
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1441 """
1442 Draws text & value with background to screen.
1443 """
9504e62 Mike added party mode.
authored
1444 scoreSurf = BASICFONT.render('%s %s' % (text, value), True, color, background)
b68496b Mike first commit
authored
1445 scoreRect = scoreSurf.get_rect()
faa87d1 Mike added Snake, Fruit, Tally classes
authored
1446 scoreRect.topleft = (x, y)
b68496b Mike first commit
authored
1447 DISPLAYSURF.blit(scoreSurf, scoreRect)
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1448
1449
ef0acb2 Mike consolidated game over sequence.
authored
1450 def drawMessage(text, x=1, y=1, color=MESSAGE_COLOR):
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1451 """
1452 Draws message to screen.
1453 """
1454 messageSurf = BASICFONT.render(text, True, color)
1455 messageRect = messageSurf.get_rect()
1456 messageRect.topleft = (x, y)
1457 DISPLAYSURF.blit(messageSurf, messageRect)
b68496b Mike first commit
authored
1458
6d8cfaf Mike set-up ai
authored
1459
b68496b Mike first commit
authored
1460 def drawGrid():
573b079 Mike moved fps changes to game class; added speed controls when only AIs play...
authored
1461 """
1462 Draws grid to screen.
1463 """
b68496b Mike first commit
authored
1464 for x in range(0, WINDOWWIDTH, CELLSIZE): # draw vertical lines
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1465 pygame.draw.line(DISPLAYSURF, DARKGRAY, (x, TOP_BUFFER), (x, WINDOWHEIGHT))
1466 for y in range(TOP_BUFFER, WINDOWHEIGHT, CELLSIZE): # draw horizontal lines
4ae7881 Mike Fixed grid and snake color changes.
authored
1467 pygame.draw.line(DISPLAYSURF, DARKGRAY, (0, y), (WINDOWWIDTH, y))
6d8cfaf Mike set-up ai
authored
1468
1469
1470 def debugPause():
1471 while True:
1472 if checkForKeyPress():
1473 return
1474
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
1475
6d8cfaf Mike set-up ai
authored
1476 def debugPrintGrid(grid):
1477 x = 0
1478 y = 0
1479 line = ""
1480 while grid.has_key((0,y)):
1481 if grid.has_key((x,y)):
1482 line = line + str(grid[(x,y)])[0]
1483 x = x + 1
1484 else:
1485 print line
1486 line = ""
1487 y = y + 1
1488 x = 0
b68496b Mike first commit
authored
1489
1490
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
1491 def getPosition(position, allsnake):
1492 return (WINDOWWIDTH - (float(position) / float(len(allsnake)) * WINDOWWIDTH))
6127227 Mike Added more selection for Duel Mode.
authored
1493
1494
d313d65 Mike fixed places in gamestats; end game requires only one click/key to retur...
authored
1495 def getStartCoords(pos=1):
6127227 Mike Added more selection for Duel Mode.
authored
1496 if pos == 1:
1497 return [{'x':5, 'y':5},{'x':4, 'y':5},{'x':3, 'y':5}]
1498 elif pos == 2:
1499 return [{'x':CELLWIDTH-5, 'y':CELLHEIGHT-5},{'x':CELLWIDTH-4, 'y':CELLHEIGHT-5},{'x':CELLWIDTH-3, 'y':CELLHEIGHT-5}]
1500 elif pos == 3:
1501 return [{'x':CELLWIDTH-5, 'y':5},{'x':CELLWIDTH-4, 'y':5},{'x':CELLWIDTH-3, 'y':5}]
1502 elif pos == 4:
844bea5 Mike Fixed getStartPosition.
authored
1503 return [{'x':5, 'y':CELLHEIGHT-5},{'x':4, 'y':CELLHEIGHT-5},{'x':3, 'y':CELLHEIGHT-5}]
4b2744c Mike added post-game tally, added event handling for sharp turns
authored
1504
1505
b68496b Mike first commit
authored
1506 if __name__ == '__main__':
1507 main()
1508
Something went wrong with that request. Please try again.