基于pygame的小游戏开发

**

“大龟吃小鱼”小游戏开发

**

摘要

“大龟吃小鱼”游戏是基于python语言的pygame模块,尝试模拟实现网络小游戏“大鱼吃小鱼”的运行效果而进行的实践性单机小游戏项目。旨在对本段时间里的python学习效果进行考查与检验。本项目完全由本人对python基础知识以及pygame模块基础知识学习后独立完成开发。该小游戏项目模拟实现了添加背景音乐、对事件添加音效,游戏暂停、开始,随机生成游动小鱼,乌龟位置随光标移动,乌龟面向移动的方向,鲨鱼吃乌龟和其他鱼类,乌龟吃较小鱼、被较大鱼吃等功能。

1 引言

1.1 背景

当今游戏越来越氪金,游戏开发依旧是一个热门行业。但是开发的游戏能否赚到钱,还要看所开发游戏的质量。现在游戏越来越倾向于3D游戏和手游,腾讯算是国内3D手游界的元老了,知名度很高。虽然如此,但也抵挡不了经典游戏的流传。就拿俄罗斯方块来说,那是快跨世纪的经典了。当然经典是属于少数的,我们的知识也要跟上时代步伐。但是无论什么知识的学习,都得从基础开始,而python又是一门简单好用,功能强大的面向对象语言,非常适合其他编程语言薄弱或者零基础学员。所以,想要学得更深层次知识,首先也得从基础爬起。一些2D平面网络小游戏或者类似街霸游戏机的游戏都可以成为我们尝试模拟开发实现的好项目,先照着学着做,再学着去创造自己的游戏。

1.2 意义

模拟实现网络小游戏“大鱼吃小鱼”,单纯为了检验自己这段时间对python基础知识和pygame模块知识的掌握运用,从简单出发,从模拟开始,既不会给自己太多难点,让自己失去耐心信心,还可以提高学习的兴趣,有兴趣了,才会有动力坚持。
python真是一门热门语言,近年来听到与他有关的大数据、深度学习、人工智能的消息不少。自己有学习python的游戏和爬虫两部分内容的决定,但一切从基础出发,项目案例是不可少的!

1.3 相关研究

大鱼吃小鱼”是一款经典,被经常模仿的小游戏,至今还是很多人的回忆。为了编写程序,我还重新回去玩了几把。现在已经被模仿出很多款大鱼吃小鱼的游戏,但操作大致一样,只是画面更加美观,游戏的精灵对象更加丰富。它们的基本玩法都是通过移动鼠标带动小鱼移动,改变方向,躲避比自己个头大的鱼,追捕比自己小的鱼。期间会产生许多游来游去的鱼,这些鱼还有一定躲避和改变方向的能力。时不时还会响起警报,冲出一条鲨鱼。鲨鱼速度快,直接横穿游戏界面,带走旁边经过的小鱼。

1.4 实现的功能

根据“大鱼吃小鱼”游戏的基本玩法,应该模拟实现的基本功能如下:
(1) 添加背景音乐
(2) 鼠标控制主角乌龟的移动
(3) 乌龟向左移动,头应该朝向左;向右移动时,头应该朝向右
(4) 随机产生小鱼、中鱼、大鱼和鲨鱼从游戏屏幕两侧游来
(5) 乌龟可以吃比自己小的鱼,可以被比自己大的鱼吃
(6) 乌龟吃鱼时,播放特定音效
(7) 乌龟吃鱼到一定数量会自动变大,设置两次变大过程
(8) 乌龟变大时播放特定音效
(9) 鲨鱼可以吃乌龟和所有鱼类
(10)鲨鱼出现前播放预警音效和显示警告标志,鲨鱼出现时播放特定音效
(11)添加游戏暂停和进行按钮
(12)实时统计乌龟吃鱼的得分,打印在窗体上。
(13)乌龟被吃,游戏停止,并在游戏屏幕中央打印出“Game Over!!!”
**

2. 系统结构

**

2.1 介绍

模拟实现的“大龟吃小鱼”只不过是个小型窗体游戏,所有游戏呈现的效果都是基于pygame的display模块的set_mode()方法创建的窗体实现的,然后通过循环一直去运行编写的程序,产生对应事件,除非达到指定的停止循环条件,程序才停止运行。而呈现的效果只不过是python高效的响应能力,每秒以人眼察觉不到的帧率刷新屏幕,让一张张图片(一点点像素)在窗体上飞速绘制。

2.2 系统中对象设计

名称图标大小相关属性
小乌龟$16050*40 像素size =1/3/5 、score = 0
小鱼$12 在这里插入图片描述在这里插入图片描述40*25像素size = 0、spend = 3、live = True
中鱼$1 在这里插入图片描述60*40像素size = 2、speed = 2、live=True
大鱼在这里插入图片描述在这里插入图片描述80*50像素size = 4、speed = 3、live = True
鲨鱼在这里插入图片描述在这里插入图片描述150*100像素size = 6、 speed = 5、live = True

相关描述:
(1)size表示对象大小关系,乌龟初始化为1,后边变大再修改为3,5。然后宽高分别变为原来1.4,1.8倍。其他对象size固定不变这样设计,为了满足大吃小的设定。
(2)score是小乌龟吃鱼所获得分数。吃小、中、大鱼分别加10、20、30分。
(3)speed是给鱼的游动速度
(4)live用于判断鱼是否被吃,被吃则置False,触发重置鱼位置的事件。

2.3 使用的模块方法

(1)display模块
set_mode(宽,高):创建窗体
set_cption(“…”):创建窗体标题

(2)mixer内的music模块——Pygame 中控制音频流的模块。load("….ogg"):载入音乐文件,创建了音乐对象
play():播放
set_colume():设置音量
pause():暂停音乐播放
unpause():恢复音乐播放
stop():结束播放呀

(3)mixer模块
pygame.mixer.Sound("….wav"): 使用前需先生成Sound()对象
play():播放
set_volume():设置音量

(4)image模块
load(“….jpg/png”): 从文件加载新图片

(5)mouse模块
set_visible():隐藏或显示鼠标光标
get_pos():获取鼠标光标的位置

(6)sprite 模块
spritecollide():方法用于检测某个精灵是否与指定的组中的其它精灵发生碰撞。
pygame.sprite.Sprite:动画精灵的基类:

(7)event模块
get():获取产生的事件

(8)transform模块
flip():水平、垂直翻转图像
smoothscale():平滑缩放图像

(9)font
Font():设置文本字体和大小
render() 方法: 将显示的文字活生生的渲染成一个 Surface 对象

(10)surface.blit():将surface对象渲染到屏幕上

(11)time模块
delay():进行延迟。
time模块有一个 Clock类。实例化的Clock 对象有一个方法叫做 tick(),参数就是设置的帧率。

**

3 实现代码

**

3.1 打地基

游戏的实现需要一个地基,而进一步工作还需要一些材料。这里的地基就是窗体,材料就是开发过程中用到的素材(音乐、图像)。
先创建一个窗体,并导入音乐素材,顺便把主角小乌龟加入到窗体中。
创建一个musice文件夹存放音乐素材如下:
在这里插入图片描述
创建一个images文件夹存放图片素材如下:
在这里插入图片描述

```python
(1)创建乌龟模块,定义乌龟类
import pygameclass Turtle(pygame.sprite.Sprite):def __init__(self,bg_size):pygame.sprite.Sprite.__init__(self)#生成乌龟图像self.image = pygame.image.load("images/turtle.png").convert_alpha()#获取位置self.rect = self.image.get_rect() self.width, self.height = bg_size[0],bg_size[1]   #用于限制获得范围#用于定位self.rect.left, self.rect.top = \(self.width - self.rect.width)//2, \(self.height - self.rect.height) //2
(2)创建主模块(main.py)
import pygame
import sys
import traceback    #为了更好退出
from pygame.locals import *import turtle       #导入自己编写的乌龟模块pygame.init()
pygame.mixer.init()     #混音器初始化(可以省略)bg_size = width, height = 800,600            #规定窗体大小
screen = pygame.display.set_mode(bg_size)    #创建窗体
pygame.display.set_caption("模拟游戏开发——大龟吃小鱼")    #设置窗体标题
background = pygame.image.load('images/bg_image.jpg').convert_alpha()   #加载背景图片
clock = pygame.time.Clock()#载入游戏音乐
pygame.mixer.music.load("music/bg_music.ogg")
pygame.mixer.music.set_volume(0.2)
die_sound = pygame.mixer.Sound("music/die.wav")
die_sound.set_volume(0.2)
eat_sound = pygame.mixer.Sound("music/eat.wav")
eat_sound.set_volume(0.3)
warn1_sound = pygame.mixer.Sound("music/warn1.wav")
warn1_sound.set_volume(0.2)
seaWater_sound = pygame.mixer.Sound("music/seaWater.wav")
seaWater_sound.set_volume(0.2)
bigger_sound = pygame.mixer.Sound("music/bigger.wav")
bigger_sound.set_volume(0.2)def main():pygame.mixer.music.play(-1)       #无限循环播放bg_musictur = turtle.Turtle(bg_size)      #生成乌龟对象running = True                    #游戏循环运行条件while running:for event in pygame.event.get():if event.type == QUIT:pygame.quit()   #解决关闭窗口不退出问题sys.exit()#绘制背景图片 screen.blit(background,(0,0))#绘制乌龟screen.blit(tur.image,(tur.rect.left,tur.rect.top))pygame.display.flip()   #刷新页面clock.tick(60)          #设置帧率为每秒60帧if __name__ == "__main__":try:main()except SystemExit:passexcept:traceback.print_exc()pygame.quit()input()

3.2 鼠标控制主角乌龟的移动

这里需要先隐藏鼠标,然后将乌龟方形区域的中心点(rect.center)设置为鼠标位置。光标隐藏和位置获取利用mouse模块是方法set_visible()和get_pos()实现
实现了鼠标移动乌龟后就需要控制乌龟的头朝向。乌龟向左移动,头应该朝向左;向右移动时,头应该朝向右。实现方法是在乌龟类中创建多一张乌龟头朝右的图片,利用transform模块的flip(self.Left,True,False)方法让原图片水平翻转。然后在主函数中,利用前后两鼠标位置差的正负判断乌龟的头朝向。

```python
(1)修改乌龟模块……省略的代码……#生成乌龟左右朝向的图像self.Limage = pygame.image.load("images/turtle.png").convert_alpha()self.Rimage = pygame.transform.flip(self.Limage,True,False)#获取位置(左右朝向图片的位置应该一致)self.rect = self.Limage.get_rect()   ……省略的代码 ……      pygame.mouse.set_visible(False)     #设置光标不可见
(2)主模块修改……省略代码……#绘制背景图片 screen.blit(background,(0,0))#判断乌龟移动方向,显示乌龟大小new_pos = pygame.mouse.get_pos()if new_pos[0] - now_pos[0] > 0:screen.blit(tur.Rimage,tur.rect)else:screen.blit(tur.Limage,tur.rect)#将光标画在pygame,默认光标的位置tur.rect.center = pygame.mouse.get_pos()       pygame.display.flip()   #刷新页面……省略的代码……

3.3 随机产生小鱼、中鱼、大鱼和鲨鱼从游戏屏幕两侧游来

创建鱼模块fish.py,定义不同鱼的类。这里给每种鱼2-3中类别,所以一个类中载入了2-3张图片。这些鱼实现了在窗体左右侧外某位置随机生成,然后一直游向窗体,当小鱼游过窗体时,在重置鱼的位置于窗体外左右侧外某位置随机生成,再重新游回屏幕,循环该过程,实现不间断的游鱼从屏幕两侧随机生成。
主模块先定义4个生成鱼的函数,让生成的每条鱼存于两个组中,方便后期使用。在应用函数生成对象后,再将组中每个对象绘制再屏幕上。
实现代码比较简单。

```pathon
(1)定义fish.py模块
import pygame
from random import *
#小鱼
class SmallFish(pygame.sprite.Sprite):def __init__(self,bg_size):pygame.sprite.Sprite.__init__(self)#加载小鱼图片self.img1 = pygame.image.load("images/sFish1.png").convert_alpha()self.img2 = pygame.image.load("images/sFish2.png").convert_alpha()self.img3 = pygame.image.load("images/sFish2.png").convert_alpha()self.rect = self.img1.get_rect()     #获取位置self.width, self.height = bg_size[0], bg_size[1]  #用于限制获得范围self.speed = 3      #定义小鱼游动速度#在页面外部左方5个屏幕宽度范围内随机生成一只小鱼self.rect.center = \(randint(-5*self.width, 0),\randint(0, self.height-self.rect.height))#当鱼从左边游到窗体右边外,重置小鱼位置,否则就让小鱼继续向前游def siwm(self):if self.rect.left > self.width:self.rect.center = \(randint(-5 * self.width, 0),\randint(0, self.height-self.rect.height))else:self.rect.right += self.speed
#中鱼类
class MidFish(pygame.sprite.Sprite):def __init__(self,bg_size):pygame.sprite.Sprite.__init__(self)#加载两种不同类型中鱼self.img1 = pygame.image.load("images/mFish1.png").convert_alpha()self.img2 = pygame.image.load("images/mFish2.png").convert_alpha()self.rect = self.img1.get_rect()self.width, self.height = bg_size[0], bg_size[1]self.speed = 2#在页面外部左方1-10个屏幕宽度范围内随机生成一只大鱼self.rect.center = \(randint(self.width,10 * self.width),\randint(0, self.height-self.rect.height))#当鱼从右边游到窗体左边外,重置小鱼位置,否则就让小鱼继续向前游def siwm(self):if self.rect.right < 0:self.rect.center = \(randint(self.width,10 * self.width),\randint(0, self.height-self.rect.height))else:self.rect.right -= self.speed
#大鱼
class BigFish(pygame.sprite.Sprite):def __init__(self,bg_size):pygame.sprite.Sprite.__init__(self)#加载两种不同类型大鱼self.img1 = pygame.image.load("images/bFish1.png").convert_alpha()self.img2 = pygame.image.load("images/bFish2.png").convert_alpha()self.rect = self.img1.get_rect()self.width, self.height = bg_size[0], bg_size[1]self.speed = 3#在页面外左方15个屏幕宽度范围内随机生成一只大鱼self.rect.center = \(randint(-10*self.width, 0),\randint(0, self.height-self.rect.height))def siwm(self):if self.rect.left > self.width:self.rect.center = \(randint(-15 * self.width, 0),\randint(0, self.height-self.rect.height))else:self.rect.right += self.speed
#鲨鱼
class Shark(pygame.sprite.Sprite):def __init__(self,bg_size):pygame.sprite.Sprite.__init__(self)#加载鲨鱼self.img1 = pygame.image.load("images/shark1.png").convert_alpha()self.img2 = pygame.image.load("images/shark2.png").convert_alpha()self.rect = self.img1.get_rect()self.width, self.height = bg_size[0], bg_size[1]self.speed = 5#在页面外部右部5-20个屏幕宽度范围内随机生成一只鲨鱼self.rect.center = \(randint(5 * self.width,20 *self.width),\randint(0, self.height-self.rect.height))def siwm(self):if self.rect.right < 0:self.rect.center = \(randint(5 * self.width,20 *self.width),\randint(0, self.height-self.rect.height))else:self.rect.right -= self.speed
(2)主模块修改
……省略的代码……
import fish         #导入自己编写的鱼模块
……省略的代码……
#添加鱼的函数,并将鱼类对象放到到两个组
def add_SmallFish(group1,group2,num):for i in range(num):fish_ = fish.SmallFish(bg_size)group1.add(fish_)group2.add(fish_)def add_MidFish(group1,group2,num):for i in range(num):fish_ = fish.MidFish(bg_size)group1.add(fish_)group2.add(fish_)def add_BigFish(group1,group2,num):for i in range(num):fish_ = fish.BigFish(bg_size)group1.add(fish_)group2.add(fish_)def add_Shark(group1,group2,num):for i in range(num):fish_ = fish.Shark(bg_size)group1.add(fish_)group2.add(fish_)def main():……省略的代码……#生成鱼fishes = pygame.sprite.Group()  #存放小、中、大和鲨鱼#3种小鱼各12条small_fish1 = pygame.sprite.Group()add_SmallFish(small_fish1,fishes,12)small_fish2 = pygame.sprite.Group()add_SmallFish(small_fish2,fishes,12)small_fish3 = pygame.sprite.Group()add_SmallFish(small_fish3,fishes,12)#2种中鱼各8条mid_fish1 = pygame.sprite.Group()add_MidFish(mid_fish1,fishes,8)mid_fish2 = pygame.sprite.Group()add_MidFish(mid_fish2,fishes,8)#2种大鱼各4条big_fish1 = pygame.sprite.Group()add_BigFish(big_fish1,fishes,4)big_fish2 = pygame.sprite.Group()add_BigFish(big_fish2,fishes,4)#2种鲨鱼各1条shark_fish1 = pygame.sprite.Group()add_Shark(shark_fish1,fishes,2)shark_fish2 = pygame.sprite.Group()
add_Shark(shark_fish2,fishes,2)
while running:…… 省略的代码……               #绘制背景图片 screen.blit(background,(0,0))#绘制鱼#小鱼for each in small_fish1:each.siwm()screen.blit(each.img1, each.rect)for each in small_fish2:each.siwm()screen.blit(each.img2, each.rect)for each in small_fish3:each.siwm()screen.blit(each.img3, each.rect)#中鱼for each in mid_fish1:each.siwm()screen.blit(each.img1, each.rect)for each in mid_fish2:each.siwm()screen.blit(each.img2, each.rect)#大鱼for each in big_fish1:each.siwm()screen.blit(each.img1, each.rect)for each in big_fish2:each.siwm()screen.blit(each.img2, each.rect)#鲨鱼for each in shark_fish1:each.siwm()screen.blit(each.img1, each.rect)    for each in shark_fish2:each.siwm()screen.blit(each.img2, each.rect)
……省略的代码……

3.4 乌龟可以吃比自己小的鱼,可以被比自己大的鱼吃

实现这个功能,首先为乌龟和鱼类都创建一个属性size,设置小鱼为0,中鱼为2,大鱼为4,鲨鱼为6。而乌龟初始值为1,但是后会应要求而变大。这样如果乌龟与鱼发生碰撞检测,如果谁的size大,谁就被吃。而鲨鱼进行碰撞检测时,无需判断size,直接将碰撞对象吃掉,因为这里它是食物链顶端。碰撞检测利用paygame的sprite模块的spritecollide(),让一对象去与一组对象Group检测。
实现该功能应该注意的是,被吃不是真的消失,而是重置了位置。所以这里还得为大小中鱼类定义一个重置方法reset()。而判断是否重置则需要为大小中鱼类的类添加一个live属性,判断对象是否还活着,活着则继续游动,死了则引用reset()方法重置对象。

```pathon
(1)修改的乌龟模块如下在乌龟类添加属性:self.size = 1
(2)修改的鱼模块如下
a. #小鱼
class SmallFish(pygame.sprite.Sprite):
def __init__(self,bg_size):
……省略的代码……
size = 0			#用于比较个头大小self.live = True    #用于判断是否还活着#重置小鱼的位置def reset(self):self.rect.center = \(randint(-5 * self.width, 0),\randint(0, self.height-self.rect.height))b. #中鱼类
class MidFish(pygame.sprite.Sprite):def __init__(self,bg_size):……省略的代码……size = 2			#用于比较个头大小self.live = True    #用于判断是否还活着#重置鱼的位置def reset(self):self.rect.center = \(randint(self.width,10 * self.width),\randint(0, self.height-self.rect.height))
c. #大鱼
class BigFish(pygame.sprite.Sprite):def __init__(self,bg_size):……省略的代码……self.size = 4self.live = True    #用于判断是否还活着#重置鱼的位置def reset(self):self.rect.center = \(randint(-15 * self.width, 0),\randint(0, self.height-self.rect.height))
d.#鲨鱼在鲨鱼类中添加属性self.seize = 6
(3)修改的主组模块如下……省略的代码……shark_fish2 = pygame.sprite.Group()add_Shark(shark_fish2,fishes,2)shark_fish = []         #存放鲨鱼对象for i in shark_fish1:shark_fish.append(i)for i in shark_fish2:shark_fish.append(i)running = True                    #游戏循环运行条件while running:……省略的代码……    #绘制鱼#小鱼for each in small_fish1:if each.live:   #检测是否还活着each.siwm()screen.blit(each.img1, each.rect)else:each.reset()each.live = Truefor each in small_fish2:if each.live:   #检测是否还活着each.siwm()screen.blit(each.img2, each.rect)else:each.reset()each.live = Truefor each in small_fish3:if each.live:   #检测是否还活着each.siwm()screen.blit(each.img3, each.rect)else:each.reset()each.live = True#中鱼for each in mid_fish1:if each.live:   #检测是否还活着each.siwm()screen.blit(each.img1, each.rect)else:each.reset()each.live = Truefor each in mid_fish2:if each.live:   #检测是否还活着each.siwm()screen.blit(each.img2, each.rect)else:each.reset()each.live = True#大鱼for each in big_fish1:if each.live:   #检测是否还活着each.siwm()screen.blit(each.img1, each.rect)else:each.reset()each.live = Truefor each in big_fish2:if each.live:   #检测是否还活着each.siwm()screen.blit(each.img2, each.rect)else:each.reset()each.live = True#鲨鱼for each in shark_fish1:each.siwm()screen.blit(each.img1, each.rect)for each in shark_fish2:each.siwm()screen.blit(each.img2, each.rect)#鲨鱼的检测for each in shark_fish:array = pygame.sprite.spritecollide(each,fishes,False)if array:for i in array:i.live = False#乌龟的检测array = pygame.sprite.spritecollide(tur, fishes, False)if array:for i in array:if tur.size > i.size:i.live=False……省略的代码……

3.5 完善小乌龟吃鱼事件

首先乌龟吃鱼时,应该播放特定音效,直接使用play()方法播放不填参数,默认播放依次。假如乌龟被吃,将乌龟画在窗体外,背景音乐停止,播放乌龟死亡音效,停止循环,游戏结束。
给乌龟类一个score属性,记录得分,吃下鱼得10分,中鱼得20分,大鱼得30分。
还应该让乌龟分数到达500时,另其变大到原来尺寸的1.4倍,分数达到1000时,变大为原来的1.8倍(这里经过计算,增大原来1.4倍刚好宽比中鱼大10个像素,增大原来1.8倍刚好宽比大鱼大10个像素)。图像变大利用pygame的transform模块smoothscale()方法实现。此时还需要在乌龟模块定义左右向的1.4倍、1.8倍图片。
此时居然乌龟比中鱼大,那么size设置为3,则乌龟可以吃中鱼了,而比大鱼大时,size设置为5,则可以吃大鱼了。乌龟变大时要播放变大音效,因为sroce可能跳过500和1000,直接往上增,所以我还定义了两个属性用于检测是否播放变大音效。

```pathon
(1)乌龟类修改
import pygameclass Turtle(pygame.sprite.Sprite):def __init__(self,bg_size):……省略的代码……self.rect = self.Limage.get_rect()#1.4倍原比例大小左右向乌龟self.Limage1_4 = pygame.transform.smoothscale(self.Limage,\(int(self.rect.width * 1.4),\int(self.rect.height * 1.4)))self.Rimage1_4 = pygame.transform.flip(self.Limage1_4,True,False)#1.8倍原比例大小左右向乌龟self.Limage1_8 = pygame.transform.smoothscale(self.Limage,\(int(self.rect.width * 1.8),\int(self.rect.height * 1.8)))self.Rimage1_8 = pygame.transform.flip(self.Limage1_8,True,False)#当score等于500,变身size=3(可吃size为0,2鱼),尺寸为70*70#当score 等于1000,变身size=5(可吃size为0,2,4的鱼),尺寸90*90self.score = 0self.change1_music= 0   #是否播放第一次变声音乐self.change2_music= 0   #是否播放第二次变声音乐(2)主模块修改
……省略的代码……#乌龟的检测array = pygame.sprite.spritecollide(tur, fishes, False)if array:for i in array:if tur.size > i.size:eat_sound.play()i.live=Falseif i.size == 0:tur.score += 10elif i.size == 2:tur.score += 20elif i.size == 4:tur.score += 30else:running = Falseeat_sound.play()screen.blit(tur.Rimage,(width+10,0))  #将乌龟画在窗体外隐藏pygame.time.delay(1000)pygame.mixer.music.stop()die_sound.play()else:           #判断乌龟移动方向,显示乌龟大小new_pos = pygame.mouse.get_pos()if tur.score < 500:if new_pos[0] - now_pos[0] > 0:screen.blit(tur.Rimage,tur.rect)else:screen.blit(tur.Limage,tur.rect)elif 500<=tur.score <1000:if new_pos[0] - now_pos[0] > 0:screen.blit(tur.Rimage1_4,tur.rect)else:screen.blit(tur.Limage1_4,tur.rect)tur.size = 3tur.change1_music += 1 elif 1000<=tur.score:if new_pos[0] - now_pos[0] > 0:screen.blit(tur.Rimage1_8,tur.rect)else:screen.blit(tur.Limage1_8,tur.rect)tur.size = 5tur.change2_music += 1……省略的代码……

3.6 将分数打印在窗体左上角

将字体打印在屏幕上需要先将字体转化为surface对象,可以使用pygame的font模块的render()方法实现,然后直接blit(文字,位置)到屏幕上即可。

```pathon
(1)主模块代码如下:
……省略的代码……
# 得分字体
score_font = pygame.font.Font(None, 36) #字体while running:……省略的代码……# 绘制得分score_text = score_font.render("Score : %s" % str(tur.score), True, (255,255,255))
screen.blit(score_text, (10, 5))……省略的代码

3.7 完善鲨鱼出现和吃鱼事件

鲨鱼出现前播放预警音效和显示警告标志,鲨鱼出现时播放特定音效。音效直接将到导入的对象play()即可,警示标志就是一张图片。

```python
(1)主模块函数修改
……省略的代码……
#鲨鱼到来警告标志
warn_tip = pygame.image.load("images/warn.png").convert_alpha()
while running:
……省略的代码……
#鲨鱼for each in shark_fish1:each.siwm()screen.blit(each.img1, each.rect)#鲨鱼快要出现时,发出警报(鲨鱼速度是4,所以要取个范围才能测试)if 3*width<= each.rect.left <=3*width+6:warn1_sound.play()#鲨鱼在这个位置范围时,显示警告标志elif 3*width<= each.rect.left <=3*width+300:screen.blit(warn_tip,(width-70 , each.rect[1]))elif 2 * width <= each.rect.left <= 2 * width + 6:seaWater_sound.play()for each in shark_fish2:each.siwm()screen.blit(each.img2, each.rect)#鲨鱼快要出现时,发出警报(鲨鱼速度是4,所以要取个范围才能测试)if 3*width<= each.rect.left <=3*width+6:warn1_sound.play()#鲨鱼在这个位置范围时,显示警告标志elif 3*width<= each.rect.left <=3*width+300:screen.blit(warn_tip,(width-70 , each.rect[1]))elif 2 * width <= each.rect.left <= 2 * width + 6:seaWater_sound.play()

3.8 添加游戏暂停和进行按钮

游戏暂停和开始是通过变量pause将两张图片在同一位置上切换,触发条件是鼠标单击位置是否是图像位置。
这里需要注意两点,游戏暂停,要背景音乐停下,游戏继续,让背景音乐播放。另外,游戏暂停后,应该重新显示光标,不然看不到光标显示。

```pyhthon
(1)主模块修改
……省略的代码……
# 标志是否暂停游戏
paused = False
pause_nor_image = pygame.image.load("images/unpause.png").convert_alpha()
pause_pressed_image = pygame.image.load("images/pause.png").convert_alpha()
paused_rect = pause_nor_image.get_rect()
paused_rect.left, paused_rect.top = width - paused_rect.width - 15, 10paused_image = pause_nor_imagewhile running:……省略的代码……if not paused:#绘制背景图片 screen.blit(background,(0,0))
……省略的代码……#暂停时设置光标可见if paused:pygame.mouse.set_visible(True)     #设置光标可见else:pygame.mouse.set_visible(False)     #设置光标不可见# 绘制得分score_text = score_font.render("Score : %s" % str(tur.score), True, (255,255,255))screen.blit(score_text, (10, 5))# 绘制暂停按钮screen.blit(paused_image, paused_rect)……省略的代码……

3.9 游戏结束时,在游戏屏幕中央打印出“Game Over!!!”

游戏结束即乌龟死亡,被吃时,所以在乌龟检测后,假如被吃,就将实现准别的图像答应到屏幕中央即可。

```python……省略的代码……
#存放打印的文字msgs = []
while running:
……省略的代码……
#乌龟的检测
array = pygame.sprite.spritecollide(tur, fishes, False)
else:
running = Falseeat_sound.play()screen.blit(tur.Rimage,(width+10,0))    #将乌龟画在窗体外隐藏pygame.time.delay(1000)pygame.mixer.music.stop()die_sound.play()#打印一张图片msg = pygame.image.load('images/lose.png').convert_alpha()msg_pos = (width - msg.get_width()) // 2, \(height - msg.get_height()) // 2msgs.append((msg,msg_pos))
……省略的代码……
#将光标画在pygame,默认光标的位置
tur.rect.center = pygame.mouse.get_pos()pygame.display.flip()   #刷新页面
……省略的代码……

3.10 完善碰撞检测

图像的背景只是透明而不是不见了,所以有时候肉眼可以观测到乌龟还没碰撞到,就检测出已经发生碰撞的消息。
Sprite模块里有一个叫做collide_mask 的函数,这个函数要求检测对象拥有一个 mask 属性,这个属性就是用于指定检测的范围,而 Pygame 的mask模块的from_surface()的函数,可以将 Surface 对象中非透明的部分标记为 mask 并返回。

```python
(1)修改每一个类,添加mask属性。添加语句如下:
self.mask = pygame.mask.from_surface(self.img1) #将非透明部分标记为maskself.mask = pygame.mask.from_surface(self.img2) #将非透明部分标记为mask
(2)修改主模块两处碰撞检测在碰撞检测方法中添加参数:pygame.sprite.collide_mask

**

4. 实验结果

**

4.1 初始化界面

在这里插入图片描述

4.2 暂停效果

在这里插入图片描述

4.3 运行效果

在这里插入图片描述

4.4 随之鼠标移动,小乌龟移动,并实时改变方向

在这里插入图片描述在这里插入图片描述

4.5 个头变化

当小乌龟分数到达500时,其个头变为原来1.4倍。
当小乌龟分数到达1000时,其个头变为原来1.8倍。
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

4.6 乌龟和鲨鱼吃较小鱼

这里只是实现一旦触碰就播放吃鱼音效,让较小的鱼消失,然后重置被吃鱼的位置于窗体以外。只是一瞬间,无法捕捉照片。

4.7 背景音乐、各种音效

游戏全程有背景音乐,吃较小鱼,乌龟尺寸变大、乌龟被吃,鲨鱼到来等都有音效。

4.8 鲨鱼靠近时显示警告标志

在这里插入图片描述

4.9 被鲨鱼吃掉,游戏结束

游戏只给乌龟一条命,被吃即游戏结束
在这里插入图片描述
**

5. 总结和展望

**

5.1 总结

程序虽然实现模拟的“大鱼吃小鱼”的基本功能,但是还是存在缺陷和未能实现的地方。

5.1.1 缺陷:

(1)碰撞检测时、可能肉眼看到还没触碰就检测到了碰撞。
原因:可能因为给每种小、中、大和鲨鱼分别增加了2到3中不同类型,所以pygame的from_surface模块的mask方法无法实现对所有对象,忽略图片对象透明部分。
图片已经做尽量裁剪缩小图像透明背景,此情况会有所改善。
(2)鼠标停止时,无论本来小乌龟的头面向哪个方向,都会改为方向向左
应有的效果应该是鼠标停止,小乌龟的头方向与刚刚移动方向一致。
产生原因:我是利用光标前后横坐标的差的正负代表小乌龟头面向做和面向右的,在判断时,光标停止即表示差等于0,此时多除一个判断条件,不知道如何处理,所以就默认归分到向左。
(3)程序只实现了乌龟吃鱼、鲨鱼吃鱼效果。

5.1.2 不足:

(1)没有实现动画效果(张口吃鱼)
(2)鱼的游动方向比较单一,不会判断较大鱼靠近而躲避

5.2展望

Python是这学期收获较多的课程之一,本学期真的是学到了东西,虽然还只是些皮毛,但相比以前的碌碌而过的其他学期,真的是莫大的进步改变。没想到疫情,让在家学习的我更加积极,这期间完全独立而且真正自己完成了几个项目。虽然项目有大有小,收获的有些也只是知识中皮毛,不懂的还是很多,但找到了方向,还有一颗真正学习的心,这段时间的学习会成为我大学来最刻苦铭心的一段记忆中。马上又假期,学习资料已经备好,爬虫和pygame,虽然遥远,但也要一点点努力靠近大数据和人工智能时代。我会更加努力……

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/18455.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鲨鱼后台源码6.0版本安装教程

这期教大家源码如何安装网站&#xff0c;记得收藏 下载源码&#xff1a;https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3 首先需要一台服务器&#xff08;这个自己去准备&#xff09; 解析域名&#xff08;不会自行百度&#xff09; 去宝塔官网安装面板 环境:p…

交易猫鲨鱼源码后台

教程&#xff1a;修改数据库账号密码直接使用。 下载程序&#xff1a;https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3

交易猫鲨鱼后台搭建

教程&#xff1a;修改数据库账号密码直接使用\n\n程序&#xff1a;https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3

CSS小鲨鱼

280行纯CSS&#xff0c;喜欢拿走 无论是css还是别的&#xff0c;前端的学习总是妙趣横生&#xff0c;只要思想在不断进步&#xff0c;技术就会一次次的突破。如果你学习过CSS&#xff0c;你会更加了解这段代码的神奇&#xff0c;送给你&#xff0c;远道而来的求学者。 <!D…

交易猫鲨鱼系统源码搭建

教程&#xff1a;修改数据库账号密码直接使用。 源码带有教程! 下载程序&#xff1a;https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3

初次模拟小鲨鱼记账本1.0

我打算逐步将小鲨鱼记账本优化,这次没有用到数据库,等出到2.0版本再用 本次的核心是查找数据用了stream流(我的另一篇简单介绍了什么是Stream流) 用到的比较简单,用于对Java基础的巩固加深,下一次的2.0版正好再对数据库的知识进行复习 如果有机会出3.0就把学的前段一些知识再…

【PPT】《使用ChatGPT一键制作带自动配图的PPT演讲稿》- 知识点目录

《使用ChatGPT一键制作带自动配图的PPT演讲稿》 1. 使用ChatGPT生成prompt 生成一个用于Tome制作《汽车诞生史》PPT的prompt为了制作《汽车诞生史》PPT&#xff0c;您可以考虑以下提示&#xff1a; 开场&#xff1a;引用一句关于汽车的名言或警句&#xff0c;如“汽车是现代生…

一看媲美chatgpt的ai工具站notion ai

介绍&#xff1a; Notion AI是一种人工智能技术&#xff0c;旨在通过自然语言处理、机器学习和深度学习等技术&#xff0c;帮助用户更高效地处理信息和完成任务。Notion AI可以帮助用户自动化一些常见的任务&#xff0c;例如自动分类文档、提取关键信息、生成摘要、自动回答问…

向ChatGPT开炮!谷歌打响全面反击战!官宣新模型比肩GPT-4!

点击下方卡片&#xff0c;关注“CVer”公众号 AI/CV重磅干货&#xff0c;第一时间送达 点击进入—>【Transformer】微信技术交流群 明敏 丰色 发自 凹非寺转载自&#xff1a;量子位&#xff08;QbitAI&#xff09; 万众瞩目&#xff0c;谷歌的反击来了。 现在&#xff0c;谷…

PaLM 2全面反超反超GPT-4,谷歌官宣AI重构搜索,朝着ChatGPT微软开炮

来源 | 量子位 | 公众号 QbitAI 万众瞩目&#xff0c;谷歌的反击来了。 现在&#xff0c;谷歌搜索终于要加入AI对话功能了&#xff0c;排队通道已经开放。 当然这还只是第一步。 大的还在后面&#xff1a; 全新大语言模型PaLM 2正式亮相&#xff0c;谷歌声称它在部分任务超…

chatgpt赋能python:Python数据清洗方法:从数据脏到数据干净

Python数据清洗方法&#xff1a;从数据脏到数据干净 数据清洗是数据科学家和分析师最重要的工作之一&#xff0c;因为在真正开始建立模型和产生洞察之前&#xff0c;必须先处理数据集。Python是一种非常流行的语言&#xff0c;特别擅长于数据处理和数据分析方面。在本文中&…

chatgpt赋能python:Python数据清洗:为何数据清洗很重要?

Python数据清洗&#xff1a;为何数据清洗很重要&#xff1f; 数据清洗是数据分析中最重要的部分之一&#xff0c;它涉及到从一堆无组织、无用或错误数据中提取有益信息的过程。随着数据量的不断增加&#xff0c;数据清洗变得越来越重要&#xff0c;因为令人困惑的数据会导致错…

chatgpt赋能python:Python数据的清洗

Python数据的清洗 Python是一种高级编程语言&#xff0c;被广泛用于数据分析和数据挖掘的领域。在这些任务中&#xff0c;数据清洗是非常重要的一部分。因为数据的质量直接影响到结果的准确性和可靠性。本文将介绍一些使用Python进行数据清洗的方法。 数据清洗的概念和意义 …

chatgpt赋能python:Python分隔:利用Python进行数据清洗的必备技能

Python分隔&#xff1a;利用Python进行数据清洗的必备技能 在数据处理过程中&#xff0c;数据分隔是一个非常常见的步骤&#xff0c;特别是在将数据导入数据库或将文本数据转换为表格数据时。Python是一种强大的数据处理工具&#xff0c;具有许多内置的分隔函数和库。在本文中…

chatgpt赋能python:数据清洗在Python中的实现及其意义

数据清洗在Python中的实现及其意义 数据清洗是数据科学和机器学习中非常关键的一步&#xff0c;因为数据通常是杂乱无章的&#xff0c;包括错误&#xff0c;缺失&#xff0c;重复&#xff0c;不一致等。这样的数据可能会对模型的预测产生负面影响&#xff0c;因此需要进行数据…

[创业之路-60] :从道德经63章和冰山模型,看创业中的守护,通透外部的人与事

道德经63章原文&#xff1a; 为无为&#xff0c;事无事&#xff0c;味无味。大小多少&#xff0c;报怨以德&#xff0c;图难于其易&#xff0c;为大于其细。天下难事&#xff0c;必作于易&#xff1b;天下大事&#xff0c;必作于细。是以圣人终不为大&#xff0c;故能成其大。夫…

《2023 HuggingGPT: Solving AI Tasks with ChatGPT and its Friends in Hugging Face》阅读笔记

http:// https://github.com/microsoft/JARVIS. 1 Abstract and Introduction 借助大语言模型&#xff08;LLMS&#xff09;在语言理解生成推理等方面表现出的出色能力&#xff0c;考虑将其作为控制器来管理现有的各种AI模型&#xff0c;把语言作为通用接口。基于这一理念&a…

ChatGPT的4个不为人知却非常实用的小功能

重点介绍四个ChatGPT很实用的小功能。 一、停止生成 如果在ChatGPT输出内容的过程中&#xff0c;我们发现结果不是自己想要的&#xff0c;可以直接点击“Stop generating”按钮&#xff0c;这样它就会立即停止输出。 二、复制功能 在ChatGPT返回对话的右侧&#xff0c;有三个图…

程序员的小幽默:让你笑到肚子痛的搞笑动图

今天小编用动图的方式带大家了解程序员这个逗逼、可爱的群体。看动图时大家注意形象啊&#xff01; 1、程序员的生存状态 。 2、双核CPU的真相。 3、当年学C语言的过程。 4、测试环境一切ok&#xff0c;马上上线 5、调试bug 6、正在调试&#xff0c;突然内存溢出了 7、卧槽&am…

图文搞笑段子这么黑程序员真的好吗?

“男朋友写代码不理我,于是我悄悄改掉了web.xml的一个配置,他搞了两天都没调通,我告诉了他,] 结果他要和我分手,我很伤心,但他的朋友告诉我,他没砍死你才说明他真的爱你…” “楼主别tm编了,程序员哪来的女朋友!” “谁告诉你我是女的了。” 谁能给解答一下什么叫做面向对象编程…