刚学习pygame不久,看完网上一个叫“我要吃金豆”的小游戏,突然心血来潮,正好因为疫情在家,努力努力,想用pygame独自编写一个小游戏——逃出生天。自己学习python也没几年,鉴于水平有限,是个小菜鸟,编出的代码可能过于累赘或没有意义,不喜勿喷哈。我会努力以创作博客的形式去记录编写过程,尽量展现出自己的思路和出现的问题,如果有好想法可以评论哟
一、今天“逃出生天”小游戏的制作目标
有游戏标题与进入界面,包括教程与多关卡式游戏(尽量去实现……),有最终界面,包含一个小游戏该有的所有主要部分,尽量使代码不那么累赘。今天把游戏的教程第一部分搞好。(tips:这里所包含的素材都是作者手画的(努力))
二、编写记录 1、游戏所需的素材照片
对于上一个博客已经贴出来的图片,这里就不再详细展示了哟~
游戏教程部分,用来介绍游戏角色的图片1(teach_tell1.png)大小:494×91
游戏教程部分,用来介绍游戏角色的图片2(teach_tell2.png)大小:516×62
游戏教程部分,用来进入下一个介绍的图片(next_teach.png)大小:94×52
游戏教程部分,强调按钮的两个箭头(arror_fornext1.png 和 arror_fornext.png) 大小:28×23
2、上期代码回顾
首先让我们回顾一下之前的代码——
import pygame,sys,time,random
from pygame.locals import *
pygame.init()
#创建屏幕
canvas = pygame.display.set_mode((600,450))
pygame.display.set_caption("escape")
#导入图片
bg0 = pygame.image.load('images/black_bg.png')
bg1 = pygame.image.load('images/bg1.png')
start_button1 = pygame.image.load('images/start_button1.png')
start_button2 = pygame.image.load('images/start_button2.png')
#设置变量
state = 'START'
start_button_state = 0
bg_alpha = 1
start_button_x1 = 289
start_button_speed = 0.6
#判断鼠标位置
def mousein(x,y,width,height):
mx,my = pygame.mouse.get_pos()
if (mx >= x and mx <= x+width) and (my >= y and my <= y+height):
return True
else:
return False
#监测事件
def HandleEvent():
global state,start_button_state
for event in pygame.event.get():
if event.type == pygame.QUIT:
state = 'QUIT'
if event.type == pygame.MOUSEMOTION:
if state == 'START':
if mousein(289,280,273,131):
start_button_state = 1
else:
start_button_state = 0
if event.type == pygame.MOUSEBUTTONDOWN:
if state == 'START':
if mousein(289,280,273,131):
state = 'TEACH'
#主循环
while True:
if state == 'QUIT':
pygame.quit()
sys.exit()
elif state == 'START':
bg1.set_alpha(bg_alpha)
canvas.blit(bg1,(0,0))
if bg_alpha <= 30:
bg_alpha += 0.1
start_button_x1 += start_button_speed
if start_button_x1 <= 279 or start_button_x1 >= 299:
start_button_speed = -start_button_speed
if start_button_state == 0:
start_button1.set_alpha(bg_alpha)
canvas.blit(start_button1,(start_button_x1,280))
elif start_button_state == 1:
start_button2.set_alpha(bg_alpha)
canvas.blit(start_button2,(start_button_x1,280))
elif state == 'TEACH':
pass #这里,是我们今天要做的内容
HandleEvent()
pygame.display.update()
time.sleep(0.001)
可以注意到,在 while True 循环里面 elif state == 'TEACH' 这个判断的下面被pass掉了,
这里就是我们今天需要完成的内容~
3、创建 Teach_Part1 方法
为了使主循环里代码尽量的简洁,我们可以在 HandleEvent 方法与 while True 主循环之间
创建一个名为 Teach_Part1 的方法,在方法里写今天教程的代码,使代码方便查看与修改
#教程
def Teach_Part1():
pass
4、在方法中,增加图片的淡入效果
现在,我们希望让介绍游戏角色的图片有一个淡入的效果,这样可以加深玩家对于角色的印象
一样的,这需要用到上一篇博客所提到的 set_alpha 方法——
Surface.set_alpha(透明度) #透明度是一个1~255的整数
首先,我们来实现第一个介绍游戏角色的图片(teach_tell1.png)的淡入效果(以下简称图片1)
第一步,别忘了导入图片哟~
teach_tell1 = pygame.image.load('images/teach_tell1.png') #导入图片
#导入图片
bg1 = pygame.image.load('images/bg1.png')
teach_tell1 = pygame.image.load('images/teach_tell1.png') #注意别忘了导入图片
第二步,需要再创建一个变量(是在设置变量里添加变量)
tell1_alpha = 1 #用于控制 teach_tell1 图片的透明度
#设置变量 state = 'START' start_button_state = 0 bg_alpha = 1 start_button_x1 = 289 start_button_speed = 0. tell1_alpha = 1 #用于控制 teach_tell1 图片的透明度
第三步,在 Teach_Part1 方法里面全局化变量(使用global关键字),怎么用不用我说吧~
#教程
def Teach_Part1():
global tell1_alpha,teach_tell1
这里需要注意一下,不可以跳过这一步哦!程序会报错
Traceback (most recent call last): File "C:UsersGY123456Desktopescapeescape_soundcode.py", line 105, inTeach_Part1() File "C:UsersGY123456Desktopescapeescape_soundcode.py", line 69, in Teach_Part1 if tell1_alpha <= 255: UnboundLocalError: local variable 'tell1_alpha' referenced before assignment
报这个错的大致原因,就是局部变量 tell1_alpha 在赋值之前被引用,具体有一个变量作用域的问
题,形象点说就是假如你穿越到古代,非让原始人写简体字,这当然不可能嘛,它都不知道简体
字是啥东西,所以当然不会写。global 就等于教会原始人简体字是啥、它怎么写,那当然就没问
题了。言归正传,对于这个错,最快的解决方法就是用 global 把它们都全局化,问题就没有啦~
第四步,使用 set_alpha 方法实现图片1的淡入
#教程
def Teach_Part1():
global tell1_alpha,teach_tell1, #全局化变量
if tell1_alpha <= 255:
canvas.fill((0,0,0)) #使窗口全黑,防止图片重叠,所以先进行覆盖
canvas.blit(teach_tell1,(50,48)) #画出 teach_tell1 图片
teach_tell1.set_alpha(tell1_alpha) #设置透明度为 tell1_alpha 的值
tell1_alpha += 0.4 #使透明度增加
第五步,实现“下一步”的按钮和其相应的箭头闪烁效果
按钮比较简陋,因为填充会破坏外面框蜡笔的感觉,所以就不做选中的样子啦
箭头闪烁也很简单,使用两个图片来回交替即可
这里又有一个小知识点,pygame用户事件与定时器,它的使用方法是这样的——
用户事件名 = pygame.USEREVENT
pygame.time.set_timer(用户事件名,时间间隔)
"""
可以每隔一个时间间隔(以毫秒为单位,也就是千分之一秒)就执行一次用户事件,具体执行方法如下:
for event in pygame.event.get():
if event.type == 用户事件名:
你要执行的内容
另:如果你想设置多个定时器,可以使用如下操作:
用户事件名1 = pygame.USEREVENT
用户事件名2 = pygame.USEREVENT + 1
用户事件名3 = pygame.USEREVENT + 2
以此类推,定时器与执行方法不变,挨个去设置与判断就行
如果你想要关闭定时器,把时间间隔设置为0即可
"""
ok,了解了定时器之后,我们就可以开始写代码啦~
首先,先导入图片
next_teach = pygame.image.load('images/next_teach.png')
arror_fornext = pygame.image.load('images/arror_fornext.png')
arror_fornext1 = pygame.image.load('images/arror_fornext1.png')
#导入图片
bg1 = pygame.image.load('images/bg1.png')
wall = pygame.image.load('images/wall.png')
door = pygame.image.load('images/door.png')
mine = pygame.image.load('images/mine.png')
teach_tell1 = pygame.image.load('images/teach_tell1.png')
next_teach = pygame.image.load('images/next_teach.png') #导入这个
arror_fornext = pygame.image.load('images/arror_fornext.png') #导入这个
arror_fornext1 = pygame.image.load('images/arror_fornext1.png') #导入这个
start_button1 = pygame.image.load('images/start_button1.png')
start_button2 = pygame.image.load('images/start_button2.png')
设置变量并全局化~
arror_settimer = False #用于控制在 HandleEvent 方法中什么时候执行定时器内容 arror_state = 0 #用于控制箭头图片,是 arror_fornext1 还是 arror_fornext arror_timeinterval = 400 #定时器的时间间隔,设置成变量是为了不需要时设成0关闭定时器
#教程第一部分
def Teach_Part1():
global tell1_alpha,teach_tell1,next_teach,arror_timeinterval,arror_settimer
if tell1_alpha <= 255:
canvas.fill((0,0,0))
canvas.blit(teach_tell1,(50,48))
teach_tell1.set_alpha(tell1_alpha)
tell1_alpha += 0.4
设置定时器
(一定要在方法和while True外!) #设置定时器 FLICKER = pygame.USEREVENT pygame.time.set_timer(FLICKER,arror_timeinterval)
判断是否显示按钮与箭头,如果是的话就显示
elif tell1_alpha > 255 and arror_timeinterval != 0: #如果tell1_alpha大于255,说明文字已显示
canvas.blit(next_teach,(449,169)) #画出 next_teach 就是那个按钮
arror_settimer = True #执行定时器的内容
当按下按钮时的效果,在HandleEvent方法里(效果是下个博客做的,这里暂时黑屏)
这里也要注意,记得全局化变量,同时定时器一定要在这个方法之前!
def HandleEvent():
global state,start_button_state,arror_fornext,arror_fornext1,arror_state,arror_timeinterval,arror_settimer
"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
state = 'QUIT'
if event.type == pygame.MOUSEMOTION:
if state == 'START':
if mousein(289,280,273,131):
start_button_state = 1
else:
start_button_state = 0
if event.type == pygame.MOUSEBUTTONDOWN:
if state == 'START':
if mousein(289,280,273,131):
state = 'TEACH'
elif state == 'TEACH':
if mousein(449,169,94,52):
arror_timeinterval = 0
"""
if arror_settimer: #当arror_settimer为真时再执行,起到开关效果
if event.type == FLICKER: #判断定时器是否发的用户事件
if arror_state == 0: #当为0时画出 arror_fornext.png
canvas.blit(arror_fornext,(551,186))
arror_state = 1
elif arror_state == 1: #当为1时画出 arror_fornext.png
canvas.blit(arror_fornext1,(551,186))
arror_state = 0
当点击按钮后在 Teach_Part1 方法里做出反应
#教程第一部分
def Teach_Part1():
"""
global tell1_alpha,teach_tell1,next_teach,arror_timeinterval,arror_settimer
if tell1_alpha <= 255:
canvas.fill((0,0,0))
canvas.blit(teach_tell1,(50,48))
teach_tell1.set_alpha(tell1_alpha)
tell1_alpha += 0.4
elif tell1_alpha > 255 and arror_timeinterval != 0:
canvas.blit(next_teach,(449,169))
arror_settimer = True
"""
elif arror_timeinterval == 0: #如果定时器关闭(即变相的判断是否点击了按钮)
canvas.fill((0,0,0)) #先黑屏并pass掉,下一个博客做这个
pass
5、全部代码
import pygame,sys,time,random
from pygame.locals import *
pygame.init()
#创建屏幕
canvas = pygame.display.set_mode((600,450))
pygame.display.set_caption("escape")
#导入图片
bg1 = pygame.image.load('images/bg1.png')
wall = pygame.image.load('images/wall.png')
door = pygame.image.load('images/door.png')
mine = pygame.image.load('images/mine.png')
teach_tell1 = pygame.image.load('images/teach_tell1.png')
next_teach = pygame.image.load('images/next_teach.png')
arror_fornext = pygame.image.load('images/arror_fornext.png')
arror_fornext1 = pygame.image.load('images/arror_fornext1.png')
start_button1 = pygame.image.load('images/start_button1.png')
start_button2 = pygame.image.load('images/start_button2.png')
#设置变量
state = 'START'
start_button_state = 0
bg_alpha = 1
tell1_alpha = 1
tell2_alpha = 1
tell3_alpha = 1
start_button_x1 = 289
start_button_speed = 0.6
arror_settimer = False
arror_state = 0
arror_timeinterval = 400
#设置定时器
FLICKER = pygame.USEREVENT
pygame.time.set_timer(FLICKER,arror_timeinterval)
#判断鼠标位置
def mousein(x,y,width,height):
mx,my = pygame.mouse.get_pos()
if (mx >= x and mx <= x+width) and (my >= y and my <= y+height):
return True
else:
return False
#监测事件
def HandleEvent():
global state,start_button_state,arror_fornext,arror_fornext1,arror_state,arror_timeinterval,arror_settimer
for event in pygame.event.get():
if event.type == pygame.QUIT:
state = 'QUIT'
if event.type == pygame.MOUSEMOTION:
if state == 'START':
if mousein(289,280,273,131):
start_button_state = 1
else:
start_button_state = 0
if event.type == pygame.MOUSEBUTTONDOWN:
if state == 'START':
if mousein(289,280,273,131):
state = 'TEACH'
elif state == 'TEACH':
if mousein(449,169,94,52):
arror_timeinterval = 0
if arror_settimer:
if event.type == FLICKER:
if arror_state == 0:
canvas.blit(arror_fornext,(551,186))
arror_state = 1
elif arror_state == 1:
canvas.blit(arror_fornext1,(551,186))
arror_state = 0
#教程第一部分
def Teach_Part1():
global tell1_alpha,teach_tell1,next_teach,arror_timeinterval,arror_settimer
if tell1_alpha <= 255:
canvas.fill((0,0,0))
canvas.blit(teach_tell1,(50,48))
teach_tell1.set_alpha(tell1_alpha)
tell1_alpha += 0.4
elif tell1_alpha > 255 and arror_timeinterval != 0:
canvas.blit(next_teach,(449,169))
arror_settimer = True
elif arror_timeinterval == 0:
canvas.fill((0,0,0))
pass
#主循环
while True:
if state == 'QUIT':
pygame.quit()
sys.exit()
elif state == 'START':
bg1.set_alpha(bg_alpha)
canvas.blit(bg1,(0,0))
if bg_alpha <= 30:
bg_alpha += 0.05
start_button_x1 += start_button_speed
if start_button_x1 <= 279 or start_button_x1 >= 299:
start_button_speed = -start_button_speed
if start_button_state == 0:
start_button1.set_alpha(bg_alpha)
canvas.blit(start_button1,(start_button_x1,280))
elif start_button_state == 1:
start_button2.set_alpha(bg_alpha)
canvas.blit(start_button2,(start_button_x1,280))
elif state == 'TEACH':
Teach_Part1()
HandleEvent()
pygame.display.update()
time.sleep(0.001)
6、效果展示
总结 这篇文章记录了逃出生天小游戏的游戏开始界面,开始按钮的制作过程及成果,作者会继续努力,争取继续与大家分享这个小游戏的制作过程,加油!



