当前位置:网站首页>PyGame practical project: write Snake games with 300 lines of code
PyGame practical project: write Snake games with 300 lines of code
2022-07-05 21:49:00 【Blue bridge cloud class】
Greedy snake is a product with clear logic 、 It's easy to operate 、 It's good for young and old 、 Popular casual games .
Now let's introduce the basic principle of Snake game , And the relevant methods needed to realize snake eating .
One 、 Main idea
Our Snake game will mainly include three core modules , Namely Game start module 、 Game running module 、 Game end module . These three modules work together in this way : First, display the game start module , Then a cycle runs between the game running module and the display game end module .
The main idea of the game
1. Draw a 640*480 The window of
2. Define the size of the small square ( Must be able to be 640 and 480 to be divisible by )
3. Draw a picture of the beginning of the game , Wait for key event input
4. The main loop of the program contains two modules , One is the game operation module , The other is the module that displays the end of the game
5. Game running module :
- Random initialization sets a point as the starting point of greedy snake
- Take this point as the starting point , Create a length of 3 GE's greedy snake ( list )
- Initialize a direction of motion
- Random location of an apple
- Deal with events in the game loop
- Change the direction of the snake according to the key
- Check if the game is over ( Hit the border or hit yourself )
- Check whether the greedy snake eats apples
- Draw the background , square , snake , Apple , Scores and other game elements
6. Module that displays the end of the game
- draw Game Over
- Wait for the user to press the key to restart the game
Two 、 The core framework
Before writing core modules , We will first implement the core framework of this program and some necessary methods , Then gradually improve .
We regard the snake as a small square , Use constant CELLSIZE Indicates the size of the square , We regard the game screen as composed of the same small squares , We can connect with the specific pixels of the screen through the grid , Simplify programming , So there is CELLWIDTH and CELLHEIGHT Two variables .
stay main() In the method , We initialize pygame, And make some basic settings , Then display the game start screen , Then enter the main cycle of the game .
We define drawGrid() Method is used to draw all squares ,getRandomLocation() Method is used to randomly generate the location of apples , The generated coordinates are saved in a dictionary ,drawApple(coord) Method is used to draw apples according to the generated coordinate dictionary , Again ,drawWorm(wormCoords) Method is used to draw greedy snakes according to the coordinate dictionary list of greedy snakes ,drawScore(score) Method is used to display scores ,terminate() Method is used to exit the game , In our game start screen and game end screen , Use drawPressKeyMsg() Method is used to prompt key messages ,checkForKeyPress() Method is used to detect key events to decide whether to exit the cycle and enter the game running screen .
# -*- coding: UTF-8 -*-
# snake.py
import random, sys, time, pygame
from pygame.locals import *
# Screen refresh rate ( Here, it is equivalent to the speed of greedy snakes )
FPS = 5
# Screen width
WINDOWWIDTH = 640
# Screen height
WINDOWHEIGHT = 480
# The size of the small square
CELLSIZE = 20
# Assertion , The width and height of the screen must be divisible by the size of the square
assert WINDOWWIDTH % CELLSIZE == 0, "Window width must be a multiple of cell size."
assert WINDOWHEIGHT % CELLSIZE == 0, "Window height must be a multiple of cell size."
# The number of horizontal and vertical squares
CELLWIDTH = int(WINDOWWIDTH / CELLSIZE)
CELLHEIGHT = int(WINDOWHEIGHT / CELLSIZE)
# Define common colors
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
DARKGREEN = ( 0, 155, 0)
DARKGRAY = ( 40, 40, 40)
BGCOLOR = BLACK
# Define the action of greedy snake
UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'
# Greedy snake ( It is often used later )
HEAD = 0
def main():
# Define global variables
global FPSCLOCK, DISPLAYSURF, BASICFONT
# initialization pygame
pygame.init()
# get pygame The clock
FPSCLOCK = pygame.time.Clock()
# Set the screen width and height
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
# Set basic font
BASICFONT = pygame.font.Font('resources/ARBERKLEY.ttf', 18)
# Set the title of the window
pygame.display.set_caption('Snake')
# Show the game start screen
showStartScreen()
while True:
# Here, it keeps cycling between the game running time and the display of the game end screen , There is a cycle in the running game , There is also a cycle to show the end of the game , Both cycles have corresponding return, In this way, the effect of switching these two modules can be achieved
# Run the game
runGame()
# Show the end of the game
showGameOverScreen()
# Draw all squares
def drawGrid():
for x in range(0, WINDOWWIDTH, CELLSIZE):
# Draw a vertical line
pygame.draw.line(DISPLAYSURF, DARKGRAY, (x, 0), (x, WINDOWHEIGHT))
for y in range(0, WINDOWHEIGHT, CELLSIZE):
# Draw a horizontal line
pygame.draw.line(DISPLAYSURF, DARKGRAY, (0, y), (WINDOWWIDTH, y))
# Randomly generate the coordinate position of an apple
def getRandomLocation():
return {
'x': random.randint(0, CELLWIDTH - 1), 'y': random.randint(0, CELLHEIGHT - 1)}
# according to coord Draw apple
def drawApple(coord):
x = coord['x'] * CELLSIZE
y = coord['y'] * CELLSIZE
appleRect = pygame.Rect(x, y, CELLSIZE, CELLSIZE)
pygame.draw.rect(DISPLAYSURF, RED, appleRect)
# according to wormCoords Draw a list of greedy snakes
def drawWorm(wormCoords):
for coord in wormCoords:
x = coord['x'] * CELLSIZE
y = coord['y'] * CELLSIZE
wormSegmentRect = pygame.Rect(x, y, CELLSIZE, CELLSIZE)
pygame.draw.rect(DISPLAYSURF, DARKGREEN, wormSegmentRect)
wormInnerSegmentRect = pygame.Rect(x + 4, y + 4, CELLSIZE - 8, CELLSIZE - 8)
pygame.draw.rect(DISPLAYSURF, GREEN, wormInnerSegmentRect)
# Show scores
def drawScore(score):
scoreSurf = BASICFONT.render('Score: %s' % (score), True, WHITE)
scoreRect = scoreSurf.get_rect()
scoreRect.topleft = (WINDOWWIDTH - 120, 10)
DISPLAYSURF.blit(scoreSurf, scoreRect)
# Quit the game
def terminate():
pygame.quit()
sys.exit()
# Prompt key message
def drawPressKeyMsg():
pressKeySurf = BASICFONT.render('Press a key to play.', True, DARKGRAY)
pressKeyRect = pressKeySurf.get_rect()
pressKeyRect.topleft = (WINDOWWIDTH - 200, WINDOWHEIGHT - 30)
DISPLAYSURF.blit(pressKeySurf, pressKeyRect)
# Detect key events
def checkForKeyPress():
if len(pygame.event.get(QUIT)) > 0:
terminate()
keyUpEvents = pygame.event.get(KEYUP)
if len(keyUpEvents) == 0:
return None
if keyUpEvents[0].key == K_ESCAPE:
terminate()
return keyUpEvents[0].key
# Show the game start screen
def showStartScreen():
pass
# When the game is running
def runGame():
pass
# Show the end of the game
def showGameOverScreen():
pass
if __name__ == '__main__':
main()
3、 ... and 、 Game start module
The game start screen mainly displays the game name and prompt key information , At the same time, call to detect the key event to determine whether there is a key event , If you have any , Exit the start screen , Enter the game operation screen , Or just quit the game . showStartScreen() The specific implementation is as follows :
# Show the game start screen
def showStartScreen():
DISPLAYSURF.fill(BGCOLOR)
titleFont = pygame.font.Font('resources/ARBERKLEY.ttf', 100)
titleSurf = titleFont.render('Snake!', True, GREEN)
titleRect = titleSurf.get_rect()
titleRect.center = (WINDOWWIDTH / 2, WINDOWHEIGHT / 2)
DISPLAYSURF.blit(titleSurf, titleRect)
drawPressKeyMsg()
pygame.display.update()
while True:
if checkForKeyPress():
pygame.event.get()
return
Four 、 Game running module
In order to prevent the snake from getting too close to the wall as soon as it comes out , Cause the game to fail , So our snake will be some distance away from the wall . The range of random numbers generated is (5,CELLWIDTH-6). We use the data structure of dictionary to store the coordinates , Enclose these dictionary elements with a list .wormCoords For the coordinates of the snake , be wormCoords[0] For the expression of snake head , That is to say wormCoords[HEAD]. The movement of the snake is actually constantly deleting the tail , The process of adding a header . runGame() The specific implementation is as follows :
# Game running screen
def runGame():
# Random initialization sets a point as the starting point of greedy snake
startx = random.randint(5, CELLWIDTH - 6)
starty = random.randint(5, CELLHEIGHT - 6)
# Take this point as the starting point , Create a length of 3 GE's greedy snake ( list )
wormCoords = [{
'x': startx, 'y': starty},
{
'x': startx - 1, 'y': starty},
{
'x': startx - 2, 'y': starty}]
direction = RIGHT # Initialize a direction of motion
# Random location of an apple
apple = getRandomLocation()
# The main cycle of the game
while True:
# Event handling
for event in pygame.event.get():
# Exit event
if event.type == QUIT:
terminate()
# Key events
elif event.type == KEYDOWN:
# If you press the left key or a key , And the current direction is not to the right , Just change direction , And so on
if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:
direction = LEFT
elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
direction = RIGHT
elif (event.key == K_UP or event.key == K_w) and direction != DOWN:
direction = UP
elif (event.key == K_DOWN or event.key == K_s) and direction != UP:
direction = DOWN
elif event.key == K_ESCAPE:
terminate()
# Check whether the greedy snake hit the border , That is, check the coordinates of the snake head
if wormCoords[HEAD]['x'] == -1 or wormCoords[HEAD]['x'] == CELLWIDTH or wormCoords[HEAD]['y'] == -1 or wormCoords[HEAD]['y'] == CELLHEIGHT:
# game over
return
# Check whether the greedy snake hit itself , That is, check whether the coordinates of the snake head are equal to the coordinates of the snake body
for wormBody in wormCoords[1:]:
if wormBody['x'] == wormCoords[HEAD]['x'] and wormBody['y'] == wormCoords[HEAD]['y']:
# game over
return
# Check whether the greedy snake eats apples , If you don't eat it , Then delete the tail , The snake moves forward one space
if wormCoords[HEAD]['x'] == apple['x'] and wormCoords[HEAD]['y'] == apple['y']:
# Do not remove the last tail cell of the snake
# Regenerate an apple randomly
apple = getRandomLocation()
else:
# Remove the last tail compartment of the snake
del wormCoords[-1]
# According to the direction , Add a new snake head , Move the greedy snake in this way
if direction == UP:
newHead = {
'x': wormCoords[HEAD]['x'], 'y': wormCoords[HEAD]['y'] - 1}
elif direction == DOWN:
newHead = {
'x': wormCoords[HEAD]['x'], 'y': wormCoords[HEAD]['y'] + 1}
elif direction == LEFT:
newHead = {
'x': wormCoords[HEAD]['x'] - 1, 'y': wormCoords[HEAD]['y']}
elif direction == RIGHT:
newHead = {
'x': wormCoords[HEAD]['x'] + 1, 'y': wormCoords[HEAD]['y']}
# Insert a new snake head at the front of the array
wormCoords.insert(0, newHead)
# Draw the background
DISPLAYSURF.fill(BGCOLOR)
# Draw all squares
drawGrid()
# Draw greedy snake
drawWorm(wormCoords)
# Draw apple
drawApple(apple)
# Draw fractions ( The score is the current length of the greedy snake list -3)
drawScore(len(wormCoords) - 3)
# Update screen
pygame.display.update()
# Set frame rate
FPSCLOCK.tick(FPS)
5、 ... and 、 Game end module
The game end screen is similar to the game start screen ,showGameOverScreen() The specific implementation is as follows :
# Show the end of the game
def showGameOverScreen():
gameOverFont = pygame.font.Font('resources/ARBERKLEY.ttf', 50)
gameSurf = gameOverFont.render('Game', True, WHITE)
overSurf = gameOverFont.render('Over', True, WHITE)
gameRect = gameSurf.get_rect()
overRect = overSurf.get_rect()
gameRect.midtop = (WINDOWWIDTH / 2, WINDOWHEIGHT / 2-gameRect.height-10)
overRect.midtop = (WINDOWWIDTH / 2, WINDOWHEIGHT / 2)
DISPLAYSURF.blit(gameSurf, gameRect)
DISPLAYSURF.blit(overSurf, overRect)
drawPressKeyMsg()
pygame.display.update()
pygame.time.wait(500)
checkForKeyPress()
while True:
if checkForKeyPress():
pygame.event.get()
return
Try to run the code
if __name__ == "__main__":
main()
perform python snake.py
summary
We go through simple pygame Programming to achieve the classic Snake game , Through the above, , You should master the basic principles of the snake game and Pygame In depth application of , meanwhile , You can also use food pictures and snake pictures to modify the code to make the game more beautiful , Last , You should use other programming languages to realize Snake game , To deepen the understanding of the principle .
Reference material
If this article is useful, remember to give me a praise !
边栏推荐
- 854. 相似度为 K 的字符串 BFS
- The primary key is set after the table is created, but auto increment is not set
- Image editor for their AutoLayout environment
- 他们主动布局(autolayout)环境的图像编辑器
- 大约SQL现场“这包括”与“包括在”字符串的写法
- datagrid直接编辑保存“设计缺陷”
- 校招期间 准备面试算法岗位 该怎么做?
- Dbeaver executes multiple insert into error processing at the same time
- EasyExcel的讀寫操作
- Interviewer: will concurrent programming practice meet? (detailed explanation of thread control operation)
猜你喜欢
R language learning notes
Huawei fast game failed to call the login interface, and returned error code -1
ICMP 介绍
Golang (1) | from environmental preparation to quick start
Parker驱动器维修COMPAX控制器维修CPX0200H
从零开始实现lmax-Disruptor队列(四)多线程生产者MultiProducerSequencer原理解析
Oracle checkpoint queue - Analysis of the principle of instance crash recovery
EBS Oracle 11g 克隆步骤(单节点)
Cold violence -- another perspective of objective function setting
JMeter installation under win7
随机推荐
How can Huawei online match improve the success rate of player matching
Simple interest mode - lazy type
Evolution of zhenai microservice underlying framework from open source component encapsulation to self-development
深信服X计划-网络协议基础 DNS
Implementing Lmax disruptor queue from scratch (IV) principle analysis of multithreaded producer multiproducersequencer
Selenium finds the contents of B or P Tags
How to use tensorflow2 for cat and dog classification and recognition
Yolov5 training custom data set (pycharm ultra detailed version)
crm创建基于fetch自己的自定义报告
ESP32
办公遇到的问题--
CRM creates its own custom report based on fetch
HDU 4391 Paint The Wall 段树(水
MMAP
854. String BFS with similarity K
校招期间 准备面试算法岗位 该怎么做?
datagrid直接编辑保存“设计缺陷”
冯唐“春风十里不如你”数字藏品,7月8日登录希壤!
华为游戏多媒体服务调用屏蔽指定玩家语音方法,返回错误码3010
Cross end solution to improve development efficiency rapidly