20221320 2022-2023-2《Python程序设计——Python综合实践》实验四报告

20221320 2022-2023-2 《Python程序设计——Python综合实践》实验四报告

课程:《Python程序设计》
班级: 2213
姓名: 冯泰瑞
学号:20221320
实验教师:王志强
实验日期:2022年5月11日
必修/选修: 公选课

1.实验内容

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
本次结课大作业选择了编写游戏的方向,以学习制作弹球游戏为基础,用python程序实现经典游戏Flappy Bird

2. 实验过程及结果(本模块有3个游戏,弹球游戏版块学习了Pygame常用模块,Flappy Bird游戏版块实现了在弹球游戏中学习的Pygame常用模块的应用,并在书上实现的游戏功能基础上做了一定改进,滑雪大冒险游戏版块实现了对书上Flappy Bird游戏代码讲解的拓展应用,实验分析、设计、实现过程、结果等信息详见以下描述)

首先是学习Flappy Bird的游戏基础:弹球游戏
1.使用pygame中的display模块和event模块创建一个Pygame窗口。代码如下:
import sys
import pygame

pygame.init()
size = width,height = 320,240
screen = pygame.display.set_mode(size)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
运行结果如下:

在这里插入图片描述

2.创建一个游戏窗口,宽和高设置为640*480。代码如下:
import sys
import pygame

pygame.init()
size = width,height = 640,480
screen = pygame.display.set_mode(size)
运行结果如下:

在这里插入图片描述

3.运行上述代码,会发现一个闪现的黑色窗口,这是因为程序执行完成后,会自动关闭。如果让窗口一直显示着,需要使用while True 让程序一直执行,此外,还需要设置关闭按钮。代码如下:
import sys
import pygame

pygame.init()
size = width,height = 640,480
screen = pygame.display.set_mode(size)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
运行结果如下:

在这里插入图片描述

4.在窗口中加载小球。我们先准备好一张ball.png图片,然后加载该图片,最后将图片显示在窗口中,代码如下:
import sys
import pygame

pygame.init()
size = width,height = 640,480
screen = pygame.display.set_mode(size)
color = (0,0,0)

ball = pygame.image.load("ball.png")
ballrect = ball.get_rect()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    screen.fill(color)
    screen.blit(ball,ballrect)
    pygame.display.flip()

运行结果如下:

在这里插入图片描述

5.下面该让球动起来啦。ball.get_rect()方法返回值ballrect是一个Rect对象,该对象有一个move()方法可以用于移动矩形。move(x,y)函数有两个参数,第一个参数是X轴移动的距离,第二个参数是Y轴移动的距离。为实现小球不停地移动,将move()函数添加while循环内,代码如下:
import sys
import pygame

pygame.init()
size = width,height = 640,480
screen = pygame.display.set_mode(size)
color = (0,0,0)

ball = pygame.image.load("ball.png")
ballrect = ball.get_rect()

speed = [1,1]

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    ballrect = ballrect.move(speed)
    screen.fill(color)
    screen.blit(ball,ballrect)
    pygame.display.flip()

运行结果如下:

在这里插入图片描述

6.运行上述代码,发现小球在屏幕中一闪而过,此时,小球并没有真正消失,而是移动到窗口之外,此时需要添加碰撞检测功能。当小球与窗体任何一边发生碰撞,则更改小球的移动方向。代码如下:
import sys
import pygame

pygame.init()
size = width,height = 640,480
screen = pygame.display.set_mode(size)
color = (0,0,0)

ball = pygame.image.load("ball.png")
ballrect = ball.get_rect()

speed = [5,5]

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    ballrect = ballrect.move(speed)

    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    screen.fill(color)
    screen.blit(ball,ballrect)
    pygame.display.flip()

运行结果如下:

实验四运行视频1

6.运行上述代码发现好像有多个小球在飞快移动,这是因为运行上述代码的时间非常短,导致肉眼观察出现错觉,因此需要添加一个“时钟”来控制程序运行的时间。这时就需要使用Pygame的time模块。使用Pygame时钟之前,必须先创建Clock对象的一个实例,然后在while循坏中设置多长时间运行一次。代码如下:
import sys
import pygame

pygame.init()
size = width,height = 640,480
screen = pygame.display.set_mode(size)
color = (0,0,0)

ball = pygame.image.load("ball.png")
ballrect = ball.get_rect()

speed = [5,5]
clock = pygame.time.Clock()

while True:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    ballrect = ballrect.move(speed)

    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    screen.fill(color)
    screen.blit(ball,ballrect)
    pygame.display.flip()

运行结果如下:

实验四运行结果2

7.上传到Gitee:

在这里插入图片描述

学习制作弹球游戏之后,我们就学会了Pygame的基本应用,接下来就可以用这些知识来制作Flappy Bird游戏啦。
Flappy Bird游戏设计:

玩家通过点击鼠标来操控游戏。游戏中小鸟会不断向前飞,玩家点击鼠标后,小鸟会向上飞一段距离。否则,小鸟会因为重力的作用向下降。小鸟每成功飞过一段立柱,游戏得分加一。游戏过程中小鸟如果碰到了上下边缘或者移动的立柱就会死亡,游戏结束。

Flappy Bird游戏分析:

在Flappy Bird小游戏中,主要有两个对象:小鸟和管道,可以创建Bird类和Pipeline类来分别表示这两个对象。小鸟可以通过上下移动来躲避管道,所以在Bird类中创建一个birdUpdate()方法,实现小鸟的上下移动。为了体现小鸟向前飞行的特征,可以让管道一直向左移动,这样因为相对运动,在窗口中看起来就像是小鸟在向前运动一样。所以,在Pipeline类中也创建一个updatePipeline()方法,实现管道向左移动。此外,还创建了3个函数:createMap()函数用于绘制地图:cheekDead函数用于判断小鸟的生命状态:getResult()函数用于计算最终得分,最后在主逻辑中,实例化类并调用相关方法,实现相应功能。

Flappy Bird游戏实现过程:
1.我们先搭建起Flappy Bird游戏的主框架。Flappy Bird游戏有两个对象:小鸟和管道。先来创建这两个类,类中具体方法可以先使用pass语句代替。然后创建一个绘制地图的函数createMap()最后,在主逻辑中绘制背景图片。代码如下:
import pygame
import sys
import random

class Bird(object):
    def __init__(self):
        """定义一个鸟类"""
        pass

    def birdUpdate(self):
        pass
class Pipeline(object):
    def __init__(self):
        """定义一个管道类"""
    def updatePipeline(self):
        """水平移动"""
        pass
def createMap():
    """定义创建地图的方法"""
    screen.fill((255,255,255))
    screen.blit(background,(0,0))
    pygame.display.update()

if __name__ == '__main__':
    """"主程序"""
    pygame.init()
    size = width,height = 400,650
    screen = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    Pipeline = Pipeline()
    Bird = Bird()
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        background = pygame.image.load("assets background.png")
        createMap()
运行结果如下:

在这里插入图片描述

2.接下来创建小鸟类。该类需要初始化很多参数,所以定义一个__init__()方法,用来初始化各种参数,包括鸟飞行的几种状态、飞行的速度、跳跃的高度等等。然后定义birdUpdate()方法,该方法用于实现小鸟的跳跃和坠落。接下来,在主逻辑的轮询事件中添加键盘按下事件或鼠标单击事件,如按下鼠标,使小鸟上升等等。最后,在createMap()方法中,显示小鸟图像,代码如下:
import pygame
import sys
import random

class Bird(object):
    def __init__(self):
        """定义一个鸟类"""
        self.birdRect = pygame.Rect(65,50,50,50)
        self.birdStatus = [pygame.image.load("assets 1.png"),
                           pygame.image.load("assets 2.png"),
                           pygame.image.load("assets dead.png")]
        self.status = 0
        self.birdX = 120
        self.birdY = 350
        self.jump = False
        self.jumpSpeed = 10
        self.gravity = 5
        self.dead = False

    def birdUpdate(self):
        if self.jump:
            self.jumpSpeed -= 1
            self.birdy -= self.jumpSpeed
        else:
            self.gravity += 0.2
            self.birdY += self.gravity
        self.birdRect[1]= self.birdY

class Pipeline(object):
    def __init__(self):
        """定义一个管道类"""
    def updatePipeline(self):
        """水平移动"""
        pass
def createMap():
    """定义创建地图的方法"""
    screen.fill((255,255,255))
    screen.blit(background,(0,0))
    if Bird.dead:
        Bird.status = 2
    elif Bird.jump:
        Bird.status = 1
    screen.blit(Bird.birdStatus[Bird.status],(Bird.birdX,Bird.birdY))
    Bird.birdUpdate()
    pygame.display.update()

if __name__ == '__main__':
    """"主程序"""
    pygame.init()
    size = width,height = 400,650
    screen = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    Pipeline = Pipeline()
    Bird = Bird()
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
                Bird.jump = True
                Bird.gravity = 5
                Bird.jumpSpeed = 10

        background = pygame.image.load("assets background.png")
        createMap()
运行结果如下:

实验四运行结果3

3.接下来创建管道类。同样,在__init__()方法中初始化各种参数,包括设置管道的坐标,加载上下管道图片等。然后在updatePipeline()方法中,定义管道向左移动的速度,并且当管道移出屏幕时,重新绘制下一组管道。最后,在createMap()函数中显示管道,代码如下:
import pygame
import sys
import random

class Bird(object):
    def __init__(self):
        """定义一个鸟类"""
        self.birdRect = pygame.Rect(65,50,50,50)
        self.birdStatus = [pygame.image.load("assets 1.png"),
                           pygame.image.load("assets 2.png"),
                           pygame.image.load("assets dead.png")]
        self.status = 0
        self.birdX = 120
        self.birdY = 350
        self.jump = False
        self.jumpSpeed = 10
        self.gravity = 5
        self.dead = False

    def birdUpdate(self):
        if self.jump:
            self.jumpSpeed -= 1
            self.birdY -= self.jumpSpeed
        else:
            self.gravity += 0.2
            self.birdY += self.gravity
        self.birdRect[1]= self.birdY

class Pipeline(object):
    def __init__(self):
        """定义一个管道类"""
        self.wallx = 400;
        self.pineUp = pygame.image.load("assets top.png")
        self.pineDown = pygame.image.load("assets bottom.png")
    def updatePipeline(self):
        """管道移动方法"""
        self.wallx -= 5
        if self.wallx < -80:
            self.wallx = 400
def createMap():
    """定义创建地图的方法"""
    screen.fill((255,255,255))
    screen.blit(background,(0,0))
    screen.blit(Pipeline.pineUp,(Pipeline.wallx,-300))
    screen.blit(Pipeline.pineDown,(Pipeline.wallx,500))
    Pipeline.updatePipeline()
    if Bird.dead:
        Bird.status = 2
    elif Bird.jump:
        Bird.status = 1
    screen.blit(Bird.birdStatus[Bird.status],(Bird.birdX,Bird.birdY))
    Bird.birdUpdate()
    pygame.display.update()

if __name__ == '__main__':
    """"主程序"""
    pygame.init()
    size = width,height = 400,650
    screen = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    Pipeline = Pipeline()
    Bird = Bird()
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
                Bird.jump = True
                Bird.gravity = 5
                Bird.jumpSpeed = 10

        background = pygame.image.load("assets background.png")
        createMap()
运行结果如下:

实验四运行结果4

4.计算得分。当小鸟飞过管道时,玩家得分加一。这里对于飞过管道的逻辑做了简化处理:当管道移动到窗体左侧一定距离后,默认为小鸟飞过管道,使分数加一,并显示在屏幕上。在updatePipeline()方法中已经实现该功能。代码如下:
import pygame
import sys
import random

class Bird(object):
    def __init__(self):
        """定义一个鸟类"""
        self.birdRect = pygame.Rect(65,50,50,50)
        self.birdStatus = [pygame.image.load("assets 1.png"),
                           pygame.image.load("assets 2.png"),
                           pygame.image.load("assets dead.png")]
        self.status = 0
        self.birdX = 120
        self.birdY = 350
        self.jump = False
        self.jumpSpeed = 10
        self.gravity = 5
        self.dead = False

    def birdUpdate(self):
        if self.jump:
            self.jumpSpeed -= 1
            self.birdY -= self.jumpSpeed
        else:
            self.gravity += 0.2
            self.birdY += self.gravity
        self.birdRect[1]= self.birdY

class Pipeline(object):
    def __init__(self):
        """定义一个管道类"""
        self.wallx = 400;
        self.pineUp = pygame.image.load("assets top.png")
        self.pineDown = pygame.image.load("assets bottom.png")
    def updatePipeline(self):
        """管道移动方法"""
        self.wallx -= 5
        if self.wallx < -80:
            global score
            score += 1
            self.wallx = 400
def createMap():
    """定义创建地图的方法"""
    screen.fill((255,255,255))
    screen.blit(background,(0,0))
    screen.blit(Pipeline.pineUp,(Pipeline.wallx,-300))
    screen.blit(Pipeline.pineDown,(Pipeline.wallx,500))
    Pipeline.updatePipeline()
    if Bird.dead:
        Bird.status = 2
    elif Bird.jump:
        Bird.status = 1
    screen.blit(Bird.birdStatus[Bird.status],(Bird.birdX,Bird.birdY))
    Bird.birdUpdate()
    pygame.display.update()
    screen.blit(font.render('Score:'+str(score),-1,(255,255,255)),(100,50))
    pygame.display.update()

if __name__ == '__main__':
    """"主程序"""
    pygame.init()
    pygame.font.init()
    font = pygame.font.SysFont(None,50)
    size = width,height = 400,650
    screen = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    Pipeline = Pipeline()
    Bird = Bird()
    score = 0
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
                Bird.jump = True
                Bird.gravity = 5
                Bird.jumpSpeed = 10

        background = pygame.image.load("assets background.png")
        createMap()
运行结果如下:

实验四运行结果5

5.碰撞测试。当小鸟与管道相撞时小鸟颜色变为灰色,游戏结束,并且显示总分数。在checkDead()函数中通过pygame。Rect()可以分别获取小鸟的矩形区域对象,该对象有一个colliderect()方法可以判断两个矩形空间是否相撞。如果相撞,设置Bird.dead属性为True。此外,当小鸟飞出窗体时,也设置Bird.dead属性为True。最后,用两行文字显示游戏得分。代码如下:
import pygame
import sys
import random

class Bird(object):
    def __init__(self):
        """定义一个鸟类"""
        self.birdRect = pygame.Rect(65,50,50,50)
        self.birdStatus = [pygame.image.load("assets 1.png"),
                           pygame.image.load("assets 2.png"),
                           pygame.image.load("assets dead.png")]
        self.status = 0
        self.birdX = 120
        self.birdY = 350
        self.jump = False
        self.jumpSpeed = 10
        self.gravity = 5
        self.dead = False

    def birdUpdate(self):
        if self.jump:
            self.jumpSpeed -= 1
            self.birdY -= self.jumpSpeed
        else:
            self.gravity += 0.2
            self.birdY += self.gravity
        self.birdRect[1]= self.birdY

class Pipeline(object):
    def __init__(self):
        """定义一个管道类"""
        self.wallx = 400;
        self.pineUp = pygame.image.load("assets top.png")
        self.pineDown = pygame.image.load("assets bottom.png")
    def updatePipeline(self):
        """管道移动方法"""
        self.wallx -= 5
        if self.wallx < -80:
            global score
            score += 1
            self.wallx = 400
def createMap():
    """定义创建地图的方法"""
    screen.fill((255,255,255))
    screen.blit(background,(0,0))
    screen.blit(Pipeline.pineUp,(Pipeline.wallx,-300))
    screen.blit(Pipeline.pineDown,(Pipeline.wallx,500))
    Pipeline.updatePipeline()
    if Bird.dead:
        Bird.status = 2
    elif Bird.jump:
        Bird.status = 1
    screen.blit(Bird.birdStatus[Bird.status],(Bird.birdX,Bird.birdY))
    Bird.birdUpdate()
    pygame.display.update()
    screen.blit(font.render('Score:'+str(score),-1,(255,255,255)),(100,50))
    pygame.display.update()
def checkDead():
    upRect = pygame.Rect(Pipeline.wallx,-300,Pipeline.pineUp.get_width() - 10,Pipeline.pineUp.get_height())
    downRect = pygame.Rect(Pipeline.wallx,500,Pipeline.pineDown.get_width() - 10,Pipeline.pineDown.get_height())
    if upRect.colliderect(Bird.birdRect) or downRect.colliderect(Bird.birdRect):
        Bird.dead = True
    if not 0 < Bird.birdRect[1] < height:
        Bird.dead = True
        return True
    else:
        return False
def getResult():
    final_text1 = "Game Over"
    final_text2 = "Your final score is: "+str(score)
    ft1_font = pygame.font.SysFont("Arial",70)
    ft1_surf = font.render(final_text1,1,(242,3,36))
    ft2_font = pygame.font.SysFont("Arial",50)
    ft2_surf = font.render(final_text2,1,(253,177,6))
    screen.blit(ft1_surf,[screen.get_width()/2 - ft1_surf.get_width()/2,100])
    screen.blit(ft2_surf,[screen.get_width()/2 - ft2_surf.get_width()/2,200])
    pygame.display.flip()

if __name__ == '__main__':
    """"主程序"""
    pygame.init()
    pygame.font.init()
    font = pygame.font.SysFont(None,50)
    size = width,height = 400,650
    screen = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    Pipeline = Pipeline()
    Bird = Bird()
    score = 0
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
                Bird.jump = True
                Bird.gravity = 5
                Bird.jumpSpeed = 10

        background = pygame.image.load("assets background.png")
        if checkDead():
            getResult()
        else:
            createMap()
运行结果如下:

实验四运行结果6

6.游戏效果加强与完善。资料上说本游戏还有很多需要升级的空间,比如没有游戏难度的设置等。我在这里为游戏配入了背景音乐,使玩家在玩游戏时有更好的游戏体验。代码如下:
import pygame
import sys
import random

class Bird(object):
    def __init__(self):
        """定义一个鸟类"""
        self.birdRect = pygame.Rect(65,50,50,50)
        self.birdStatus = [pygame.image.load("assets 1.png"),
                           pygame.image.load("assets 2.png"),
                           pygame.image.load("assets dead.png")]
        self.status = 0
        self.birdX = 120
        self.birdY = 350
        self.jump = False
        self.jumpSpeed = 10
        self.gravity = 5
        self.dead = False

    def birdUpdate(self):
        if self.jump:
            self.jumpSpeed -= 1
            self.birdY -= self.jumpSpeed
        else:
            self.gravity += 0.2
            self.birdY += self.gravity
        self.birdRect[1]= self.birdY

class Pipeline(object):
    def __init__(self):
        """定义一个管道类"""
        self.wallx = 400;
        self.pineUp = pygame.image.load("assets top.png")
        self.pineDown = pygame.image.load("assets bottom.png")
    def updatePipeline(self):
        """管道移动方法"""
        self.wallx -= 5
        if self.wallx < -80:
            global score
            score += 1
            self.wallx = 400
def createMap():
    """定义创建地图的方法"""
    screen.fill((255,255,255))
    screen.blit(background,(0,0))
    screen.blit(Pipeline.pineUp,(Pipeline.wallx,-300))
    screen.blit(Pipeline.pineDown,(Pipeline.wallx,500))
    Pipeline.updatePipeline()
    if Bird.dead:
        Bird.status = 2
    elif Bird.jump:
        Bird.status = 1
    screen.blit(Bird.birdStatus[Bird.status],(Bird.birdX,Bird.birdY))
    Bird.birdUpdate()
    pygame.display.update()
    screen.blit(font.render('Score:'+str(score),-1,(255,255,255)),(100,50))
    pygame.display.update()
def checkDead():
    upRect = pygame.Rect(Pipeline.wallx,-300,Pipeline.pineUp.get_width() - 10,Pipeline.pineUp.get_height())
    downRect = pygame.Rect(Pipeline.wallx,500,Pipeline.pineDown.get_width() - 10,Pipeline.pineDown.get_height())
    if upRect.colliderect(Bird.birdRect) or downRect.colliderect(Bird.birdRect):
        Bird.dead = True
    if not 0 < Bird.birdRect[1] < height:
        Bird.dead = True
        return True
    else:
        return False
def getResult():
    final_text1 = "Game Over"
    final_text2 = "Your final score is: "+str(score)
    ft1_font = pygame.font.SysFont("Arial",70)
    ft1_surf = font.render(final_text1,1,(242,3,36))
    ft2_font = pygame.font.SysFont("Arial",50)
    ft2_surf = font.render(final_text2,1,(253,177,6))
    screen.blit(ft1_surf,[screen.get_width()/2 - ft1_surf.get_width()/2,100])
    screen.blit(ft2_surf,[screen.get_width()/2 - ft2_surf.get_width()/2,200])
    pygame.display.flip()

if __name__ == '__main__':
    """"主程序"""
    pygame.init()
    pygame.font.init()
    filepath = r"E:\Python\办公自动化\music.MP3"  # 打开mp3文件
    pygame.mixer.init()
    pygame.mixer.music.load(filepath)  # 加载MP3文件
    pygame.mixer.music.play()  # 播放mp3文件
    font = pygame.font.SysFont(None,50)
    size = width,height = 400,650
    screen = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    Pipeline = Pipeline()
    Bird = Bird()
    score = 0
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
                Bird.jump = True
                Bird.gravity = 5
                Bird.jumpSpeed = 10

        background = pygame.image.load("assets background.png")
        if checkDead():
            getResult()
        else:
            createMap()
运行结果如下:(播放此视频时请调大电脑或手机音量听取视频中的声音)

实验四运行结果7

7.上传到Gitee:

在这里插入图片描述

做完Flappy Bird游戏版块,我们可以根据Flappy Bird的游戏原理进行游戏的拓展,完成滑雪大冒险游戏。
滑雪大冒险游戏设计:

玩家通过键盘来操控游戏。游戏中滑雪人会不断向下滑行,玩家按键盘向左箭头键或向右箭头键可以实现滑雪人改变滑行方向,向左或向右滑行。滑雪人在途中如果碰到红旗,则游戏得分加100分,如果碰到大树,则游戏得分减100分,如果碰到饮料瓶,则滑行速度增加。

滑雪大冒险游戏分析:

在滑雪大冒险游戏中,主要有两个两个游戏对象:滑雪人和障碍物,可以创建SkierClass类和ObstacleClass类来分别表示这两个对象。滑雪人可以左右移动来躲避障碍物,所以在SkierClass类中创建一个turn()方法,实现滑雪人的左右移动。为了体现滑雪人一直向下飞行的特征,可以让障碍物一直向上运动,这样因为相对运动,在窗口中看起来就像是一个滑雪人在向下飞行一样。所以,在ObstacleClass类中创建一个update()方法,实现障碍物的向上运动。此外,还创建了两个函数:create_map()用于障碍物位置确定,animate()函数用于滑雪者,障碍物和游戏得分在屏幕上的显示。最后在主逻辑中,实例化类并调用相关方法,实现相应功能。

滑雪大冒险游戏实现过程:
1.首先创建滑雪人类。该类需要初始化很多参数,所以定义一个__init__()方法,用来初始化各种参数,包括滑雪人的几种滑行状态、滑行的角度等等。然后定义turn()方法,用来实现滑雪人的角度转向和转向后速度的减速变化。最后定义move()函数,实现滑雪人速度控制。代码如下:
class SkierClass(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("skier_down.png")
        self.rect = self.image.get_rect()
        self.rect.center = [320, 100]
        self.angle = 0

    def turn(self, direction):
        self.angle = self.angle + direction
        if self.angle < -2:  self.angle = -2
        if self.angle > 2:  self.angle = 2
        center = self.rect.center
        self.image = pygame.image.load(skier_images[self.angle])
        self.rect = self.image.get_rect()
        self.rect.center = center
        speed = [self.angle, 6 - abs(self.angle) * 2]
        return speed

    def move(self, speed):
        self.rect.centerx = self.rect.centerx + speed[0]
        if self.rect.centerx < 20:  self.rect.centerx = 20
        if self.rect.centerx > 620: self.rect.centerx = 620
2.接下来创建障碍物类。同样,在__init__()方法中初始化各类参数,包括障碍物的位置坐标和加载障碍物图片等等。然后在update()方法中,定义障碍物的移动速度。代码如下:
class ObstacleClass(pygame.sprite.Sprite):
    def __init__(self, image_file, location, type):
        pygame.sprite.Sprite.__init__(self)
        self.image_file = image_file
        self.image = pygame.image.load(image_file)
        self.rect = self.image.get_rect()
        self.rect.center = location
        self.type = type
        self.passed = False

    def update(self):
        global speed
        self.rect.centery -= speed[1]
        if self.rect.centery < -32:
            self.kill()
3.接下来在create_map()函数中确定障碍物的位置。代码如下:
def create_map():
    global obstacles
    locations = []
    for i in range(10):
        row = random.randint(0, 9)
        col = random.randint(0, 9)
        location = [col * 64 + 32, row * 64 + 32 + 640]
        if not (location in locations):
            locations.append(location)
            type = random.choice(["tree", "flag","drink"])
            if type == "tree":
                img = "skier_tree.png"
            elif type == "flag":
                img = "skier_flag.png"
            elif type == "drink":
                img = "energy drink1.png"
            obstacle = ObstacleClass(img, location, type)
            obstacles.add(obstacle)
5.接下来,在animate()函数中实现滑雪者,障碍物和游戏得分在屏幕上的显示。代码如下:
def animate():
    screen.fill([255, 255, 255])
    obstacles.draw(screen)
    screen.blit(skier.image, skier.rect)
    screen.blit(score_text, [10, 10])
    pygame.display.flip()
5.接下来,在主逻辑中初始化一些参数,实现上述类的实例化,调用相关方法,添加背景音乐,实现整个游戏功能。代码如下:
pygame.init()
pygame.font.init()
screen = pygame.display.set_mode([640, 640])
clock = pygame.time.Clock()
y = 6
speed = [0, y]
obstacles = pygame.sprite.Group()
skier = SkierClass()
map_position = 0
points = 0
create_map()
font = pygame.font.Font(None, 50)
filepath = r"E:\Python\办公自动化\music.MP3"  # 打开mp3文件
pygame.mixer.init()
pygame.mixer.music.load(filepath)  # 加载MP3文件
pygame.mixer.music.play()  # 播放mp3文件

running = True
while running:
    clock.tick(30)
    for event in pygame.event.get():
        if event.type == pygame.QUIT: running = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed = skier.turn(-1)
            elif event.key == pygame.K_RIGHT:
                speed = skier.turn(1)
    skier.move(speed)
    map_position += speed[1]

    if map_position >= 640:
        create_map()
        map_position = 0

    hit = pygame.sprite.spritecollide(skier, obstacles, False)
    if hit:
        if hit[0].type == "tree" and not hit[0].passed:
            points = points - 100
            skier.image = pygame.image.load("skier_crash.png")
            animate()
            pygame.time.delay(1000)
            skier.image = pygame.image.load("skier_down.png")
            skier.angle = 0
            speed = [0, y]
            hit[0].passed = True
        elif hit[0].type == "flag" and not hit[0].passed:
            points = points + 100
            hit[0].kill()
        elif hit[0].type == "drink" and not hit[0].passed:
            y = y + 1
            speed = [0,y]

    obstacles.update()
    score_text = font.render("Score: " + str(points), 1, (0, 0, 0))
    animate()

pygame.quit()

6.最后合并各步骤的代码,实现滑雪大冒险小游戏(对不起是盗版+简陋版,正版+精装版还是在应用商城里搜索“滑雪大冒险”下载安装再玩吧)。代码如下:
import pygame, sys, random

skier_images = ["skier_down.png", "skier_right1.png", "skier_right2.png",
                "skier_left2.png", "skier_left1.png"]


class SkierClass(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("skier_down.png")
        self.rect = self.image.get_rect()
        self.rect.center = [320, 100]
        self.angle = 0

    def turn(self, direction):
        self.angle = self.angle + direction
        if self.angle < -2:  self.angle = -2
        if self.angle > 2:  self.angle = 2
        center = self.rect.center
        self.image = pygame.image.load(skier_images[self.angle])
        self.rect = self.image.get_rect()
        self.rect.center = center
        speed = [self.angle, 6 - abs(self.angle) * 2]
        return speed

    def move(self, speed):
        self.rect.centerx = self.rect.centerx + speed[0]
        if self.rect.centerx < 20:  self.rect.centerx = 20
        if self.rect.centerx > 620: self.rect.centerx = 620


class ObstacleClass(pygame.sprite.Sprite):
    def __init__(self, image_file, location, type):
        pygame.sprite.Sprite.__init__(self)
        self.image_file = image_file
        self.image = pygame.image.load(image_file)
        self.rect = self.image.get_rect()
        self.rect.center = location
        self.type = type
        self.passed = False

    def update(self):
        global speed
        self.rect.centery -= speed[1]
        if self.rect.centery < -32:
            self.kill()


def create_map():
    global obstacles
    locations = []
    for i in range(10):
        row = random.randint(0, 9)
        col = random.randint(0, 9)
        location = [col * 64 + 32, row * 64 + 32 + 640]
        if not (location in locations):
            locations.append(location)
            type = random.choice(["tree", "flag","drink"])
            if type == "tree":
                img = "skier_tree.png"
            elif type == "flag":
                img = "skier_flag.png"
            elif type == "drink":
                img = "energy drink1.png"
            obstacle = ObstacleClass(img, location, type)
            obstacles.add(obstacle)


def animate():
    screen.fill([255, 255, 255])
    obstacles.draw(screen)
    screen.blit(skier.image, skier.rect)
    screen.blit(score_text, [10, 10])
    pygame.display.flip()


pygame.init()
pygame.font.init()
screen = pygame.display.set_mode([640, 640])
clock = pygame.time.Clock()
y = 6
speed = [0, y]
obstacles = pygame.sprite.Group()
skier = SkierClass()
map_position = 0
points = 0
create_map()
font = pygame.font.Font(None, 50)
filepath = r"E:\Python\办公自动化\music.MP3"  # 打开mp3文件
pygame.mixer.init()
pygame.mixer.music.load(filepath)  # 加载MP3文件
pygame.mixer.music.play()  # 播放mp3文件

running = True
while running:
    clock.tick(30)
    for event in pygame.event.get():
        if event.type == pygame.QUIT: running = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed = skier.turn(-1)
            elif event.key == pygame.K_RIGHT:
                speed = skier.turn(1)
    skier.move(speed)
    map_position += speed[1]

    if map_position >= 640:
        create_map()
        map_position = 0

    hit = pygame.sprite.spritecollide(skier, obstacles, False)
    if hit:
        if hit[0].type == "tree" and not hit[0].passed:
            points = points - 100
            skier.image = pygame.image.load("skier_crash.png")
            animate()
            pygame.time.delay(1000)
            skier.image = pygame.image.load("skier_down.png")
            skier.angle = 0
            speed = [0, y]
            hit[0].passed = True
        elif hit[0].type == "flag" and not hit[0].passed:
            points = points + 100
            hit[0].kill()
        elif hit[0].type == "drink" and not hit[0].passed:
            y = y + 1
            speed = [0,y]

    obstacles.update()
    score_text = font.render("Score: " + str(points), 1, (0, 0, 0))
    animate()

pygame.quit()

运行结果如下:(播放此视频时请调大电脑或手机音量听取视频中的声音)

实验四运行视频8

7.上传到Gitee:

在这里插入图片描述

3. 实验过程中遇到的问题和解决过程

  • 问题1:如何成功下载第三方库pygame(虽然这个看起来不是问题的问题,在我的电脑上实现真的搞了我好久,因为老师讲的两种安装方式都没有实现成(灬ꈍ ꈍ灬),这个安装过程真的很泪崩)

  • 问题1解决方案:首先我在终端中使用命令行“pip install pygame”无法下载,显示错误“fatal error in launcher: Unable to create process using ‘“D:\python.exe” “D:\Scripts\pip.exe” install pygame’:”查询资料fatal error in launcher:unable to create process using 解决办法得知使用命令行“ python -m pip install pygame -i https://pypi.tuna.tsinghua.edu.cn/simple”即可完成安装,但是在我的终端内输入此命令行没有任何响应。便尝试在Pycharm——>file——>setting——>python interpreter中搜索pygame尝试安装,但在pycharm中报错称“无法下载”的问题来源不在pycharm中。因为看到终端中的文件名目录不对,自己的python安装路径在D盘中但是终端打开的文件夹是C:/User.便尝试使用文件目录操作命令cd/python去实现文件目录的切换,可是不行。最后通过卸载了D盘中的python安装程序,在C盘的“用户”文件夹中重新安装,最终在pycharm中下载成功了第三方库pygame
    在这里插入图片描述

  • 问题2:如何实现在用pygame实现的游戏中为游戏添加背景音乐

  • 问题2解决方案:查询资料PyGame|给程序插入背景音乐得知应在主函数中加入以下代码

filepath=r"E:\Python\办公自动化\music.MP3"#打开mp3文件
pygame.mixer.init()
pygame.mixer.music.load(filepath)#加载MP3文件
pygame.mixer.music.play()#播放mp3文件

即可实现在游戏过程中播放背景音乐

4.实验感想

其实做完整个实验发现我们平时玩的一些游戏其中的代码没有我们想象的那么复杂,就比如我在想为这个Flappy bird游戏配什么背景音的时候,突然想到的自己之前玩过的游戏“滑雪大冒险”的配音。其实Flappy BIrd和滑雪大冒险这两个游戏的原理在我学习了使用pygame实现游戏后发现是相同的,都是通过对游戏中各个“”实例化为“对象”后完成在程序界面中的“坐标位置”的判断来推动游戏的进程,只不过滑雪大冒险(应用商城中的正版)它会用到一张更大的背景图片作为底板,中途的障碍物可能不仅仅是立柱这么简单,而且要使用随机数来完成对不同种类障碍物的随机生成工作。于是,我在学习完Flappy Bird的游戏制作后,做了滑雪大冒险的盗版+简陋版小游戏。之所以本篇实验报告看起来非常长,是因为我把三个小游戏都合并在一起写了,且后一个是在学习完前一个的基础上完成的

全课总结

课程内容小结:
1.python是一个面向对象,跨平台,解释性的编程语言。
2.主要的开发环境有IDLE,Pycharm,VScode。
3.与C语言相区别的基本语法有:通过语句的缩进来实现C语言中语句块的功能,语句的末尾没有分号来表示语句的结束,变量的命名不可以用数字开头等等。
4.条件语句:if,if-else,if-elif-else。
5.循环语句:while,for…in…。
6.四种序列:列表(可改,可切片:[ : : : ]),元组(不可改,可切片),字典(键值对{k:v}),集合(元素不可重复)。
7.字符串,正则表达式
8.面向对象语言三要素:封装、继承、多态
9.冯诺依曼结构:计算机由输入设备,输出设备,存储器,运算器,控制器组成。
10.文件操作:open,read,write,close
11.异常处理:try…except…finally语句
12.数据库:SQLite(嵌入式DB),MySQL(非嵌入式)
13.网络编程:Socket通信编程(Client<——>Server)
14.爬虫:发送信息,拿到数据。
15.反反爬虫:模拟浏览器(headers)

课程感想体会、意见和建议

感想体会:通过本门课程的学习,解答了我学习C语言课程时的疑问:学习编程怎么解决实际生活中的问题?因为C语言课程中反复做的题目都是一些数学题目,如何通过C语言来实现求解,但是python给了很多生活中的应用,比如编写一些小游戏,网络爬虫,办公自动化的实现等等。这些生活中的应用不是说用C语言实现不了,是由于我们C语言学习的还不够深入,实现这些应用的代码太过于庞杂,基于我们的水平暂时无法用其实现。但是python的第三方库就很好的解决了这个问题,让我们能够站在前人的肩膀上来实现C语言中需要较多代码才能实现的应用。王老师上课时节奏把握得非常到位。课前会用10分钟时间带大家复习上节课的学习内容,这种“前情回顾式的教学方式让同学们可以在很快的时间内回忆起上节课的知识,这大大提高了同学们本节课的听课效率,使两节课的内容间有很好的衔接。在上课时举的例子贴近年轻人的日常生活,使我们的知识接受度较高。在课堂快结束前几分钟会让我们自己巩固本节课学习到的知识,使得授课内容能够得到良好的消化。所谓“师傅领进门,修行靠个人。”,本门Python课程给我的Python学习起到了很好的启蒙作用,让我有了扎实的Python语言基础,使我在今后的大创项目中和课程学习中无疑是加入了一支强大的“同盟军”。
建议意见:王老师可以在平时多多布置一点课下作业,帮助同学们巩固当堂课的内容,正所谓“Practice makes perfect.”,当理论与实践相结合,往往能取得更好的吸收效果。然后英语打卡这个加分项目可以保持下去,本人亲测对学习Python的帮助作用真的很大。还有就是王老师可以让同学们充分利用课余时间通过观看学习通上的视频来学习课堂上没有精讲的内容。

希望之后还能上王老师的课~

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值