Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 1509 lines (1314 sloc) 56.281 kB
b68496b @djrahl first commit
authored
1 #!/usr/bin/env python
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
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 @djrahl first commit
authored
6
7 import random, pygame, sys
8 from pygame.locals import *
9
10 WINDOWWIDTH = 640
11 WINDOWHEIGHT = 480
6c613da @djrahl Worked on AI; added crude apple detection.
authored
12 FPS = 12
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
13 MIN_FPS = 3
14 MAX_FPS = 60
b68496b @djrahl first commit
authored
15 CELLSIZE = 20
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
16 TOP_BUFFER = CELLSIZE * 1 # displays in-game info
b68496b @djrahl first commit
authored
17 assert WINDOWWIDTH % CELLSIZE == 0, "Window width must be a multiple of cell size."
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
18 assert (WINDOWHEIGHT - TOP_BUFFER) % CELLSIZE == 0, "Window height must be a multiple of cell size."
b68496b @djrahl first commit
authored
19 CELLWIDTH = int(WINDOWWIDTH / CELLSIZE)
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
20 CELLHEIGHT = int((WINDOWHEIGHT - TOP_BUFFER) / CELLSIZE)
b68496b @djrahl first commit
authored
21
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
22 # colors - (R G B)
b68496b @djrahl 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 @djrahl added Snake, Fruit, Tally classes
authored
44 ORANGE = (255, 127, 0)
b68496b @djrahl first commit
authored
45 PURPLE = (142, 56, 142)
46 MAROON = (255, 52, 179)
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
47 BACKGROUNDCOLOR = BLACK
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
48 BUTTONCLR = GREEN
49 BUTTONTXT = DARKGRAY
c9dd311 @djrahl added tron(y) mode.
authored
50 BUTTONCLR_SL = COBALTGREEN
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
51 BUTTONTXT_SL = GOLDENROD
ef0acb2 @djrahl consolidated game over sequence.
authored
52 MESSAGE_COLOR = GREEN
b68496b @djrahl first commit
authored
53
6c613da @djrahl Worked on AI; added crude apple detection.
authored
54 # for consistency in direction types
b68496b @djrahl first commit
authored
55 UP = 'up'
56 DOWN = 'down'
57 LEFT = 'left'
58 RIGHT = 'right'
59
6c613da @djrahl Worked on AI; added crude apple detection.
authored
60 # for consistency in snake names
6127227 @djrahl Added more selection for Duel Mode.
authored
61 SNAKEY = 'snakey'
2199376 @djrahl changed intro menu; added arcade mode & duel mode.
authored
62 WIGGLES = 'wiggles'
63 GIGGLES = 'giggles'
64 LINUS = 'linus'
65
6c613da @djrahl Worked on AI; added crude apple detection.
authored
66 # index of snake's head
67 HEAD = 0
b68496b @djrahl first commit
authored
68
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
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 @djrahl added Snake, Fruit, Tally classes
authored
77
78 POISONBONUS = 7
79 ORANGEBONUS = 8
80 RASPBERRYBONUS = 9
81 BLUEBERRYBONUS = 10
82 LEMONBONUS = 11
b68496b @djrahl first commit
authored
83
84
85 class Snake:
faa87d1 @djrahl 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 @djrahl set-up ai
authored
89 name - name of snake.
faa87d1 @djrahl 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 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
99 place - used to determine death order.
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
100 """
6127227 @djrahl Added more selection for Duel Mode.
authored
101 def __init__(self, n=SNAKEY, c=False, sc=GREEN, sb=COBALTGREEN):
6d8cfaf @djrahl set-up ai
authored
102 self.name = n
6127227 @djrahl Added more selection for Duel Mode.
authored
103 if self.name == SNAKEY:
104 self.player = True
105 else:
106 self.player = False
b68496b @djrahl first commit
authored
107 self.alive = True
6127227 @djrahl Added more selection for Duel Mode.
authored
108
109 if c == False:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
110 self.coords = getStartCoords(1)
6127227 @djrahl Added more selection for Duel Mode.
authored
111 else:
112 self.coords = c
b68496b @djrahl first commit
authored
113 # ensure snake length
114 assert len(self.coords) > 1
6127227 @djrahl 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 @djrahl first commit
authored
121 self.color = sc
4ae7881 @djrahl Fixed grid and snake color changes.
authored
122 self.colorCurrent = self.color
b68496b @djrahl first commit
authored
123 self.colorBorder = sb
4ae7881 @djrahl Fixed grid and snake color changes.
authored
124 self.colorBorderCurrent = self.colorBorder
b68496b @djrahl first commit
authored
125 self.growth = 0
126 self.multiplier = 1
127 self.multipliertimer = 0
128 self.score = 0
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
129 self.place = False
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
130 self.fruitEaten = {'apple':0, 'poison':0, 'orange':0,
131 'raspberry':0, 'blueberry':0, 'lemon':0}
faa87d1 @djrahl 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 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
152
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
153 def getPlace(self, totaldead, totalsnakes):
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
154 """
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
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 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
157 """
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
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 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
175 return '2nd'
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
176 elif self.place + 1 == totalsnakes - totalalive:
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
177 return '3rd'
178 else:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
179 return 'last'
faa87d1 @djrahl 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 @djrahl set-up ai
authored
185 # check if out of bounds -- offset on on 'y' for buffer.
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
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 @djrahl 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 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
201 if snakebody['x'] == self.coords[HEAD]['x'] and \
202 snakebody['y'] == self.coords[HEAD]['y']:
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
203 return True
204 else:
205 for snakebody in snake.coords:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
206 if snakebody['x'] == self.coords[HEAD]['x'] and \
207 snakebody['y'] == self.coords[HEAD]['y']:
faa87d1 @djrahl 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 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
216 if self.coords[HEAD]['x'] == fruit.coords['x'] and \
217 self.coords[HEAD]['y'] == fruit.coords['y']:
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
218 return True
219 else:
220 return False
221
c9dd311 @djrahl added tron(y) mode.
authored
222 def move(self, trailing=False):
faa87d1 @djrahl 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 @djrahl 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 @djrahl 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 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
247 newhead = {'x': self.coords[HEAD]['x'],
248 'y': self.coords[HEAD]['y'] - 1}
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
249 elif self.direction == DOWN:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
250 newhead = {'x': self.coords[HEAD]['x'],
251 'y': self.coords[HEAD]['y'] + 1}
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
252 elif self.direction == LEFT:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
253 newhead = {'x': self.coords[HEAD]['x'] - 1,
254 'y': self.coords[HEAD]['y']}
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
255 elif self.direction == RIGHT:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
256 newhead = {'x': self.coords[HEAD]['x'] + 1,
257 'y': self.coords[HEAD]['y']}
c9dd311 @djrahl added tron(y) mode.
authored
258
faa87d1 @djrahl 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 @djrahl Fixed grid and snake color changes.
authored
274 pygame.draw.rect(DISPLAYSURF, self.colorBorderCurrent, snakeSegmentRect)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
275 snakeInnerSegmentRect = pygame.Rect(x + 4, y + 4, CELLSIZE - 8, CELLSIZE - 8)
4ae7881 @djrahl Fixed grid and snake color changes.
authored
276 pygame.draw.rect(DISPLAYSURF, self.colorCurrent, snakeInnerSegmentRect)
6d8cfaf @djrahl set-up ai
authored
277
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
278 def drawScore(self, position, allsnake):
6d8cfaf @djrahl set-up ai
authored
279 """
280 Responsible for drawing snake score to screen.
281 """
4ae7881 @djrahl Fixed grid and snake color changes.
authored
282 scoreSurf = BASICFONT.render('%s: %s' % (self.name, self.score), True, self.colorCurrent)
6d8cfaf @djrahl set-up ai
authored
283 scoreRect = scoreSurf.get_rect()
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
284 scoreRect.topleft = (getPosition(position, allsnake), 1)
6d8cfaf @djrahl 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 @djrahl 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 @djrahl set-up ai
authored
294 self.avoidBoundaries = True
c134769 @djrahl fixed key input bug
authored
295 self.randomness = r
6d8cfaf @djrahl set-up ai
authored
296 self.preferSameDirection = p
297
298 def updateDirection(self, grid):
299 # all directions have value adjusted
6c613da @djrahl Worked on AI; added crude apple detection.
authored
300 nextDirection = {LEFT:0, RIGHT:0, UP:0, DOWN:0}
6d8cfaf @djrahl 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 @djrahl Worked on AI; added crude apple detection.
authored
308 nextDirection[RIGHT] = nextDirection[RIGHT] - 100
6d8cfaf @djrahl set-up ai
authored
309 elif self.direction == RIGHT:
6c613da @djrahl Worked on AI; added crude apple detection.
authored
310 nextDirection[LEFT] = nextDirection[LEFT] - 100
6d8cfaf @djrahl set-up ai
authored
311 elif self.direction == UP:
6c613da @djrahl Worked on AI; added crude apple detection.
authored
312 nextDirection[DOWN] = nextDirection[DOWN] - 100
6d8cfaf @djrahl set-up ai
authored
313 elif self.direction == DOWN:
6c613da @djrahl Worked on AI; added crude apple detection.
authored
314 nextDirection[UP] = nextDirection[UP]- 100
6d8cfaf @djrahl set-up ai
authored
315
316 # avoid boundaries
317 if self.avoidBoundaries == True:
318 if x == 0:
6c613da @djrahl Worked on AI; added crude apple detection.
authored
319 nextDirection[LEFT] = nextDirection[LEFT] - 100
6d8cfaf @djrahl set-up ai
authored
320 if x == CELLWIDTH - 1:
6c613da @djrahl Worked on AI; added crude apple detection.
authored
321 nextDirection[RIGHT] = nextDirection[RIGHT] - 100
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
322 if y == (TOP_BUFFER / CELLSIZE):
6c613da @djrahl Worked on AI; added crude apple detection.
authored
323 nextDirection[UP] = nextDirection[UP] - 100
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
324 if y == CELLHEIGHT + (TOP_BUFFER / CELLSIZE) - 1:
6c613da @djrahl Worked on AI; added crude apple detection.
authored
325 nextDirection[DOWN] = nextDirection[DOWN] - 100
6d8cfaf @djrahl set-up ai
authored
326
327 # prefer same direction
6c613da @djrahl Worked on AI; added crude apple detection.
authored
328 nextDirection[self.direction] = nextDirection[self.direction] + self.preferSameDirection
6d8cfaf @djrahl set-up ai
authored
329
330 # avoid immediate snakes
331 if grid.has_key((x-1,y)) and (grid[(x-1,y)] == 'snake'):
6c613da @djrahl Worked on AI; added crude apple detection.
authored
332 nextDirection[LEFT] = nextDirection[LEFT] - 100
6d8cfaf @djrahl set-up ai
authored
333 if grid.has_key((x+1,y)) and (grid[(x+1,y)] == 'snake'):
6c613da @djrahl Worked on AI; added crude apple detection.
authored
334 nextDirection[RIGHT] = nextDirection[RIGHT] - 100
6d8cfaf @djrahl set-up ai
authored
335 if grid.has_key((x,y-1)) and (grid[(x,y-1)] == 'snake'):
6c613da @djrahl 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 @djrahl set-up ai
authored
354
355 # factor in randomness
6c613da @djrahl Worked on AI; added crude apple detection.
authored
356 for d in nextDirection:
357 nextDirection[d] = nextDirection[d] + random.randint(0,self.randomness)
6d8cfaf @djrahl set-up ai
authored
358
359 # report if debugging
360 if DEBUG == True:
361 print self.name
6c613da @djrahl Worked on AI; added crude apple detection.
authored
362 print nextDirection
6d8cfaf @djrahl set-up ai
authored
363
364 # update snake direction to direction with highest score
6c613da @djrahl Worked on AI; added crude apple detection.
authored
365 self.direction = max(nextDirection, key=nextDirection.get)
6d8cfaf @djrahl set-up ai
authored
366
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
367 def getPlace(self, totaldead, totalsnakes):
368 return Snake.getPlace(self, totaldead, totalsnakes)
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
369
6d8cfaf @djrahl 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 @djrahl added tron(y) mode.
authored
388 def move(self, trailing):
389 Snake.move(self, trailing)
6d8cfaf @djrahl set-up ai
authored
390
391 def drawSnake(self):
392 Snake.drawSnake(self)
393
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
394 def drawScore(self, position, allsnake):
395 Snake.drawScore(self, position, allsnake)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
396
b68496b @djrahl first commit
authored
397
398 class Fruit:
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
399 """
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
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 @djrahl added Snake, Fruit, Tally classes
authored
402 """
403 def __init__(self):
404 self.timer = 0
405
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
406 def getRandomLocation(self, allfruit, allsnake, game):
faa87d1 @djrahl 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 @djrahl first commit
authored
411 while True:
412 conflict = False
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
413 if game.checkEasyTrigger():
b68496b @djrahl 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 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
418 y = random.randint((TOP_BUFFER / CELLSIZE), CELLHEIGHT - 1)
b68496b @djrahl 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 @djrahl 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 @djrahl first commit
authored
434 if self.timer > 0:
435 self.timer = self.timer - 1
436 return True
437 else:
438 return False
439
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
455 def __init__(self, allfruit, allsnake, game):
456 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
457 self.color = RED
458 self.points = 10
459 self.growth = 1
460
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
461 def isEaten(self, snake, game):
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
462 snake.fruitEaten['apple'] = snake.fruitEaten['apple'] + 1
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
463 game.fruitEaten['apple'] = game.fruitEaten['apple'] + 1
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
475 def __init__(self, allfruit, allsnake, game):
476 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
482 def isEaten(self, snake, game):
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
483 snake.fruitEaten['poison'] = snake.fruitEaten['poison'] + 1
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
484 game.fruitEaten['poison'] = game.fruitEaten['poison'] + 1
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
499 def __init__(self, allfruit, allsnake, game):
500 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
506 def isEaten(self, snake, game):
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
507 snake.fruitEaten['orange'] = snake.fruitEaten['orange'] + 1
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
508 game.fruitEaten['orange'] = game.fruitEaten['orange'] + 1
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
523 def __init__(self, allfruit, allsnake, game):
524 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
530 def isEaten(self, snake, game):
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
531 snake.fruitEaten['raspberry'] = snake.fruitEaten['raspberry'] + 1
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
532 game.fruitEaten['raspberry'] = game.fruitEaten['raspberry'] + 1
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
547 def __init__(self, allfruit, allsnake, game):
548 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
549 self.timer = random.randint(BLUEBERRYTIMER[0], BLUEBERRYTIMER[1])
550 self.color = BLUE
551 self.score = 100
a734fdb @djrahl Added snake choices for duel mode.
authored
552 self.slowtimer = 80
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
553
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
554 def isEaten(self, snake, game):
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
555 snake.fruitEaten['blueberry'] = snake.fruitEaten['blueberry'] + 1
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
556 game.fruitEaten['blueberry'] = game.fruitEaten['blueberry'] + 1
faa87d1 @djrahl 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 @djrahl Worked on AI.
authored
567 """
4ae7881 @djrahl Fixed grid and snake color changes.
authored
568 TBD... currently worth 1000 points.
569 """
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
570 def __init__(self, allfruit, allsnake, game):
571 self.coords = Fruit.getRandomLocation(self, allfruit, allsnake, game)
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
576 def isEaten(self, snake, game):
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
577 snake.fruitEaten['lemon'] = snake.fruitEaten['lemon'] + 1
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
578 game.fruitEaten['lemon'] = game.fruitEaten['lemon'] + 1
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
588 class GameData:
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
589 """
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
590 Responsible for dynamics for a particular game instance.
faa87d1 @djrahl 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 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
595 currentplace - the current 'place' of snake. When snake has died.
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
596 apples - number of apples on screen.
faa87d1 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
600 def __init__(self, st=20, bt=10, et=20, a=1, tmin=1, tmax=10):
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
601 self.fruitEaten = {'apple':0, 'poison':0, 'orange':0,
602 'raspberry':0, 'blueberry':0, 'lemon':0}
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
603 self.speedTrigger = st
604 self.bonusTrigger = bt
605 self.easyTrigger = et
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
606 self.currentplace = 1
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
607 self.apples = a
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
608 self.typeMin = tmin
609 self.typeMax = tmax
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
610 self.basespeed = FPS
611 self.currentspeed = self.basespeed
612 self.slowtimer = 0
c9dd311 @djrahl added tron(y) mode.
authored
613 self.trailing = False
faa87d1 @djrahl 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 @djrahl moved fps changes to game class; added speed controls when only AIs p…
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 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
661 if (self.basespeed + value > MIN_FPS) and \
662 (self.basespeed + value < MAX_FPS):
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
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 @djrahl 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 @djrahl first commit
authored
748
749 class Button():
6d8cfaf @djrahl set-up ai
authored
750 """
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
751 A clickable button that is rendered on screen.
752 """
b68496b @djrahl first commit
authored
753 def __init__(self, text, x, y):
754 self.text = text
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
755 startSurf = BUTTONFONT.render(self.text, True, BUTTONCLR, BUTTONTXT)
b68496b @djrahl first commit
authored
756 self.rect = startSurf.get_rect()
757 self.rect.center = x,y
758
759 def display(self):
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
760 startSurf = BUTTONFONT.render(self.text, True, BUTTONCLR, BUTTONTXT)
b68496b @djrahl first commit
authored
761 DISPLAYSURF.blit(startSurf, self.rect)
762
6127227 @djrahl Added more selection for Duel Mode.
authored
763 def pressed(self, mouse):
b68496b @djrahl 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 @djrahl 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 @djrahl added tron(y) mode.
authored
785 startSurf = BUTTONFONT.render(self.text, True, BUTTONCLR_SL, BUTTONTXT_SL)
6127227 @djrahl Added more selection for Duel Mode.
authored
786 else:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
787 startSurf = BUTTONFONT.render(self.text, True, BUTTONCLR, BUTTONTXT)
6127227 @djrahl 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 @djrahl first commit
authored
802 def main():
6d8cfaf @djrahl 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 @djrahl 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 @djrahl added party mode.
authored
815 BUTTONFONT = pygame.font.Font('freesansbold.ttf', 30)
2199376 @djrahl changed intro menu; added arcade mode & duel mode.
authored
816 pygame.display.set_caption('Snakey Party')
b68496b @djrahl first commit
authored
817
2199376 @djrahl 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 @djrahl added party mode.
authored
821 titleRect.center = (WINDOWWIDTH / 2, WINDOWHEIGHT * 2/8)
2199376 @djrahl changed intro menu; added arcade mode & duel mode.
authored
822
9504e62 @djrahl 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 @djrahl 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 @djrahl changed intro menu; added arcade mode & duel mode.
authored
828
829 while True: ### need to update this
830
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
831 DISPLAYSURF.fill(BACKGROUNDCOLOR)
2199376 @djrahl changed intro menu; added arcade mode & duel mode.
authored
832 DISPLAYSURF.blit(titleSurf, titleRect)
833 arcadebutton.display()
834 duelbutton.display()
9504e62 @djrahl added party mode.
authored
835 partybutton.display()
c9dd311 @djrahl added tron(y) mode.
authored
836 tronybutton.display()
2199376 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
846 game = GameData()
6127227 @djrahl Added more selection for Duel Mode.
authored
847 runGame(game, [SNAKEY])
2199376 @djrahl changed intro menu; added arcade mode & duel mode.
authored
848 showGameOverScreen()
849 elif duelbutton.pressed(mouse):
850 pygame.event.get()
6127227 @djrahl Added more selection for Duel Mode.
authored
851 players = False
852 players = showSelectPlayersScreen()
853 if players != False:
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
854 game = GameData(10, 10, 9, 2)
6127227 @djrahl Added more selection for Duel Mode.
authored
855 runGame(game, players)
a734fdb @djrahl Added snake choices for duel mode.
authored
856 showGameOverScreen()
9504e62 @djrahl added party mode.
authored
857 elif partybutton.pressed(mouse):
858 pygame.event.get()
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
859 game = GameData(25, 12, 0, 4)
6127227 @djrahl Added more selection for Duel Mode.
authored
860 runGame(game, [SNAKEY, LINUS, WIGGLES, GIGGLES])
9504e62 @djrahl added party mode.
authored
861 showGameOverScreen()
c9dd311 @djrahl 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 @djrahl 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 @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
873 game = GameData()
6127227 @djrahl Added more selection for Duel Mode.
authored
874 runGame(game, [SNAKEY])
2199376 @djrahl changed intro menu; added arcade mode & duel mode.
authored
875 showGameOverScreen()
876 elif event.key == K_d:
877 pygame.event.get()
6127227 @djrahl Added more selection for Duel Mode.
authored
878 players = False
879 players = showSelectPlayersScreen()
880 if players != False:
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
881 game = GameData(10, 10, 9, 2)
6127227 @djrahl Added more selection for Duel Mode.
authored
882 runGame(game, players)
a734fdb @djrahl Added snake choices for duel mode.
authored
883 showGameOverScreen()
9504e62 @djrahl added party mode.
authored
884 elif event.key == K_p:
885 pygame.event.get()
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
886 game = GameData(25, 12, 0, 4)
6127227 @djrahl Added more selection for Duel Mode.
authored
887 runGame(game, [SNAKEY, LINUS, WIGGLES, GIGGLES])
9504e62 @djrahl added party mode.
authored
888 showGameOverScreen()
c9dd311 @djrahl 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 @djrahl 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 @djrahl Added more selection for Duel Mode.
authored
900 game = False
2199376 @djrahl changed intro menu; added arcade mode & duel mode.
authored
901 pygame.display.update()
902 FPSCLOCK.tick(FPS)
9504e62 @djrahl added party mode.
authored
903
b68496b @djrahl first commit
authored
904
6127227 @djrahl Added more selection for Duel Mode.
authored
905 def runGame(game, players=[]):
b68496b @djrahl first commit
authored
906
6d8cfaf @djrahl set-up ai
authored
907 # in game variables
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
908 allsnake = []
909 allfruit = []
6127227 @djrahl Added more selection for Duel Mode.
authored
910 nextEvent = 0
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
911
6127227 @djrahl 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 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
914 pos = 1
6127227 @djrahl Added more selection for Duel Mode.
authored
915 for snake in players:
916 if snake == SNAKEY:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
917 player = Snake(SNAKEY, getStartCoords(pos))
6127227 @djrahl Added more selection for Duel Mode.
authored
918 allsnake.append(player)
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
919 pos = pos + 1
2199376 @djrahl changed intro menu; added arcade mode & duel mode.
authored
920 elif snake == LINUS:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
921 linus = Opponent(LINUS, getStartCoords(pos), IVORY, COBALTGREEN, 5, 20)
2199376 @djrahl changed intro menu; added arcade mode & duel mode.
authored
922 allsnake.append(linus)
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
923 pos = pos + 1
6127227 @djrahl Added more selection for Duel Mode.
authored
924 elif snake == WIGGLES:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
925 wiggles = Opponent(WIGGLES, getStartCoords(pos), OLIVEGREEN, PURPLE, 20, 5)
6127227 @djrahl Added more selection for Duel Mode.
authored
926 allsnake.append(wiggles)
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
927 pos = pos + 1
6127227 @djrahl Added more selection for Duel Mode.
authored
928 elif snake == GIGGLES:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
929 giggles = Opponent(GIGGLES, getStartCoords(pos), PURPLE, EMERALDGREEN, 10, 10)
6127227 @djrahl Added more selection for Duel Mode.
authored
930 allsnake.append(giggles)
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
931 pos = pos + 1
b68496b @djrahl first commit
authored
932
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
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 @djrahl changed intro menu; added arcade mode & duel mode.
authored
939
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
940 # main game loop
941 while True:
6127227 @djrahl Added more selection for Duel Mode.
authored
942
6d8cfaf @djrahl set-up ai
authored
943 # get grid representation for AIs
944 grid = getGrid(allsnake, allfruit)
945
6127227 @djrahl Added more selection for Duel Mode.
authored
946 # event handling loop -- get player's direction choice
947 stop = False
948
4b2744c @djrahl 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 @djrahl added Snake, Fruit, Tally classes
authored
951 for event in pygame.event.get():
b68496b @djrahl first commit
authored
952 if event.type == QUIT:
953 terminate()
6127227 @djrahl Added more selection for Duel Mode.
authored
954 elif nextEvent != 0 and player != False:
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
955 player.direction = nextEvent
956 nextEvent = 0
957 stop = True
6127227 @djrahl Added more selection for Duel Mode.
authored
958 # check for exit/quit/debug keys
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
959 if event.type == KEYDOWN and \
960 (event.key == K_ESCAPE or event.key == K_q):
6127227 @djrahl Added more selection for Duel Mode.
authored
961 terminate()
962 elif event.type == KEYDOWN and event.key == K_e:
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
963 showGameStats(allsnake)
6127227 @djrahl 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 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
968 # if player is dead / does not exist - check for speed controls
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
969 elif event.type == KEYDOWN and event.key == K_f and \
970 (player == False or player.alive == False):
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
971 game.updateBaseSpeed(10)
972 game.updateCurrentSpeed(False, True)
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
973 elif event.type == KEYDOWN and event.key == K_s and \
974 (player == False or player.alive == False):
ef0acb2 @djrahl consolidated game over sequence.
authored
975 game.updateBaseSpeed(-10)
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
976 game.updateCurrentSpeed(False, True)
6127227 @djrahl Added more selection for Duel Mode.
authored
977
978 # if player exists - check for direction input
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
979 if event.type == KEYDOWN and \
980 player != False and stop == False:
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
981 if event.key == K_LEFT and player.direction != RIGHT:
6d8cfaf @djrahl set-up ai
authored
982 player.direction = LEFT
b68496b @djrahl first commit
authored
983 stop = True
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
984 elif event.key == K_RIGHT and player.direction != LEFT:
6d8cfaf @djrahl set-up ai
authored
985 player.direction = RIGHT
b68496b @djrahl first commit
authored
986 stop = True
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
987 elif event.key == K_UP and player.direction != DOWN:
6d8cfaf @djrahl set-up ai
authored
988 player.direction = UP
b68496b @djrahl first commit
authored
989 stop = True
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
990 elif event.key == K_DOWN and player.direction != UP:
6d8cfaf @djrahl set-up ai
authored
991 player.direction = DOWN
6127227 @djrahl Added more selection for Duel Mode.
authored
992
4b2744c @djrahl 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 @djrahl Added more selection for Duel Mode.
authored
994 elif event.type == KEYDOWN and player != False and nextEvent == 0:
4b2744c @djrahl 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 @djrahl 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 @djrahl first commit
authored
1015
6d8cfaf @djrahl set-up ai
authored
1016 # collision detection
b68496b @djrahl first commit
authored
1017 for snake in allsnake:
6d8cfaf @djrahl set-up ai
authored
1018 # check if the snake has hit boundary
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1019 if snake.alive and snake.boundsCollision():
b68496b @djrahl first commit
authored
1020 snake.alive = False
faa87d1 @djrahl 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 @djrahl first commit
authored
1024 snake.alive = False
1025
1026 # check score - change color accordingly
1027 # only looks at player snake
6127227 @djrahl 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 @djrahl 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 @djrahl added Snake, Fruit, Tally classes
authored
1066 if snake.alive and snake.fruitCollision(fruit):
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1067 fruit.isEaten(snake, game)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1068 # apples have special adding properties
1069 if fruit.__class__ == Apple:
b68496b @djrahl first commit
authored
1070 # check for speed increase
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1071 if game.checkSpeedTrigger():
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1072 game.updateBaseSpeed(1)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1073 # check for bonus drop
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1074 if game.checkBonusTrigger():
1075 bonus = game.runBonus()
1076 for bonusfruit in bonus:
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1077 if bonusfruit == 'poison':
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1078 f = Poison(allfruit, allsnake, game)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1079 elif bonusfruit == 'orange':
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1080 f = Orange(allfruit, allsnake, game)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1081 elif bonusfruit == 'raspberry':
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1082 f = Raspberry(allfruit, allsnake, game)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1083 elif bonusfruit == 'blueberry':
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1084 f = Blueberry(allfruit, allsnake, game)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1085 else:
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1086 f = Lemon(allfruit, allsnake, game)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1087 allfruit.append(f)
1088 # chance of poison drop
b68496b @djrahl first commit
authored
1089 if random.randint(1,4) == 1:
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1090 p = Poison(allfruit, allsnake, game)
b68496b @djrahl first commit
authored
1091 allfruit.append(p)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1092 # chance of orange drop
b68496b @djrahl first commit
authored
1093 if random.randint(1,5) == 1:
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1094 o = Orange(allfruit, allsnake, game)
b68496b @djrahl first commit
authored
1095 allfruit.append(o)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1096 # chance of raspberry drop
b68496b @djrahl first commit
authored
1097 if random.randint(1,6) == 1:
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1098 r = Raspberry(allfruit, allsnake, game)
b68496b @djrahl first commit
authored
1099 allfruit.append(r)
1100 # create new apple
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1101 a = Apple(allfruit, allsnake, game)
b68496b @djrahl first commit
authored
1102 allfruit.append(a)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1103 elif fruit.__class__ == Blueberry:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1104 # update game frames to be 'slow' by 7 seconds
1105 game.slowtimer = game.slowtimer + game.currentspeed * 7
b68496b @djrahl first commit
authored
1106 # remove fruit
1107 allfruit.remove(fruit)
1108
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1109 # check for snake death, update place and end game if no more snakes are alive
1110 if game.checkSnakeDeath(allsnake):
6127227 @djrahl Added more selection for Duel Mode.
authored
1111 showGameStats(allsnake)
1112 return 1
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1113
1114 # check for size changes / move snake
1115 for snake in allsnake:
c9dd311 @djrahl added tron(y) mode.
authored
1116 snake.move(game.trailing)
b68496b @djrahl 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 @djrahl Fixed grid and snake color changes.
authored
1122 snake.colorBorderCurrent = PURPLE
b68496b @djrahl first commit
authored
1123 else:
4ae7881 @djrahl Fixed grid and snake color changes.
authored
1124 # make sure multiplier is 1, color is normal
b68496b @djrahl first commit
authored
1125 snake.multiplier = 1
4ae7881 @djrahl Fixed grid and snake color changes.
authored
1126 snake.colorBorderCurrent = snake.colorBorder
b68496b @djrahl first commit
authored
1127
1128 # check slow and adjust color and fps as needed
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1129 if game.checkSlowTimer():
1130 game.updateSlowTimer()
1131 game.updateCurrentSpeed(FREEZING_POINT)
b68496b @djrahl first commit
authored
1132 for snake in allsnake:
4ae7881 @djrahl Fixed grid and snake color changes.
authored
1133 snake.colorCurrent = BLUE
b68496b @djrahl first commit
authored
1134 else:
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1135 game.updateCurrentSpeed()
4ae7881 @djrahl Fixed grid and snake color changes.
authored
1136 # make sure color is normal
1137 for snake in allsnake:
1138 snake.colorCurrent = snake.color
b68496b @djrahl first commit
authored
1139
1140 # update timers on fruits, remove if necessary
1141 for fruit in allfruit:
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1142 if fruit.__class__ != Apple:
1143 if fruit.updateTimer() == False:
b68496b @djrahl first commit
authored
1144 allfruit.remove(fruit)
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1145
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1146 DISPLAYSURF.fill(BACKGROUNDCOLOR)
b68496b @djrahl first commit
authored
1147 drawGrid()
1148 for fruit in allfruit:
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1149 fruit.drawFruit()
b68496b @djrahl first commit
authored
1150 for snake in allsnake:
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1151 snake.drawSnake()
6d8cfaf @djrahl set-up ai
authored
1152
1153 # print scores
1154 position = 1
1155 for snake in allsnake:
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
1156 snake.drawScore(position, allsnake)
6d8cfaf @djrahl set-up ai
authored
1157 position = position + 1
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1158 # if player is dead, print extra messages
1159 if player == False or player.alive == False:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
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 @djrahl first commit
authored
1166 pygame.display.update()
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1167 FPSCLOCK.tick(game.currentspeed)
b68496b @djrahl 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 @djrahl 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 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1194 else:
ef0acb2 @djrahl consolidated game over sequence.
authored
1195 return
1196 elif event.type == MOUSEBUTTONDOWN:
1197 if pygame.mouse.get_pressed() != None:
1198 return
b68496b @djrahl first commit
authored
1199
1200
6127227 @djrahl Added more selection for Duel Mode.
authored
1201 def showSelectPlayersScreen():
a734fdb @djrahl Added snake choices for duel mode.
authored
1202 """
6127227 @djrahl Added more selection for Duel Mode.
authored
1203 Blits player/opponent select onto screen. Returns selection as list.
a734fdb @djrahl Added snake choices for duel mode.
authored
1204 """
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1205 playerbuttons = []
6127227 @djrahl 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 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1215 opponentbuttons = []
6127227 @djrahl 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 @djrahl 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 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1233 DISPLAYSURF.fill(BACKGROUNDCOLOR)
a734fdb @djrahl Added snake choices for duel mode.
authored
1234 DISPLAYSURF.blit(choiceSurf, choiceRect)
1235
6127227 @djrahl 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 @djrahl Added snake choices for duel mode.
authored
1241 cancelbutton.display()
6127227 @djrahl Added more selection for Duel Mode.
authored
1242 acceptbutton.display()
a734fdb @djrahl 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 @djrahl 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 @djrahl Added snake choices for duel mode.
authored
1259 pygame.event.get()
6127227 @djrahl Added more selection for Duel Mode.
authored
1260 return False
1261 elif acceptbutton.pressed(mouse):
a734fdb @djrahl Added snake choices for duel mode.
authored
1262 pygame.event.get()
6127227 @djrahl 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 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1279
a734fdb @djrahl Added snake choices for duel mode.
authored
1280 elif event.type == KEYDOWN:
6127227 @djrahl 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 @djrahl Added snake choices for duel mode.
authored
1285 pygame.event.get()
6127227 @djrahl Added more selection for Duel Mode.
authored
1286 opponentlinusbutton.setActive(opponentbuttons)
a734fdb @djrahl Added snake choices for duel mode.
authored
1287 elif event.key == K_w:
1288 pygame.event.get()
6127227 @djrahl Added more selection for Duel Mode.
authored
1289 opponentwigglesbutton.setActive(opponentbuttons)
a734fdb @djrahl Added snake choices for duel mode.
authored
1290 elif event.key == K_g:
1291 pygame.event.get()
6127227 @djrahl 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 @djrahl 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 @djrahl first commit
authored
1319 def showInstructScreen():
6c613da @djrahl Worked on AI; added crude apple detection.
authored
1320 """
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1321 Blits instructions onto screen. Returns when exit button clicked / key pressed.
1322 """
b68496b @djrahl 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 @djrahl Worked on AI; added crude apple detection.
authored
1352 """
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1353 Clean exit from pygame.
1354 """
b68496b @djrahl first commit
authored
1355 pygame.quit()
1356 sys.exit()
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
1357
1358
1359 def showGameStats(allsnake):
6c613da @djrahl Worked on AI; added crude apple detection.
authored
1360 """
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1361 Displays game stats for all snakes at end of game.
1362 Returns when any key pressed.
1363 """
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
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 @djrahl added post-game tally, added event handling for sharp turns
authored
1369 position = 1
1370 for snake in allsnake:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1371 pos_x = getPosition(position, allsnake)
1372 pos_y = WINDOWHEIGHT / 20
1373 drawMessage(snake.name, pos_x, WINDOWHEIGHT / 20 * 3, snake.color)
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1374 if len(allsnake) != 1:
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
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 @djrahl added post-game tally, added event handling for sharp turns
authored
1382 position = position + 1
1383
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1384 drawMessage('Press any key.', WINDOWWIDTH / 2, pos_y * 19, GOLDENROD)
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
1385 pygame.display.update()
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1386 pygame.time.wait(300)
ef0acb2 @djrahl consolidated game over sequence.
authored
1387 pygame.event.get() # clear event queue
1388 showGameOverScreen()
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1389 waitForInput()
b68496b @djrahl first commit
authored
1390
1391
1392 def showGameOverScreen():
6c613da @djrahl Worked on AI; added crude apple detection.
authored
1393 """
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1394 Displays 'Game Over' message.
6c613da @djrahl Worked on AI; added crude apple detection.
authored
1395 Returns when any key pressed.
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
authored
1396 """
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
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 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1403 #drawMessage('Press any key.', WINDOWWIDTH / 2, WINDOWHEIGHT / 20 * 19, GOLDENROD)
b68496b @djrahl first commit
authored
1404 pygame.display.update()
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1405 #pygame.time.wait(100)
b68496b @djrahl first commit
authored
1406
1407
6d8cfaf @djrahl set-up ai
authored
1408 def getGrid(allsnake, allfruit):
6c613da @djrahl Worked on AI; added crude apple detection.
authored
1409 """
c46945d @djrahl Moved Tally Class into Game Data- now passed from menu. Added support…
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 @djrahl set-up ai
authored
1414 # refresh grid, dictionary representation of playing board used by AI
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1415 grid = {(x,y):0 for x in range(CELLWIDTH) for y in range(CELLHEIGHT + (TOP_BUFFER / CELLSIZE))}
6d8cfaf @djrahl 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 @djrahl 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 @djrahl moved fps changes to game class; added speed controls when only AIs p…
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 @djrahl Worked on AI; added crude apple detection.
authored
1436
6d8cfaf @djrahl set-up ai
authored
1437 return grid
b68496b @djrahl first commit
authored
1438
1439
9504e62 @djrahl added party mode.
authored
1440 def drawText(text, value, x=1, y=1, color=WHITE, background=BLACK):
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1441 """
1442 Draws text & value with background to screen.
1443 """
9504e62 @djrahl added party mode.
authored
1444 scoreSurf = BASICFONT.render('%s %s' % (text, value), True, color, background)
b68496b @djrahl first commit
authored
1445 scoreRect = scoreSurf.get_rect()
faa87d1 @djrahl added Snake, Fruit, Tally classes
authored
1446 scoreRect.topleft = (x, y)
b68496b @djrahl first commit
authored
1447 DISPLAYSURF.blit(scoreSurf, scoreRect)
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1448
1449
ef0acb2 @djrahl consolidated game over sequence.
authored
1450 def drawMessage(text, x=1, y=1, color=MESSAGE_COLOR):
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
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 @djrahl first commit
authored
1458
6d8cfaf @djrahl set-up ai
authored
1459
b68496b @djrahl first commit
authored
1460 def drawGrid():
573b079 @djrahl moved fps changes to game class; added speed controls when only AIs p…
authored
1461 """
1462 Draws grid to screen.
1463 """
b68496b @djrahl first commit
authored
1464 for x in range(0, WINDOWWIDTH, CELLSIZE): # draw vertical lines
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
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 @djrahl Fixed grid and snake color changes.
authored
1467 pygame.draw.line(DISPLAYSURF, DARKGRAY, (0, y), (WINDOWWIDTH, y))
6d8cfaf @djrahl set-up ai
authored
1468
1469
1470 def debugPause():
1471 while True:
1472 if checkForKeyPress():
1473 return
1474
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
1475
6d8cfaf @djrahl 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 @djrahl first commit
authored
1489
1490
4b2744c @djrahl 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 @djrahl Added more selection for Duel Mode.
authored
1493
1494
d313d65 @djrahl fixed places in gamestats; end game requires only one click/key to re…
authored
1495 def getStartCoords(pos=1):
6127227 @djrahl 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 @djrahl Fixed getStartPosition.
authored
1503 return [{'x':5, 'y':CELLHEIGHT-5},{'x':4, 'y':CELLHEIGHT-5},{'x':3, 'y':CELLHEIGHT-5}]
4b2744c @djrahl added post-game tally, added event handling for sharp turns
authored
1504
1505
b68496b @djrahl first commit
authored
1506 if __name__ == '__main__':
1507 main()
1508
Something went wrong with that request. Please try again.