前言
最近正在练习使用 pygame, 感觉这东西真的是功能强大、用途广泛。前几天用 pygame,写了一个 Console 程序,看起来很极客(实际上很弱智),今天觉得可以写一个简易的贪吃蛇程序。
游戏界面
其中,浅绿色的部分是水果(吃了之后蛇的长度 +1),深绿色的部分是蛇身(蛇头和蛇尾一个样,懒得处理了),暗绿色的部分是墙。
snake.py
贪吃蛇游戏的主程序。
from game_method import *
import random
import time
BOARD_EMPTY = 0
BOARD_SNAKE = 1
BOARD_WALL = 2
BOARD_FRUIT = 3
chessboard = {}
WIDTH = 20
HEIGHT = 20
for i in range(0, HEIGHT):
for j in range(0, WIDTH):
chessboard[(i, j)] = BOARD_EMPTY
RESOLUTION = (1920, 1080)
REDIUS = int((RESOLUTION[1] - 50) / HEIGHT / 2) - 2
SNAKE_BODY = []
INIT_LEN = 4
for i in range(0, INIT_LEN):
SNAKE_BODY.append((int(HEIGHT/2), int(WIDTH/2) + i))
DIRX = {}
DIRY = {}
DIRX['LEFT'] = 0
DIRX['RIGHT'] = 0
DIRX['UP'] = -1
DIRX['DOWN'] = 1
DIRY['LEFT'] = -1
DIRY['RIGHT'] = 1
DIRY['UP'] = 0
DIRY['DOWN'] = 0
DIRECTION = 'LEFT'
def NextHead():
NowHead = SNAKE_BODY[0]
nextHead = ((NowHead[0] + DIRX[DIRECTION]) % HEIGHT, (NowHead[1] + DIRY[DIRECTION]) % WIDTH)
return nextHead
def Crash():
return chessboard[NextHead()] != BOARD_EMPTY and chessboard[NextHead()] != BOARD_FRUIT
def Grow():
return chessboard[NextHead()] == BOARD_FRUIT
Window = screen(Title = "Snake Game", FullScreen = True, Resolution = RESOLUTION)
Window.Fill((0, 0, 0))
def Modify(R, G, B, rate):
return (int(R*rate), int(G*rate), int(B*rate))
LINECOLOR = Modify(34, 252, 43, 0.10)
"""
def GetColor(BOARD_TYPE): # 获得某种区块对应的颜色
if BOARD_TYPE == BOARD_EMPTY: return ( 0, 0, 0)
if BOARD_TYPE == BOARD_FRUIT: return (255, 50, 50)
if BOARD_TYPE == BOARD_SNAKE: return ( 50, 50, 255)
if BOARD_TYPE == BOARD_WALL : return (127, 127, 127)
return (0, 255, 0) # Error color
"""
def GetColor(BOARD_TYPE):
if BOARD_TYPE == BOARD_EMPTY: return Modify(34, 252, 43, 0.00)
if BOARD_TYPE == BOARD_FRUIT: return Modify(34, 252, 43, 1.00)
if BOARD_TYPE == BOARD_SNAKE: return Modify(34, 252, 43, 0.50)
if BOARD_TYPE == BOARD_WALL : return Modify(34, 252, 43, 0.10)
return (0, 255, 0)
def ShowChessBoard():
D = (RESOLUTION[1] - 50) / HEIGHT
for i in range(0, HEIGHT + 1):
pygame.draw.line(Window.Screen, LINECOLOR, (0, D*i), (RESOLUTION[1] - 50, D*i), 3)
for i in range(0, WIDTH + 1):
pygame.draw.line(Window.Screen, LINECOLOR, (D*i, 0), (D*i, RESOLUTION[1] - 50), 3)
for i in range(0, HEIGHT):
for j in range(0, WIDTH):
if chessboard[(i, j)] == BOARD_SNAKE:
chessboard[(i, j)] = BOARD_EMPTY
for pos in SNAKE_BODY:
chessboard[pos] = BOARD_SNAKE
for i in range(0, HEIGHT):
for j in range(0, WIDTH):
pos = (D*j + int(D/2), D*i + int(D/2))
pygame.draw.circle(Window.Screen, GetColor(chessboard[(i, j)]), pos, int(D/2) - 4)
def dir(EventKey):
if EventKey == K_LEFT: return 'LEFT'
elif EventKey == K_RIGHT: return 'RIGHT'
elif EventKey == K_UP: return 'UP'
else: return 'DOWN'
SPEED = 0.2
def RandFruit():
posList = []
for i in range(0, HEIGHT):
for j in range(0, WIDTH):
if chessboard[(i, j)] == BOARD_EMPTY:
posList.append((i, j))
if len(posList) > 0:
id = random.randint(0, len(posList) - 1)
chessboard[posList[id]] = BOARD_FRUIT
Message = "Paused ..."
state = text(Window, Message = Message)
length = text(Window)
if __name__ == "__main__":
running = False
BeginTime = time.time()
ShowChessBoard()
RandFruit()
for i in range(0, HEIGHT):
for j in range(0, WIDTH):
if chessboard[(i, j)] == BOARD_EMPTY and (i, j) != NextHead():
if random.randint(0, 100) < 10:
chessboard[(i, j)] = BOARD_WALL
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
elif event.key == K_SPACE and Message != "You Dead!":
running = not running
BeginTime = time.time()
if running:
Message = "Running ..."
else:
Message = "Paused ..."
if running:
if event.key == K_LEFT or event.key == K_RIGHT:
if DIRECTION != 'LEFT' and DIRECTION != 'RIGHT':
DIRECTION = dir(event.key)
elif event.key == K_UP or event.key == K_DOWN:
if DIRECTION != 'UP' and DIRECTION != 'DOWN':
DIRECTION = dir(event.key)
if running:
if time.time() - BeginTime >= SPEED:
if Crash():
running = False
Message = "You Dead!"
elif Grow():
SNAKE_BODY = [NextHead()] + SNAKE_BODY
chessboard[SNAKE_BODY[0]] = BOARD_SNAKE
RandFruit()
else:
SNAKE_BODY = [NextHead()] + SNAKE_BODY
del SNAKE_BODY[len(SNAKE_BODY) - 1]
BeginTime = time.time()
Window.Fill((0, 0, 0))
state.ChangeMessage(Message + " ESC to exit, SPACE to pause.")
state.Show((RESOLUTION[1] + 20, 20))
length.ChangeMessage("Length: " + str(len(SNAKE_BODY)))
length.Show((RESOLUTION[1] + 20, 42))
ShowChessBoard()
pygame.display.flip()
game_method.py
须和 snake.py 放在同一目录下。
import pygame
from pygame.locals import *
from sys import exit
class screen(object):
def __init__(self, Title = "GGN PyGame Template", FullScreen = True, Resolution = (1920,1080)):
self.Title = Title
self.FullScreen = FullScreen
self.Resolution = Resolution
pygame.display.set_caption(Title)
if self.FullScreen:
self.Screen = pygame.display.set_mode(Resolution, FULLSCREEN, 32)
else:
self.Screen = pygame.display.set_mode(Resolution, 0, 32)
def ChangeFullScreen(self):
self.FullScreen = not self.FullScreen
if self.FullScreen:
self.Screen = pygame.display.set_mode(self.Resolution, FULLSCREEN, 32)
else:
self.Screen = pygame.display.set_mode(self.Resolution, 0, 32)
def ChangeTitle(self, NewTitle):
self.Title = NewTitle
pygame.display.set_caption(Title)
def Fill(self, Color = (0, 0, 0)):
self.Screen.fill(Color)
class text(object):
def __init__(self, Screen, FontName = "consolas", CharSize = 20, Message = "", Color = (34, 252, 43)):
self.Visible = True
self.Screen = Screen.Screen
self.FontName = FontName
self.CharSize = CharSize
self.Message = Message
self.Color = Color
self.Font = pygame.font.SysFont(self.FontName, self.CharSize)
self.Text = self.Font.render(self.Message, True, self.Color)
def ChangeMessage(self, NewMessage):
self.Message = NewMessage
self.Text = self.Font.render(NewMessage, True, self.Color)
def SetVisible(self, NewVisible = True):
self.Visible = NewVisible
def Show(self, Position = (0, 0)):
if self.Visible:
self.Screen.blit(self.Text, Position)
pygame.init()
|