zoukankan      html  css  js  c++  java
  • 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
    
  • 相关阅读:
    PHP原生实现,校验微信公众号||小程序服务器地址
    TP3.2校验微信公众号||小程序 服务器地址
    【微信小程序】解决 竖向<scroll-view>组件 “竖向滚动页面出现遮挡”问题
    【微信小程序】:confirm(删除提示)
    【微信小程序】:评论、回复和删除功能 -- 2017/7/14
    微信小程序:bindtap方法传参
    TP3.2之WHERE组合条件处理
    Python:导入numpy报错 No module named numpy
    Python: 二进制、八进制、十六进制转换或者输出
    Python:数字的格式化输出
  • 原文地址:https://www.cnblogs.com/A-FM/p/6823288.html
Copyright © 2011-2022 走看看