pygame开发滑雪者游戏

pygame开发滑雪者游戏

一、实验说明

下述介绍为实验楼默认环境,如果您使用的是定制环境,请修改成您自己的环境介绍。

1. 环境登录

无需密码自动登录,系统用户名 shiyanlou,该用户具备 sudo 的权限,可以执行安装软件等管理员操作。

2. 环境介绍

本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面上的程序:

  1. LX终端(LXTerminal): Linux命令行终端,打开后会进入Bash环境,可以使用Linux命令
  2. Firefox:浏览器,可以用在需要前端界面的课程里,只需要打开环境里写的HTML/JS页面即可
  3. GVim:非常好用的编辑器,最简单的用法可以参考课程Vim编辑器

3. 环境使用

使用编辑器输入实验所需的代码及文件,使用命令行终端运行所需命令进行操作。

“实验记录”页面可以在“我的主页”中查看,每次实验的截图及笔记,以及有效学习时间(指的是在实验桌面内操作的时间,如果没有操作,系统会记录为发呆时间)。这些都是您在实验楼学习的真实性证明。

本课程中的所有源码可以在 Xfce 终端中执行下列命令获取:

wget http://labfile.oss.aliyuncs.com/courses/826/skierGames.py

二、课程介绍

1. 知识点:

本实验中将介绍在 Linux 桌面环境下使用 Python 及 pygame 快速开发小游戏的方式。

2. 参考文档:

http://www.pygame.org/docs/

3. 安装依赖包

$ sudo apt-get update
$ sudo apt-get install python-pygame

4. 依赖文件

因为我们的游戏包含一些图片和背景音乐,所以请下载背景音乐和图片:

wget http://labfile.oss.aliyuncs.com/courses/826/bg_music.tar.gz
wget http://labfile.oss.aliyuncs.com/courses/826/bg_img.tar.gz

然后对其进行解压

tar zcvf bg_music.tar.gz
tar bg_img.tar.gz

运行方式:将源代码文件和图像声音文件放到一起然后在终端中运行

python skierGames.py

5. 游戏介绍:

主人公就是滑雪者,在滑雪的时候可能会撞上树,当撞上树的时候会扣分,地图中也有小旗子当撞上小旗子的时候会加分 ---很传统的游戏。

6. 注意事项:

因为实验楼不提供音频播放功能,所以在源代码中将音频部分注释了,当您在本机运行的时候可以将代码中的注释去掉,从而播放音频。此处输入图片的描述
此处输入图片的描述

三、技术设计

重要的事情说三遍:

当您在学习Pygame模块的时候有不懂的要参考 Pygame的文档

http://www.pygame.org/docs/

×3

1. 角色设计

class SkierClass(pygame.sprite.Sprite):  # 创建滑雪者

    def __init__(self):
        pygame.sprite.Sprite.__init__(self) # 基类的init方法
        self.image = pygame.image.load("./bg_img/skier_down.png") # 这个是滑雪者的美照。
        self.rect = self.image.get_rect() # 用于获得Image的矩形大小
        self.rect.center = [320, 100]  # 指定矩形的中心位置
        self.angle = 0

    def turn(self, direction):				# 滑雪者 转向函数 其中的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. 创建树和小旗子

class ObstacleClass(pygame.sprite.Sprite):	#创建书和小旗
    def __init__(self, image_file, location, type):
        pygame.sprite.Sprite.__init__(self)
        self.image_file = image_file	#image_file可能是树或者小旗
        self.image = pygame.image.load(image_file)	#载入当前的图片
        self.location = location
        self.rect = self.image.get_rect()
        self.rect.center = location
        self.type = type
        self.passed = False

    def scroll(self, terrainPos):	#场景上滚,造成下滑假象。
        self.rect.centery = self.location[1] - terrainPos

该类创建出来 树或者小旗子并且造成场景运动的镜像。

3. 树和小旗的随机位置

def create_map(start, end): 	# 创建一个窗口,包含随机的树和小旗
    obstacles = pygame.sprite.Group() # 创建独立运动的组织
    locations = []
    gates = pygame.sprite.Group()
    for i in range(10):
        row = random.randint(start, end) #获得随机数在 start-end之间
        col = random.randint(0, 9)
        location  = [col * 64 + 20, row * 64 + 20] # 确定所在位置
        if not (location in locations): # 如果上面定义的物体不在已经确定属性(位置等参数)的物体里面。
            locations.append(location)
            type = random.choice(["tree", "flag"])#随机选择是树还是小旗
            if type == "tree": img = "./bg_img/skier_tree.png"	#选择相应的图片
            elif type == "flag":  img = "./bg_img/skier_flag.png"
            obstacle = ObstacleClass(img, location, type)		#将上面的形成的物体添加到游戏
            obstacles.add(obstacle)		
    return obstacles

用于创建窗口,并且随机生成树和小旗子在随机位置。并且将相应图片放到随机的位置。

4. 绘制屏幕背景并进行图像的更新

代码很简单,见下方:

def animate(): 	# 如果发生移动就重新绘制屏幕
    screen.fill([255, 255, 255])	#指定背景颜色 (RGB)
    pygame.display.update(obstacles.draw(screen))#这个函数就pygame.display.flip的优化版本。它只允许屏幕的一部分更新,而不是整个区域。如果没有参数传递它更新整个表面积就像pygame.display.flip()一样。
    screen.blit(skier.image, skier.rect)# 用于绘制位图 在屏幕的skier.rect位置绘制skier.image
    screen.blit(score_text, [10, 10])
    pygame.display.flip()

四、程序逻辑:

首先我们应该初始化Pygame模块和声音播放模块(因为实验楼不提供音频支持,所以将音频部分代码注释掉了,在本机运行的时候请去掉注释。)。
然后我们初始化游戏窗口,载入时间监听模块。随机生成树和小旗子
然后开始运行游戏进行无限循环,设置游戏的更新帧率,使用键盘监控左右按键,设置滑雪者的运动轨迹。随机生成树和小旗子然后检测 是否撞到树和小旗子然后进行相应的操作

pygame.init()        #初始化pygame的所有模块
#pygame.mixer.init()  # 初始化混音部分 进行声音的加载和播放---播放音频之用
#pygame.mixer.music.load("./bg_music/bg_music.mp3")  # 将会加载这一个音乐的文件名并且准备播放!
#pygame.mixer.music.set_volume(0.3)#设置音乐 的音量参数之在 0-1之间
#pygame.mixer.music.play(-1) #这将播放载入的音乐流。如果音乐已经播放,它就会重新启动。其中的参数时控制音乐播放的次数。如果是-1的话就是无限重复播放。
screen = pygame.display.set_mode([640,640])# 用于初始化窗口,其中的参数就是分辨率
clock = pygame.time.Clock()# 载入监听时间的模块 clock在下面还可以看到 clock.tick等方法
skier = SkierClass() # 初始化SkierClass对象
speed = [0, 6]
map_position = 0
points = 0
map0 = create_map(20, 29)
map1 = create_map(10, 19)
activeMap = 0

obstacles = updateObstacleGroup(map0, map1)

font = pygame.font.Font(None, 50)

while True:
    clock.tick(30)		# 每秒更新30次图形 ---这就是帧率。
    for event in pygame.event.get():    # 检查按键或者窗口是否关闭
        if event.type == pygame.QUIT: sys.exit()
        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 and activeMap == 0: 		# 从场景的一个窗口切换到下一个窗口
        activeMap = 1
        map0 = create_map(20, 29)
        obstacles = updateObstacleGroup(map0, map1)
    if map_position >=1280 and activeMap == 1:
        activeMap = 0
        for ob in map0:
            ob.location[1] = ob.location[1] - 1280
        map_position = map_position - 1280
        map1 = create_map(10, 19)
        obstacles = updateObstacleGroup(map0, map1)

    for obstacle in obstacles:
        obstacle.scroll(map_position)

    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("./bg_img/skier_crash.png")
            animate()
            pygame.time.delay(1000) # 游戏暂停 1秒。
            skier.image = pygame.image.load("./bg_img/skier_down.png")
            skier.angle = 0
            speed = [0, 6]
            hit[0].passed = True
        elif hit[0].type == "flag" and not hit[0].passed:
            points += 10
            obstacles.remove(hit[0])
	#显示得分
    score_text = font.render("Score: " +str(points), 1, (0, 0, 0))
    animate()

五、完整代码参考

import pygame, sys, random

skier_images = ["./bg_img/skier_down.png", "./bg_img/skier_right1.png", "./bg_img/skier_right2.png",
                 "./bg_img/skier_left2.png", "./bg_img/skier_left1.png"]     # 将可能用到的图片列表化

class SkierClass(pygame.sprite.Sprite):  # 创建滑雪者
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) # 基类的init方法
        self.image = pygame.image.load("./bg_img/skier_down.png") # 这个是滑雪者的美照。
        self.rect = self.image.get_rect() # 用于获得Image的矩形大小
        self.rect.center = [320, 100]  # 指定矩形的中心位置
        self.angle = 0

    def turn(self, direction):				# 滑雪者 转向函数 其中的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	#image_file可能是树或者小旗
        self.image = pygame.image.load(image_file)	#载入当前的图片
        self.location = location
        self.rect = self.image.get_rect()
        self.rect.center = location
        self.type = type
        self.passed = False

    def scroll(self, terrainPos):	#场景上滚,造成下滑假象。
        self.rect.centery = self.location[1] - terrainPos

def create_map(start, end): 	# 创建一个窗口,包含随机的树和小旗
    obstacles = pygame.sprite.Group() # 创建独立运动的组织
    locations = []
    gates = pygame.sprite.Group()
    for i in range(10):
        row = random.randint(start, end) #获得随机数在 start-end之间
        col = random.randint(0, 9)
        location  = [col * 64 + 20, row * 64 + 20] # 确定所在位置
        if not (location in locations): # 如果上面定义的物体不在已经确定属性(位置等参数)的物体里面。
            locations.append(location)
            type = random.choice(["tree", "flag"])#随机选择是树还是小旗
            if type == "tree": img = "./bg_img/skier_tree.png"	#选择相应的图片
            elif type == "flag":  img = "./bg_img/skier_flag.png"
            obstacle = ObstacleClass(img, location, type)		#将上面的形成的物体添加到游戏
            obstacles.add(obstacle)		
    return obstacles

def animate(): 	# 如果发生移动就重新绘制屏幕
    screen.fill([255, 255, 255])	#指定背景颜色 (RGB)
    pygame.display.update(obstacles.draw(screen))#这个函数就pygame.display.flip的优化版本。它只允许屏幕的一部分更新,而不是整个区域。如果没有参数传递它更新整个表面积就像pygame.display.flip()一样。
    screen.blit(skier.image, skier.rect)# 用于绘制位图 在屏幕的skier.rect位置绘制skier.image
    screen.blit(score_text, [10, 10])
    pygame.display.flip()

def updateObstacleGroup(map0, map1):  # 切换到场景的下一屏
    obstacles = pygame.sprite.Group()
    for ob in map0:  obstacles.add(ob)
    for ob in map1:  obstacles.add(ob)
    return obstacles

pygame.init()        #初始化pygame的所有模块
#pygame.mixer.init()  # 初始化混音部分 进行声音的加载和播放---播放音频之用
#pygame.mixer.music.load("./bg_music/bg_music.mp3")  # 将会加载这一个音乐的文件名并且准备播放!
#pygame.mixer.music.set_volume(0.3)#设置音乐 的音量参数之在 0-1之间
#pygame.mixer.music.play(-1) #这将播放载入的音乐流。如果音乐已经播放,它就会重新启动。其中的参数时控制音乐播放的次数。如果是-1的话就是无限重复播放。
screen = pygame.display.set_mode([640,640])# 用于初始化窗口,其中的参数就是分辨率
clock = pygame.time.Clock()# 载入监听时间的模块 clock在下面还可以看到 clock.tick等方法
skier = SkierClass() # 初始化SkierClass对象
speed = [0, 6]
map_position = 0
points = 0
map0 = create_map(20, 29)
map1 = create_map(10, 19)
activeMap = 0

obstacles = updateObstacleGroup(map0, map1)

font = pygame.font.Font(None, 50)

while True:
    clock.tick(30)		# 每秒更新30次图形 ---这就是帧率。
    for event in pygame.event.get():    # 检查按键或者窗口是否关闭
        if event.type == pygame.QUIT: sys.exit()
        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 and activeMap == 0: 		# 从场景的一个窗口切换到下一个窗口
        activeMap = 1
        map0 = create_map(20, 29)
        obstacles = updateObstacleGroup(map0, map1)
    if map_position >=1280 and activeMap == 1:
        activeMap = 0
        for ob in map0:
            ob.location[1] = ob.location[1] - 1280
        map_position = map_position - 1280
        map1 = create_map(10, 19)
        obstacles = updateObstacleGroup(map0, map1)

    for obstacle in obstacles:
        obstacle.scroll(map_position)

    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("./bg_img/skier_crash.png")
            animate()
            pygame.time.delay(1000)
            skier.image = pygame.image.load("./bg_img/skier_down.png")
            skier.angle = 0
            speed = [0, 6]
            hit[0].passed = True
        elif hit[0].type == "flag" and not hit[0].passed:
            points += 10
            obstacles.remove(hit[0])
	#显示得分
    score_text = font.render("Score: " +str(points), 1, (0, 0, 0))
    animate()

完整代码可以从这里获得:

wget http://labfile.oss.aliyuncs.com/courses/826/skierGames.py
原文地址:https://www.cnblogs.com/A-FM/p/6823288.html