所以我通过senddex上的newboston youtube频道上的pygame教程制作了Nibbles / Snake重拍。我做了很多微小的审美变化,但总的来说,这是同一个游戏。这是代码:
import pygame
import time
import random
pygame.init()
# A few extra colors just for testing purposes.
WHITE = (pygame.Color("white"))
BLACK = ( 0, 0, 0)
RED = (245, 0, 0)
TURQ = (pygame.Color("turquoise"))
GREEN = ( 0, 155, 0)
GREY = ( 90, 90, 90)
SCREEN = (800, 600)
gameDisplay = pygame.display.set_mode(SCREEN)
#Set the window title and picture
pygame.display.set_caption('Slither')
ICON = pygame.image.load("apple10pix.png")
pygame.display.set_icon(ICON)
CLOCK = pygame.time.Clock()
FPS = 20
FONT = pygame.font.SysFont("arial", 25)
SNAKE_SIZE = 10 # The width of the snake in pixels, not the length. Start length is defined in the game loop.
APPLE_SIZE = 10
TINY_FONT = pygame.font.SysFont("candara", 15)
SMALL_FONT = pygame.font.SysFont("candara", 25)
MED_FONT = pygame.font.SysFont("candara", 50)
LARGE_FONT = pygame.font.SysFont("krabbypatty", 75)
HUGE_FONT = pygame.font.SysFont("krabbypatty", 150)
IMG = pygame.image.load("snakehead.png")
APPLE_IMG = pygame.image.load("apple10pix.png")
DIRECTION = "up"
def pause():
paused = True
message_to_screen("Paused",
BLACK,
Y_DISPLACE = -100,
size = "huge")
message_to_screen("Press C to continue or Q to quit.",
BLACK,
Y_DISPLACE = 25)
pygame.display.update()
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key in (pygame.K_c, pygame.K_p):
paused = False
elif event.key in(pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
CLOCK.tick(5)
def score(score):
text = SMALL_FONT.render("Score: " + str(score), True, BLACK)
gameDisplay.blit(text, [0, 0])
pygame.display.update
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
intro = False
if event.key in (pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
gameDisplay.fill(WHITE)
message_to_screen("Welcome to",
GREEN,
Y_DISPLACE = -170,
size = "large")
message_to_screen("Block Worm",
GREEN,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("The objective of the game is to eat apples.",
BLACK,
Y_DISPLACE = 36,
size = "tiny")
message_to_screen("The more apples you eat the longer you get.",
BLACK,
Y_DISPLACE = 68,
size = "tiny")
message_to_screen("If you run into yourself or the edges, you die.",
BLACK,
Y_DISPLACE = 100,
size = "tiny")
message_to_screen("Press C to play or Q to quit.",
GREY,
Y_DISPLACE = 210,)
pygame.display.update()
CLOCK.tick(FPS)
def snake(SNAKE_SIZE, SNAKE_LIST):
if DIRECTION == "right":
HEAD = pygame.transform.rotate(IMG, 270)
elif DIRECTION == "left":
HEAD = pygame.transform.rotate(IMG, 90)
elif DIRECTION == "down":
HEAD = pygame.transform.rotate(IMG, 180)
else:
DIRECTION == "up"
HEAD = IMG
gameDisplay.blit(HEAD, (SNAKE_LIST[-1][0], SNAKE_LIST[-1][1]))
for XnY in SNAKE_LIST[:-1]:
pygame.draw.rect(gameDisplay, GREEN, [XnY[0], XnY[1], SNAKE_SIZE, SNAKE_SIZE])
pygame.display.update
def text_objects(text, color, size):
if size == "tiny":
TEXT_SURFACE = TINY_FONT.render(text, True, color)
elif size == "small":
TEXT_SURFACE = SMALL_FONT.render(text, True, color)
elif size == "medium":
TEXT_SURFACE = MED_FONT.render(text, True, color)
elif size == "large":
TEXT_SURFACE = LARGE_FONT.render(text, True, color)
elif size == "huge":
TEXT_SURFACE = HUGE_FONT.render(text, True, color)
return TEXT_SURFACE, TEXT_SURFACE.get_rect()
def message_to_screen(msg, color, Y_DISPLACE = 0, size = "small"):
TEXT_SURF, TEXT_RECT = text_objects(msg, color, size)
TEXT_RECT.center = (SCREEN[0] / 2), (SCREEN[1] / 2) + Y_DISPLACE
gameDisplay.blit(TEXT_SURF, TEXT_RECT)
def randAppleGen():
randAppleX = random.randrange(0, (SCREEN[0] - APPLE_SIZE), APPLE_SIZE)
randAppleY = random.randrange(0, (SCREEN[1]- APPLE_SIZE), APPLE_SIZE)
return randAppleX, randAppleY
def gameLoop():
global DIRECTION
gameExit = False
gameOver = False
SNAKE_LIST = [] # Where the snake head has been.
SNAKE_LENGTH = 1 #Length that the snake starts.
lead_x = (SCREEN[0] / 2)
lead_y = (SCREEN[1] - (SCREEN[1] / 5))
move_speed = 10
move_speed_neg = move_speed * -1
lead_x_change = 0
lead_y_change = -move_speed
randAppleX, randAppleY = randAppleGen()
while not gameExit:
if gameOver == True:
message_to_screen("Game over",
RED,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("Press C to play again or Q to quit.",
BLACK,
Y_DISPLACE = 50,
size = "small")
pygame.display.update()
while gameOver == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
gameOver = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameOver = False
gameExit = True
elif event.key == pygame.K_c:
gameLoop()
# Handles arrow key and WASD events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
elif event.type == pygame.KEYDOWN:
if event.key in (pygame.K_LEFT, pygame.K_a):
lead_x_change = move_speed_neg
lead_y_change = 0
DIRECTION = "left"
elif event.key in (pygame.K_RIGHT, pygame.K_d):
lead_x_change = move_speed
lead_y_change = 0
DIRECTION = "right"
elif event.key in (pygame.K_UP, pygame.K_w):
lead_y_change = move_speed_neg
lead_x_change = 0
DIRECTION = "up"
elif event.key in (pygame.K_DOWN, pygame.K_s):
lead_y_change = move_speed
lead_x_change = 0
DIRECTION = "down"
elif event.key in (pygame.K_p, pygame.K_ESCAPE):
pause()
# If the snake goes beyond the screen borders the game will end.
if lead_x >= SCREEN[0] or lead_x < 0 or lead_y >= SCREEN[1] or lead_y <0:
gameOver = True
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(WHITE)
# Draw the apple on screen
APPLE_RECT = pygame.draw.rect(gameDisplay, RED, [randAppleX, randAppleY, APPLE_SIZE, APPLE_SIZE])
if APPLE_RECT in SNAKE_LIST:
APPLE_RECT #If the apple appears anywhere "under" the snake, it will immediately respawn elsewhere.
# Draw the snake on screen
SNAKE_HEAD = []
SNAKE_HEAD.append(lead_x)
SNAKE_HEAD.append(lead_y)
SNAKE_LIST.append(SNAKE_HEAD)
# If you hit yourself, game over.
if SNAKE_HEAD in SNAKE_LIST[:-1]:
gameOver = True
if len(SNAKE_LIST) > SNAKE_LENGTH:
del SNAKE_LIST[0]
snake(SNAKE_SIZE, SNAKE_LIST)
score(SNAKE_LENGTH - 1)
# If the snake eats the apple
if APPLE_RECT.collidepoint(lead_x, lead_y) == True:
randAppleX, randAppleY = randAppleGen()
SNAKE_LENGTH += 1
pygame.display.update()
CLOCK.tick(FPS)
pygame.quit()
quit()
game_intro()
gameLoop()
这是一个相当稳固的小游戏。但是我想把蛇和苹果分成几类,这样我以后可以产生其他类型的蛇(也许是基本的AI?)和其他类型的苹果(也许是绿色的,可以让你的蛇变成3+)。我试图用蛇类来做这件事:
import pygame
import time
import random
pygame.init()
WHITE = (pygame.Color("white"))
BLACK = ( 0, 0, 0)
RED = (245, 0, 0)
TURQ = (pygame.Color("turquoise"))
GREEN = ( 0, 155, 0)
GREY = ( 90, 90, 90)
SCREEN = (800, 600)
gameDisplay = pygame.display.set_mode(SCREEN)
#Set the window title and picture
pygame.display.set_caption('Block Worm')
ICON = pygame.image.load("apple10pix.png")
pygame.display.set_icon(ICON)
CLOCK = pygame.time.Clock()
FPS = 20
FONT = pygame.font.SysFont("arial", 25)
APPLE_SIZE = 10
TINY_FONT = pygame.font.SysFont("candara", 15)
SMALL_FONT = pygame.font.SysFont("candara", 25)
MED_FONT = pygame.font.SysFont("candara", 50)
LARGE_FONT = pygame.font.SysFont("krabbypatty", 75)
HUGE_FONT = pygame.font.SysFont("krabbypatty", 150)
IMG = pygame.image.load("snakehead.png")
APPLE_IMG = pygame.image.load("apple10pix.png")
def pause():
paused = True
message_to_screen("Paused",
BLACK,
Y_DISPLACE = -100,
size = "huge")
message_to_screen("Press C to continue or Q to quit.",
BLACK,
Y_DISPLACE = 25)
pygame.display.update()
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key in (pygame.K_c, pygame.K_p):
paused = False
elif event.key in(pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
CLOCK.tick(5)
def score(score):
text = SMALL_FONT.render("Score: " + str(score), True, BLACK)
gameDisplay.blit(text, [5, 5])
pygame.display.update
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
intro = False
if event.key in (pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
gameDisplay.fill(WHITE)
message_to_screen("Welcome to",
GREEN,
Y_DISPLACE = -170,
size = "large")
message_to_screen("Block Worm",
GREEN,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("The objective of the game is to eat apples.",
BLACK,
Y_DISPLACE = 36,
size = "tiny")
message_to_screen("The more apples you eat the longer you get.",
BLACK,
Y_DISPLACE = 68,
size = "tiny")
message_to_screen("If you run into yourself or the edges, you die.",
BLACK,
Y_DISPLACE = 100,
size = "tiny")
message_to_screen("Press C to play or Q to quit.",
GREY,
Y_DISPLACE = 210,)
pygame.display.update()
CLOCK.tick(FPS)
def text_objects(text, color, size):
if size == "tiny":
TEXT_SURFACE = TINY_FONT.render(text, True, color)
elif size == "small":
TEXT_SURFACE = SMALL_FONT.render(text, True, color)
elif size == "medium":
TEXT_SURFACE = MED_FONT.render(text, True, color)
elif size == "large":
TEXT_SURFACE = LARGE_FONT.render(text, True, color)
elif size == "huge":
TEXT_SURFACE = HUGE_FONT.render(text, True, color)
return TEXT_SURFACE, TEXT_SURFACE.get_rect()
def message_to_screen(msg, color, Y_DISPLACE = 0, size = "small"):
TEXT_SURF, TEXT_RECT = text_objects(msg, color, size)
TEXT_RECT.center = (SCREEN[0] / 2), (SCREEN[1] / 2) + Y_DISPLACE
gameDisplay.blit(TEXT_SURF, TEXT_RECT)
def randAppleGen():
randAppleX = random.randrange(0, (SCREEN[0] - APPLE_SIZE), APPLE_SIZE)
randAppleY = random.randrange(0, (SCREEN[1]- APPLE_SIZE), APPLE_SIZE)
return randAppleX, randAppleY
class Snake:
def __init__(self, image, x, y, direction, speed):
self.image = image
self.rect = self.image.get_rect()
self.width = self.rect.width
self.rect.x = x
self.rect.y = y
self.direction = direction
self.speed = speed
self.trail = [] # Where the snake head has been.
self.length = 1 # Length that the snake starts.
def snake_direction_change(direction):
if direction == "right":
self.image = pygame.transform.rotate(self.image, 270)
elif direction == "left":
self.image = pygame.transform.rotate(self.image, 90)
elif direction == "down":
self.image = pygame.transform.rotate(self.image, 180)
else:
direction == "up"
pygame.display.update
def snake_grow(x, y, z):
gameDisplay.blit(self.image, (self.trail[-1][0], self.trail[-1][1]))
for XnY in snake.trail[:-1]:
pygame.draw.rect(gameDisplay, GREEN, [XnY[0], XnY[1], self.width, self.width])
pygame.display.update
def gameLoop():
gameExit = False
gameOver = False
lead_x_change = 0
lead_y_change = -snake.speed
randAppleX, randAppleY = randAppleGen()
gameDisplay.fill(WHITE)
snake = Snake(IMG,
x = (SCREEN[0] / 2),
y =(SCREEN[1] - (SCREEN[1] / 5)),
direction = "up",
speed = 10,)
while not gameExit:
if gameOver == True:
message_to_screen("Game over",
RED,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("Press C to play again or Q to quit.",
BLACK,
Y_DISPLACE = 50,
size = "small")
pygame.display.update()
while gameOver == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
gameOver = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameOver = False
gameExit = True
elif event.key == pygame.K_c:
gameLoop()
# Handles arrow key and WASD events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
elif event.type == pygame.KEYDOWN:
if event.key in (pygame.K_LEFT, pygame.K_a):
lead_x_change = snake.speed * -1
lead_y_change = 0
snake.snake_direction_change("left")
elif event.key in (pygame.K_RIGHT, pygame.K_d):
lead_x_change = snake.speed
lead_y_change = 0
snake.snake_direction_change("right")
elif event.key in (pygame.K_UP, pygame.K_w):
lead_y_change = snake.speed * -1
lead_x_change = 0
snake.snake_direction_change("up")
elif event.key in (pygame.K_DOWN, pygame.K_s):
lead_y_change = snake.speed
lead_x_change = 0
snake.snake_direction_change("down")
elif event.key in (pygame.K_p, pygame.K_ESCAPE):
pause()
# If the snake goes beyond the screen borders the game will end.
if snake.rect.x >= SCREEN[0] or snake.rect.x < 0 or snake.rect.y >= SCREEN[1] or snake.rect.y <0:
gameOver = True
snake.rect.x += lead_x_change
snake.rect.y += lead_y_change
gameDisplay.fill(WHITE)
# Draw the apple on screen
APPLE_RECT = pygame.draw.rect(gameDisplay, RED, [randAppleX, randAppleY, APPLE_SIZE, APPLE_SIZE])
if APPLE_RECT in snake.trail:
APPLE_RECT #If the apple appears anywhere "under" the snake, it will immediately respawn elsewhere.
# Draw the snake on screen
SNAKE_HEAD = []
SNAKE_HEAD.append(snake.rect.x)
SNAKE_HEAD.append(snake.rect.y)
snake.trail.append(SNAKE_HEAD)
# If you hit yourself, game over.
if SNAKE_HEAD in snake.trail[:-1]:
gameOver = True
if len(snake.trail) > snake.length:
del snake.trail[0]
snake.snake_grow(snake.width, snake.trail)
score(snake.length - 1)
# If the snake eats the apple
if APPLE_RECT.collidepoint(snake.rect.x, snake.rect.y) == True:
randAppleX, randAppleY = randAppleGen()
snake.length += 1
pygame.display.update()
CLOCK.tick(FPS)
pygame.quit()
quit()
game_intro()
gameLoop()
这个版本不是那么可爱。事实上,它根本不起作用。我对课程和职能的理解充其量只是基础。在我的试错过程中,更改或完全删除了原始代码中的大量代码。我花了几个小时试图让这项工作无济于事。我的主要目标是制作一个Snake和Apple类,可以重复用于以后的两种变体。
所以,我来找你们好帮助我!我有两个主要问题:
1)我需要做些什么才能使其正常工作?
2)如何清理我的代码以使其更易于阅读并且整体效率更高?
答案 0 :(得分:0)
&#34;我的试错过程中更改或完全删除了原始代码中的许多代码&#34;
Bingo。您刚刚找到了问题的症结所在。软件开发应该是一个受控制的,深思熟虑的过程 - 而不是试验和错误。你需要有意识地,有目的地进行。
在介绍课程时,您尝试做(或应该尝试做)的是refactoring您的代码。
您应该重新使用原始的工作副本,并在引入Snake类时尽可能少地进行更改。第一步是简单地将snake
函数转换为类,并将其替换为。下面是您可以开始的地方:将此snake
方法替换为此Snake
类,然后更改您使用它的行
class Snake:
def __init__(self, SNAKE_SIZE, SNAKE_LIST):
if DIRECTION == "right":
HEAD = pygame.transform.rotate(IMG, 270)
elif DIRECTION == "left":
HEAD = pygame.transform.rotate(IMG, 90)
elif DIRECTION == "down":
HEAD = pygame.transform.rotate(IMG, 180)
else:
DIRECTION == "up" # note: this line does nothing
HEAD = IMG
gameDisplay.blit(HEAD, (SNAKE_LIST[-1][0], SNAKE_LIST[-1][1]))
for XnY in SNAKE_LIST[:-1]:
pygame.draw.rect(gameDisplay, GREEN, [XnY[0], XnY[1], SNAKE_SIZE, SNAKE_SIZE])
pygame.display.update # note: this likely does nothing - I think you want to call it (pygame.display.update())
并改变这一点:
snake(SNAKE_SIZE, SNAKE_LIST)
成:
snake = Snake(SNAKE_SIZE, SNAKE_LIST)
现在,在这一点上,如果您的代码之前有效,它应该仍然有效(假设我没有做任何愚蠢的事情)。这是一个很好的班级例子吗?没有。 My Snake课很糟糕。你对蛇类的尝试远远好得多。以这种方式做事给你一个起点。然后,您可以继续执行以下操作:
重构此模块的另一种方法可能是更改每个函数,以便它们都不依赖于模块级变量。将每个函数所需的每个变量传递给该函数。
我想告诉您的重点是,通过一次编写/更改一下,制作工作软件要容易得多。在更改其他内容之前确保它仍然有效。研究一小部分代码&amp;测试每个更改,以便您确切知道您的程序在何处以及如何破坏。