Python Google Dinosaur--Pygame

Python Google Dinosaur (continuously updated, unfinished)

foreword

  • This is the first time I write a blog, and there may be some things that are not very well written. Welcome to comment and suggest.
  • My starting point for writing this blog is to share my process of writing code with you with simple and clear code, and I hope it will be helpful to you.
  • If you have needs, you can also contact me, and I can also take on some small projects such as course design . +v: Ts_liyun
  • In addition, this article is also a process of my own learning, and some reference articles will be listed in the article or at the end of the article.

First of all, we want to achieve the final effect like this.
The little dinosaur jumping game that appears when Google Chrome cannot browse
If you want to try it, you can directly enter the URL in Google Chrome to open: chrome://dino
Other browsers can use this URL: https://dino.zone/zh-cn/

If you are interested in this game and want to write it with your own hands, then let's continue to read. At the same time, it is also recommended that friends who read this article and want to learn pay attention to the difference between the code before and after. Since I thought about this game slowly by myself (without referring to any code of the little dinosaur jumping game), I will also add some of my own ideas in it, so maybe my ideas are not suitable for everyone, but I still Hope you can learn something useful from it.

So without further ado, let's start.

text

Next I will follow step by step to show my process of writing this game.
In the article, I will first display the results with pictures and then explain the code for everyone.
In addition, it is recommended to master some basic syntax of the Python language before reading this article, and have some preliminary understanding of the Pygame library. I personally recommend reading this blog: Python Game Programming (Pygame )

create window

Since we want to write a game, we definitely need a window display.
First create a window through the built-in function of Pygame.

import pygame
import sys

pygame.init()  # 初始化pygame
size = width, height = 734, 286  # 设置窗口大小
screen = pygame.display.set_mode(size)  # 显示窗口

while True:  # 死循环确保窗口一直显示
    for event in pygame.event.get():  # 遍历所有事件
        if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
            sys.exit()

Regarding the size of the window frame, I designed it according to the size of the picture of the small dinosaur background.

Add a static background image

Next we import the background.

import pygame
import sys

pygame.init()  # 初始化pygame
size = width, height = 734, 286  # 设置窗口大小
screen = pygame.display.set_mode(size)  # 显示窗口

background = pygame.image.load('D:/project/Python/PDL_Python/pygame/dragon/picture/background1.png')  # 加载图片
backgroundrect = background.get_rect()  # 获取矩形区域

while True:  # 死循环确保窗口一直显示
    for event in pygame.event.get():  # 遍历所有事件
        if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
            sys.exit()

    screen.blit(background, backgroundrect)  # 将图片画到窗口上

    pygame.display.flip()  # 更新全部显示

You can click here to get the relevant pictures of this mini game from the network disk. Extraction code: 88iw
The image imported here is background1, you can also import background2, depending on your mood. Remember to replace the image path in the code, the above code is the direct address in my computer.

Add static baby dinosaur

Then we let the protagonist, the little dinosaur, appear on the stage.

import pygame
import sys

pygame.init()  # 初始化pygame
size = width, height = 734, 286  # 设置窗口大小
screen = pygame.display.set_mode(size)  # 显示窗口

background = pygame.image.load('D:/project/Python/PDL_Python/pygame/dragon/picture/background1.png')  # 加载图片
backgroundrect = background.get_rect()  # 获取矩形区域

dragon = pygame.image.load('D:/project/Python/PDL_Python/pygame/dragon/picture/dragon1.png')
dragonrect = dragon.get_rect()
dragonrect = dragonrect.move(50,210)


while True:  # 死循环确保窗口一直显示
    for event in pygame.event.get():  # 遍历所有事件
        if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
            sys.exit()

    screen.blit(background, backgroundrect)  # 将图片画到窗口上
    screen.blit(dragon, dragonrect)

    pygame.display.flip()  # 更新全部显示

When importing the picture, we will find that the little dinosaur is in the "sky", so we need to use the move function to move it to the "ground".

Let the little dinosaur move

insert image description here
Just now we inserted the picture and found that the little dinosaur is not moving on the ground, so next we try to make the little dinosaur move. If we have played this game, we will find that the movement of the little dinosaur can be divided into two steps. The first part is to let the little dinosaur stand still, and the second step is to let the background move to the left. Let's do the first part first:

import pygame
import sys

pygame.init()  # 初始化pygame
size = width, height = 734, 286  # 设置窗口大小
screen = pygame.display.set_mode(size)  # 显示窗口
clock = pygame.time.Clock()

background = pygame.image.load('D:/project/Python/PDL_Python/pygame/dragon/picture/background1.png')  # 加载图片
backgroundrect = background.get_rect()  # 获取矩形区域

dragon1 = pygame.image.load('D:/project/Python/PDL_Python/pygame/dragon/picture/dragon1.png')
dragon2 = pygame.image.load('D:/project/Python/PDL_Python/pygame/dragon/picture/dragon2.png')
dragonrect = dragon1.get_rect()
dragonrect = dragonrect.move(50,210)

flag = True
while True:  # 死循环确保窗口一直显示
    clock.tick(6)
    for event in pygame.event.get():  # 遍历所有事件
        if event.type == pygame.QUIT:  # 如果单击关闭窗口,则退出
            sys.exit()

    screen.blit(background, backgroundrect)  # 将图片画到窗口上
    if flag == True:
        screen.blit(dragon1, dragonrect)
    else:
        screen.blit(dragon2, dragonrect)
    flag = not flag

    pygame.display.flip()  # 更新全部显示

The principle of the little dinosaur walking in place is to play two pictures in the background in a loop.

Small program optimization (increase small knowledge)

In order to allow downloading users to use it after downloading, it is not necessary to change the address after downloading the code to use it, so the code is specially updated. The updates are as follows:

  1. Improve annotations. If you don't understand, you can private message or leave a message, and I will continue to improve.
  2. Use the OS library to read the current directory of the file and merge it into the address of the picture, so that there is no need to change the path frequently when reading the picture, just ensure that the entire folder is consistent when downloading .
    code show as below:
import pygame
import sys
import os

#获取当前文件的目录,方便在别的电脑运行时读取相应文件
Current_path = os.path.join(os.getcwd(), 'pygame', 'dragon', 'picture')
Current_path = Current_path.replace('\\', '/')

pygame.init()  # 初始化pygame
size = width, height = 734, 286  # 设置窗口大小
screen = pygame.display.set_mode(size)  # 显示窗口
clock = pygame.time.Clock() #创建一个时间对象用于控制游戏运作的快慢

background = pygame.image.load(Current_path + '/background1.png')  # 加载图片
backgroundrect = background.get_rect()  # 获取矩形区域

dragon1 = pygame.image.load(Current_path + '/dragon1.png')
dragon2 = pygame.image.load(Current_path + '/dragon2.png')
dragonrect = dragon1.get_rect()
dragonrect = dragonrect.move(50,210)    #将小恐龙移动到“地上”

flag = True #创建一个flag标志用于在循环中判断使用哪张图片
while True:  # 死循环确保窗口一直显示
    clock.tick(6)
    for event in pygame.event.get():  # 遍历所有事件
        if event.type == pygame.QUIT:  # 如果程序发现单击关闭窗口按钮
            sys.exit()  #将窗口关闭

    screen.blit(background, backgroundrect)  # 将背景图片画到窗口上

    #根据flag标志确定显示的图片,这样可以造成小恐龙在跑的现象
    if flag == True:
        screen.blit(dragon1, dragonrect)
    else:
        screen.blit(dragon2, dragonrect)
    flag = not flag

    pygame.display.flip()  # 更新全部显示

background moving

insert image description here
The little dinosaur is walking in place and the background is moving, so it really makes the little dinosaur run!
In fact, the principle of realizing this step is very simple. I used Tkinter (the user interface design package that comes with Python) to design an animation demonstration. In fact, the two backgrounds are moving in a cycle behind.
insert image description here
In the picture above, the black frame represents the screen displayed by our game, while the red and blue are two background frames respectively. When we let them "line up" and slide past the program window, the effect of background motion is formed.
The specific implementation method is that we detect the right border of the red frame, and when it moves out of the screen, we let it teleport behind the blue frame, that is, set the red left frame to match the blue left frame at this time Consistent, it may be a bit convoluted, just look at the animation above to understand, of course, we do the same with the blue box.
The following code changes the content:
1. Import one more background image and design one more background frame
2. Let the background move circularly (lines 42-47)

import pygame
import sys
import os

#获取当前文件的目录,方便在别的电脑运行时读取相应文件
Current_path = os.path.join(os.getcwd(), 'picture')
Current_path = Current_path.replace('\\', '/')

pygame.init()  # 初始化pygame
size = width, height = 734, 286  # 设置窗口大小
screen = pygame.display.set_mode(size)  # 显示窗口
clock = pygame.time.Clock() #创建一个时间对象用于控制游戏运作的快慢

background1 = pygame.image.load(Current_path + '/background1.png')  # 加载图片
background2 = pygame.image.load(Current_path + '/background2.png')  # 加载图片
backgroundrect1 = background1.get_rect()  # 获取矩形区域
backgroundrect2 = background2.get_rect()  # 获取矩形区域
backgroundrect2[0] = backgroundrect1.right

dragon1 = pygame.image.load(Current_path + '/dragon1.png')
dragon2 = pygame.image.load(Current_path + '/dragon2.png')
dragonrect = dragon1.get_rect()
dragonrect = dragonrect.move(50, 210)    #将小恐龙移动到“地上”

flag = True #创建一个flag标志用于在循环中判断使用哪张图片
while True:  # 死循环确保窗口一直显示
    clock.tick(6)
    for event in pygame.event.get():  # 遍历所有事件
        if event.type == pygame.QUIT:  # 如果程序发现单击关闭窗口按钮
            sys.exit()  #将窗口关闭

    screen.blit(background1, backgroundrect1)  # 将背景图片画到窗口上
    screen.blit(background2, backgroundrect2)

    #根据flag标志确定显示的图片,这样可以造成小恐龙在跑的现象
    if flag == True:
        screen.blit(dragon1, dragonrect)
    else:
        screen.blit(dragon2, dragonrect)
    flag = not flag

    backgroundrect1 = backgroundrect1.move(-10, 0)    #将背景向左移动
    backgroundrect2 = backgroundrect2.move(-10, 0)    #将背景向左移动
    if backgroundrect1.right < 0:   #判断第一个背景框如果移动到了窗口外面
        backgroundrect1[0] = backgroundrect2.right  #将第一个背景框移动到第二个背景框后面,形成循环
    if backgroundrect2.right < 0:   #和上面同理,最终实现的效果就是两个图片排着队从窗口前划过
        backgroundrect2[0] = backgroundrect1.right

    pygame.display.flip()  # 更新全部显示

Little Dinosaur Jumping (Big code change, be mentally prepared)

When I was doing the little dinosaur jumping, I encountered a problem, how to separate the jumping speed of the little dinosaur from the speed of the background movement. If we have played that game, it is not difficult to find that as the score increases, the background moves The speed will become faster and faster, but the jumping speed of the little dinosaur will not change. The speed at which the little dinosaur stepped before us is actually the same as the speed of the background movement, which is controlled by the global game speed. So I modified most of the code, but our logic has not changed, that is, we have added definition classes, so that we can better manage our code and make the code less bloated.
First up the effect picture:
insert image description here
the current little dinosaur can already detect that the button is pressed and jump.
Put the code below first, and I will explain it one by one.

import pygame
import sys

'''定义一个小恐龙的类'''
class Dragon:
    #小恐龙的默认参数
    def __init__(self):
        self.rectangle = pygame.Rect(50, 210, 40, 45)    #小恐龙的边框,预先设计好就不需要移动到地上
        #定义小恐龙的两种状态(读取图片放在列表里)
        self.status = [
            pygame.image.load('./picture/dragon1.png'),
            pygame.image.load('./picture/dragon2.png')
        ]
        self.Y_axis = 210    #小恐龙所在Y轴坐标
        self.jump_flag = False   #跳跃标志,判断小恐龙是否跳跃
        self.jump_speed = 0  #小恐龙的跳跃速度,当为正的时候上升,为负的时候下降
        self.alive = True    #生命状态,默认为活着
        self.jump_permission = True #小恐龙的跳跃权限,如果在空中时不给跳跃

    #更新小恐龙的状态
    def update(self):
        if self.jump_flag:   #如果检测到按下跳跃
            self.jump_speed = 15 #将上升速度调为10
            self.jump_permission = False     #跳跃期间不给小恐龙再次跳跃
            self.jump_flag = False   #设置好后回复默认值等待下次跳跃

        if self.jump_speed != 0:   #如果小恐龙的跳跃速度不为0,说明正在跳跃周期
            self.Y_axis -= self.jump_speed    #移动小恐龙的Y坐标
            if self.Y_axis > 210:    #防止将小恐龙移动到地下
                self.Y_axis = 210
                self.jump_permission = True  #回到地上,允许跳跃
            self.rectangle[1] = self.Y_axis   #将框真正移动
            
        if self.jump_permission == False:    #如果此时不允许跳跃,即正在跳跃过程中
            self.jump_speed -= 1 #将速度降低,效果为上升越来越慢,下降越来越快

'''定义一个地图的类'''
class Map:
    #默认参数
    def __init__(self):
        self.speed = 3
        self.background_1 = pygame.image.load('./picture/background1.png')  # 加载图片
        self.background_2 = pygame.image.load('./picture/background2.png')
        self.background_rectangle_1 = self.background_1.get_rect()    # 获取矩形区域
        self.background_rectangle_2 = self.background_2.get_rect()
        self.background_rectangle_2[0] = self.background_rectangle_1.right

    def update(self):
        self.background_rectangle_1 = self.background_rectangle_1.move(-self.speed, 0)    #将背景向左移动
        self.background_rectangle_2 = self.background_rectangle_2.move(-self.speed, 0)
        if self.background_rectangle_1.right < 0:   #判断第一个背景框如果移动到了窗口外面
            self.background_rectangle_1[0] = self.background_rectangle_2.right  #将第一个背景框移动到第二个背景框后面,形成循环
        if self.background_rectangle_2.right < 0:   #和上面同理,最终实现的效果就是两个图片排着队从窗口前划过
            self.background_rectangle_2[0] = self.background_rectangle_1.right

# 定义一个更新画面的函数(这样做可能更合理)
flag = True #创建一个flag标志用于在循环中判断使用哪张图片
count = 0
def screen_update(jump_permission):
    '''更新背景'''
    screen.blit(map.background_1, map.background_rectangle_1)  # 将背景图片画到窗口上
    screen.blit(map.background_2, map.background_rectangle_2)

    global count
    count += 1
    count %= 100

    if jump_permission:     #这个if语句是实现小恐龙踏步的
        if count % 15 == 0:     #为了控制小恐龙踏步的速度
            '''更新小恐龙'''
            global flag
            #根据flag标志确定显示的图片,这样可以造成小恐龙在跑的现象
            if flag == True:
                screen.blit(dragon.status[0], dragon.rectangle)
            else:
                screen.blit(dragon.status[1], dragon.rectangle)
            flag = not flag
        else:
            if flag == True:
                screen.blit(dragon.status[0], dragon.rectangle)
            else:
                screen.blit(dragon.status[1], dragon.rectangle)
    else:   #如果在空中那就显示两个图片,效果就是两个脚都平行(没有太大意义)
        screen.blit(dragon.status[0], dragon.rectangle)
        screen.blit(dragon.status[1], dragon.rectangle)  

if __name__ == "__main__":
    pygame.init()  # 初始化pygame
    screen = pygame.display.set_mode([734, 286])  # 创建并显示窗口
    clock = pygame.time.Clock() #创建一个时间对象用于控制游戏运作的快慢

    map = Map()     #创建地图实例
    dragon = Dragon()   #创建小恐龙实例
    score = 0   #设置初始分数

    while True:  # 死循环确保窗口一直显示
        clock.tick(60)      #越大越快
        for event in pygame.event.get():  # 遍历所有事件
            if event.type == pygame.QUIT:  # 如果程序发现单击关闭窗口按钮
                sys.exit()  # 将窗口关闭
            if event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN:
                if dragon.jump_permission:  #如果检测到按键按下并且当前允许跳跃
                    dragon.jump_flag = True

        map.update()    #更新地图元素框的位置
        dragon.update()     ##更新小恐龙元素框的位置
        screen_update(dragon.jump_permission)   #根据框显示图片

        #这部分暂时测试用 现在背景的移动速度和时间成正比
        score += 1
        if score % 100 == 0:
            map.speed += 0.5

        pygame.display.flip()  # 更新全部显示

First of all, this involves the definition of the class. If you don’t know much about it, you can go to other tutorials. It probably defines classes for the small dinosaur and the background. Each class has some default attributes, and the update (update function ) box position. If there is anything you don't understand, you can leave a message or private message, and I will add more details.

To be continued
Next, we have to fill in the pits:
1. Add obstacles
2. Add scores and make the scores positively correlated with the background movement speed

Guess you like

Origin blog.csdn.net/saoqixiaoyunge/article/details/122756399