1 #!/usr/bin/env python3 2 # -*- coding: utf-8 -*- 3 from sys import exit#调用exit函数,用于终止python程序 4 from random import choice#调用choice函数,返回一个列表,元组或字符串的随机项 5 6 import pygame#调用pygame库 7 from pygame.locals import QUIT, KEYDOWN#调用quit(用于退出python),keydown函数(触发按下某键时的功能) 8 9 TITLE = ‘贪吃蛇--Transfer by 逗比小青年‘ 10 11 WIDTH = 660#宽度 12 HEIGHT = 500#长度 13 SNAKE_SIZE = 20#每一块蛇的大小 14 BOARD_COLOR = (0, 0, 100)#底板颜色 15 16 17 class Vector(): 18 def __init__(self, x, y): 19 self._x = x 20 self._y = y 21 22 @property 23 def x(self): 24 return self._x 25 26 @property 27 def y(self): 28 return self._y 29 30 @x.setter 31 def x(self, value): 32 self._x = value 33 34 @y.setter 35 def y(self, value): 36 self._y = value 37 38 def __len__(self):#返回集合长度 39 return 2 40 41 def __getitem__(self, index):#getitem用于输出序列属性中的某个元素 42 if index == 0: 43 return self.x 44 if index == 1: 45 return self.y 46 raise IndexError#raise 关键字用于引发一个异常,即程序出现错误后,程序内部会显示"IndexError" 47 48 def copy(self):#复制对象子列 49 type_self = type(self) 50 return type_self(self.x, self.y) 51 52 def move(self, other):#运动函数 53 if isinstance(other, Vector):#isinstance() 函数用来判断一个对象是否是一个已知的类型 54 self.x += other.x 55 self.y += other.y 56 else: 57 self.x += other 58 self.y += other 59 return self 60 61 def __eq__(self, other): 62 if isinstance(other, Vector): 63 return self.x == other.x and self.y == other.y 64 return NotImplemented 65 66 def __ne__(self, other): 67 if isinstance(other, Vector): 68 return self.x != other.x or self.y != other.y 69 return NotImplemented 70 71 def __repr__(self):#repr() 函数将对象转化为供解释器读取的形式 72 type_self = type(self) 73 name = type_self.__name__ 74 return ‘{}({!r}, {!r})‘.format(name, self.x, self.y) 75 76 77 class Snake: 78 def __init__(self): 79 self.map = {(x, y): 0 80 for x in range(1, 81 int(WIDTH / SNAKE_SIZE) - 2) 82 for y in range(1, 83 int(HEIGHT / SNAKE_SIZE) - 2)} 84 self.body = [ 85 Vector(5 * SNAKE_SIZE, 5 * SNAKE_SIZE), 86 Vector(6 * SNAKE_SIZE, 5 * SNAKE_SIZE) 87 ] 88 self.head = self.body[-1].copy() 89 self.color = (0, 0, 0) 90 self.direction = { 91 ‘right‘: Vector(SNAKE_SIZE, 0), 92 ‘left‘: Vector(-SNAKE_SIZE, 0), 93 ‘up‘: Vector(0, -SNAKE_SIZE), 94 ‘down‘: Vector(0, SNAKE_SIZE) 95 } 96 self.move_direction = ‘right‘ 97 self.speed = 4 98 self.score = 0 99 self.food = Vector(0, 0) 100 self.food_color = (255, 0, 0) 101 self.generate_food() 102 self.game_started = False 103 104 def generate_food(self):#食物生成 105 empty_pos = [ 106 pos for pos in self.map.keys() 107 if Vector(pos[0] * SNAKE_SIZE, pos[1] * 108 SNAKE_SIZE) not in self.body 109 ] 110 result = choice(empty_pos) 111 self.food.x = result[0] * 20 112 self.food.y = result[1] * 20 113 114 def move(self):#移动中的进食过程与死亡判断 115 self.head = self.body[-1].copy() 116 self.head.move(self.direction[self.move_direction]) 117 if not self._islive(self.head): 118 return False 119 120 self.body.append(self.head) 121 122 if self.head == self.food: 123 self.score += 1 124 if self.score % 5 == 0: 125 self.speed += 2 126 self.generate_food() 127 else: 128 self.body.pop(0) 129 return True 130 131 def _islive(self, head):#死亡定义 132 return 0 < head.x < WIDTH - SNAKE_SIZE and 0 < head.y < HEIGHT - SNAKE_SIZE and head not in self.body 133 134 135 KEY_DIRECTION_DICT = {#操控键位定义 136 119: ‘up‘, # W 137 115: ‘down‘, # S 138 97: ‘left‘, # A 139 100: ‘right‘, # D 140 273: ‘up‘, # UP 141 274: ‘down‘, # DOWN 142 276: ‘left‘, # LEFT 143 275: ‘right‘, # RIGHT 144 } 145 146 147 def press(events, snake): 148 for event in events: 149 if event.type == QUIT: 150 exit() 151 if event.type == KEYDOWN: 152 if event.key == 13: 153 snake.game_started = True 154 if snake.game_started and event.key in KEY_DIRECTION_DICT: 155 return direction_check(snake.move_direction, 156 KEY_DIRECTION_DICT[event.key]) 157 158 159 def draw_score(screen, score, position):#实时分数显示 160 tips_font = pygame.font.SysFont(‘arial‘, 20) 161 screen.blit( 162 tips_font.render(‘Score: {}‘.format(score), True, (0, 0, 205), 163 (255, 255, 255)), position) 164 165 166 def game_continue(screen, snake): 167 init_board(screen) 168 draw_score(screen, snake.score, (500, 0)) 169 for seg in snake.body: 170 pygame.draw.rect(screen, snake.color, [seg[0], seg[1], 20, 20], 0) 171 pygame.draw.rect(screen, snake.food_color, 172 [snake.food[0], snake.food[1], 20, 20], 0) 173 174 175 def game_over(screen, fonts, score): 176 screen.blit(fonts[‘game_over‘], (250, 100)) 177 draw_score(screen, score, (290, 200)) 178 screen.blit(fonts[‘start‘], (220, 310)) 179 snake = Snake() 180 return snake 181 182 183 def direction_check(move_direction, change_direction):#键位感知 184 directions = [[‘up‘, ‘down‘], [‘left‘, ‘right‘]] 185 if move_direction in directions[0] and change_direction in directions[1]: 186 return change_direction 187 elif move_direction in directions[1] and change_direction in directions[0]: 188 return change_direction 189 190 return move_direction 191 192 193 def init(fonts):#游戏界面文字布置 194 fps_clock = pygame.time.Clock() 195 pygame.display.set_caption(TITLE) 196 screen = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32) 197 screen.fill((255, 255, 255)) 198 screen.blit(fonts[‘welcome‘], (177, 100)) 199 screen.blit(fonts[‘start‘], (195, 310)) 200 return fps_clock, screen 201 202 203 def init_board(screen):#边框定制 204 board_width = int(WIDTH / SNAKE_SIZE) 205 board_height = int(HEIGHT / SNAKE_SIZE) 206 color = BOARD_COLOR 207 width = 0 208 for i in range(board_width): 209 pos = i * SNAKE_SIZE, 0, SNAKE_SIZE, SNAKE_SIZE 210 pygame.draw.rect(screen, color, pos, width) 211 pos = i * SNAKE_SIZE, (board_height - 212 1) * SNAKE_SIZE, SNAKE_SIZE, SNAKE_SIZE 213 pygame.draw.rect(screen, color, pos, width) 214 215 # 上下边框占用了 Y: 0 26*20 216 for i in range(board_height - 1): 217 pos = 0, SNAKE_SIZE + i * SNAKE_SIZE, SNAKE_SIZE, SNAKE_SIZE 218 pygame.draw.rect(screen, color, pos, width) 219 pos = ( 220 board_width - 1 221 ) * SNAKE_SIZE, SNAKE_SIZE + i * SNAKE_SIZE, SNAKE_SIZE, SNAKE_SIZE 222 pygame.draw.rect(screen, color, pos, width) 223 224 225 def font_setting():#游戏初始,游戏结束,游戏胜利界面文字布置 226 title_font = pygame.font.SysFont(‘arial‘, 32) 227 welcome_words = title_font.render(‘Welcome to My Snake‘, True, (0, 0, 0), 228 (255, 255, 255)) 229 tips_font = pygame.font.SysFont(‘arial‘, 24) 230 start_game_words = tips_font.render(‘Press Enter to Start Game‘, True, 231 (0, 0, 0), (255, 255, 255)) 232 gameover_words = title_font.render(‘GAME OVER‘, True, (205, 92, 92), 233 (255, 255, 255)) 234 win_words = title_font.render(‘THE SNAKE IS LONG ENOUGH AND YOU WIN!‘, 235 True, (0, 0, 205), (255, 255, 255)) 236 return { 237 ‘welcome‘: welcome_words, 238 ‘start‘: start_game_words, 239 ‘game_over‘: gameover_words, 240 ‘win‘: win_words 241 } 242 243 244 def main(): 245 pygame.init() 246 fonts = font_setting() 247 fps_clock, screen = init(fonts) 248 249 snake = Snake() 250 direction = snake.move_direction 251 while True: 252 events = pygame.event.get() 253 new_direction = press(events, snake) 254 if snake.game_started: 255 if new_direction: 256 snake.move_direction = new_direction 257 screen.fill((255, 255, 255)) 258 if not snake.move(): 259 snake = game_over(screen, fonts, snake.score) 260 direction = snake.move_direction 261 else: 262 game_continue(screen, snake) 263 pygame.display.update() 264 fps_clock.tick(snake.speed) 265 266 267 268 if __name__ == ‘__main__‘: 269 main()
原文:https://www.cnblogs.com/yeluozhiqiumax/p/13139955.html