在上一期,阿呆提及了柏拉图,收藏数激增...嗯...
本期阿呆请来了本华叔~
本华叔说:“音乐凭借自身的特性成了一种合适的素材,能够把人心的活动,亦即意欲的活动---其本质永远就在于满足和不满足,虽然这里面有着无数的级别-连带其至为微妙、细腻的差别和变化,忠实地塑造和重现出来。”
今天,阿呆就带领大家开启音乐之旅~
这是材料,各位看官请收好~
链接:https://pan.baidu.com/s/1lJch03Ma32S5oRUiuDXr-A 提取码:4qrb
Part 1 锦上添花
上一期的最后,我们留了一个小问题:如何避免小鸟的重叠?
1. 碰撞检测
Pygame 中已经内置了碰撞检测来而检查每一个其他动画精灵的位置和大小,防止出现重叠的现象。动画精灵模块的spritecollide()函数用来检测某个精灵是否与制定组的其他精灵发生碰撞,这个函数的形式如下:
spritecollide(被检测的精灵(sprite),指定组(group),是否重叠(False))
另外,与上一期中建立的小鸟列表不同,我们将会使用 Pygame 的组类。组和碰撞检测密切相关。它不仅可以检测不同组的碰撞,还能检测组内部的碰撞。
最后,我们需要把小鸟的动画部分放在一个函数中,在Python中创建或定义函数要使def关键字,随后就可以用函数名来使用或调用这个函数。我们的函数命名为 animate()。在这个函数中,我们把同一组精灵的碰撞检测分为四步:
1.1 先移动所有小鸟
1.2 从这个组中删除这只小鸟
1.3 检查这个小鸟与组中其他小鸟的碰撞
1.4 把小鸟添加到原来的组中
按照以上的文字说明,代码如下:
def animate(group):
screen.fill(THECOLORS['white'])
for ball in group:
ball.move()
for ball in group:
group.remove(ball)
if pygame.sprite.spritecollide(ball, group, False):
ball.speed[0] = -ball.speed[0]
ball.speed[1] = -ball.speed[1]
group.add(ball)
ball.move()
screen.blit(ball.image, ball.rect)
pygame.display.flip()
pygame.time.delay(20)
运行代码,就会发现两只小鸟相遇后,转眼间又相忘于江湖啦~
2. 控制帧速率
为了让我们的程序更准确完美,我们采用pygame.time.Clock()来代替time.delay()。用大白话说,我们在程序中加入一个定时器,设定每次循环所需的时间,这样我们就不用在每个循环中都增加一个时间延迟啦~
不过,这个循环时间该怎么设定呢?我们采用帧速率(fps)这个参数,也就是循环在每秒运行的次数。而每个循环所用的时间就由1000ms/帧速率算得。如果循环时间超过了设定的范围,程序就会报错。大多数现代计算机都完全可以按20~30fps 的速率运行Pygame 程序。我们这里使用30fps,即在主循环中加入:
clock.tick(30)
好了,来看看我们的完整代码吧,有点儿长,大家要多练习呀~
#引入
import pygame
import random
from pygame.color import THECOLORS
#定义小鸟类
class AngryBirdClass(pygame.sprite.Sprite):
def __init__(self, image_file, location,speed):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left,self.rect.top = location
self.speed = speed
#动画函数
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > height:
self.speed[1] = -self.speed[1]
def animate(group):
screen.fill(THECOLORS['white'])
#先移动所有小鸟
for bird in group:
bird.move()
#将小鸟从组中删除
for bird in group:
group.remove(bird)
#检查碰撞
if pygame.sprite.spritecollide(bird, group, False):
bird.speed[0] = -bird.speed[0]
bird.speed[1] = -bird.speed[1]
#将小鸟添加回原组
group.add(bird)
bird.move()
screen.blit(bird.image, bird.rect)
pygame.display.flip()
#设置窗口大小、颜色、载入图片
size = width,height = 800,600
screen = pygame.display.set_mode(size)
screen.fill(THECOLORS['white'])
img_file1 = 'redBird.png'
img_file2 = 'blueBird.png'
#创建Clock的实例
clock = pygame.time.Clock()
#创建小组
group = pygame.sprite.Group()
for row in range(0,1):
for column in range(0,2):
location = [column*180+10,row*180+10]
speed = [random.choice([-3,3]),random.choice([-5,5])]
bird = AngryBirdClass(img_file1,location,speed)
group.add(bird)
for row in range(0,2):
for column in range(0,1):
location = [column*180+100,row*180+100]
speed = [random.choice([-5,5]),random.choice([-3,3])]
bird = AngryBirdClass(img_file2,location,speed)
group.add(bird)
#主循环
mRunning = True
while mRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
mRunning = False
#检查帧速率
frame_rate = clock.get_fps()
print ('frame rate =',frame_rate )
animate(group)
#控制帧速率
clock.tick(30)
pygame.quit()
Part2 Let's play band
沉浸在编程世界的阿呆似乎忘记了自己是一名心理系的学生~为了说明我木有不务正业,现在开始强行找补~
其实啊,游戏里包含着许多心理学的概念呢~例如:游戏里有不同的难度等级、可以将经验迁移到新情境中,更重要的是,它能随时反馈结果,让我们产生参与感和沉浸感。咱们接下来就会跟计算机第一次亲密接触啦~
2.1 鼠标事件
在Pygame中,我们希望能按下鼠标就做某件事情,我们可以利用 MOUSEBUTTONDOWN 事件得到鼠标按钮何时按下,现在,我们就用它来播放一首优美的歌曲。还记得怎么导入音乐吗?我们首先用load()函数载入音乐,接着设置音量及播放,代码如下:
mp3FileName = 'CanonInD.mp3'
pygame.mixer.music.load(mp3FileName)
pygame.mixer.music.set_volume(0.3)
pygame.mixer.music.play()
在导入我们所需要的音乐、背景&按钮图片后,在主循环中,我们加入以下代码,按下鼠标后,音乐就会播放啦~
if event.type == pygame.MOUSEBUTTONDOWN:
unpause = not unpause
运行代码,我们会发现,当我们的鼠标点击
当我们点击
效果如下:
完整代码:
#引入
import pygame
#初始化
pygame.init()
#设定窗口大小、标题、背景图片
size = width,height = 400,300
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Canon')
pngFileName_3 = 'bgWhale.png'
backGround = pygame.image.load(pngFileName_3)
screen.blit(backGround,[0,0])
#载入Canon音乐
mp3FileName = 'CanonInD.mp3'
pygame.mixer.music.load(mp3FileName)
pygame.mixer.music.set_volume(0.3)
pygame.mixer.music.play()
#给unpause赋予播放状态
unpause = False
#载入图片
pngFileName_1 = 'unpause.png'
pngFileName_2 = 'pause.png'
imgRect_1 = pygame.image.load(pngFileName_1)
imgRect_2 = pygame.image.load(pngFileName_2)
#设定按钮的位置
unpause_rect = imgRect_1.get_rect()
unpause_rect.left,unpause_rect.top = (0),(height - unpause_rect.height)
#创建Clock的实例
clock = pygame.time.Clock()
#主循环
mRunning = True
while mRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
mRunning = False
#鼠标按下事件
if event.type == pygame.MOUSEBUTTONDOWN:
unpause = not unpause
#播放
if unpause:
screen.blit(imgRect_1,unpause_rect)
pygame.mixer.music.unpause()
#暂停
else:
screen.blit(imgRect_2 ,unpause_rect)
pygame.mixer.music.pause()
#帧速率
clock.tick(30)
pygame.display.flip()
pygame.quit()
【小练习】
我们学会了用鼠标与计算机交互,如果想使用键盘来操作,该怎么办呢?其实很简单,在Pygame中,键盘事件是 KEYDOWN。至于键盘上的每个键,都以K_开头,比如字母a,用K_a表示,向上箭头用K_UP表示。我们想用空格键来控制音乐的开关,就用K_SPACE。在主循环中,我们将鼠标的命令行替换为如下代码:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
unpause = not unpause
大家自己动手试试吧~
2.2 键盘事件
刚才我们在键盘上小试牛刀,为了不让大家有审美疲劳,用盲僧来镇楼!
阿呆碎碎念:补充一个插入文本的小知识
在载入图片后,可加上以下代码,其中第一行的字体大家可以在C盘>Windows>Fonts文件夹里自行选择哦~
font = pygame.font.Font('C:WindowsFontscambriab.ttf',14)
text = font.render(u'Force is meaningless without skills!',True,[255,255,255],1)
text_rect = text.get_rect()
text_rect.center = (200,270)
现在我们让盲僧动起来吧~我们预先设定盲僧有三种状态:正面、向左转、向右转。在程序的开头,我们为这三种状态的图片创建了一个列表,然后将图片按特定的顺序放入列表:
mangseng_images = ['HeroMangSeng_Down.png','HeroMangSeng_Right.png','HeroMangSeng_Left.png']
首先,我们创建一个盲僧的类,定义他的初始状态、位置、角度等信息。其中,他的初始位置我们用他的中心位置来定义:
self.rect.center = [300,300]
接着,我们用一个类来改变盲僧的状态,它会在角度的值改变时载入正确的图片,并设置好盲僧运动的速度。速度由水平和竖直两个方向构成。我们只改变左右方向的速度,即x方向。同时,盲僧的状态不能超过+-1,即向左转&向右转,按照这个思路,代码如下:
def turn(self, direction):
self.angle = self.angle + direction
if self.angle > 1:
self.angle = 1
if self.angle < -1:
self.angle = 1
center = self.rect.center
self.image = pygame.image.load(mangseng_images[self.angle])
self.rect = self.image.get_rect()
self.rect.center = center
speed = [self.angle,0]
return speed
盲僧位移后,还要限制他不要移动到窗口外:
def move(self, speed):
self.rect.centerx = self.rect.centerx + speed[0]
if self.rect.centerx < 50:
self.rect.centerx = self.rect.centerx - speed[0]
if self.rect.centerx > 550:
self.rect.centerx = self.rect.centerx - speed[0]
随后,重绘屏幕、设置窗口大小。在主循环中,我们加入按键事件,用左箭头让盲僧向左转并加入向左转的图片,用右箭头让盲僧向右转同时载入向右转的图片,空格键退出游戏:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
speed = mangseng.turn(-1)
elif event.key == pygame.K_RIGHT:
speed = mangseng.turn(1)
elif event.key == pygame.K_SPACE:
running = False;
执行程序后,我们可以看到如下效果:
完整代码如下:
#引入
import pygame
from pygame.color import THECOLORS
#载入三种状态的图片
mangseng_images = ['HeroMangSeng_Down.png','HeroMangSeng_Right.png','HeroMangSeng_Left.png']
#定义盲僧类
class MangSengClass(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('HeroMangSeng_Down.png')
self.rect = self.image.get_rect()
#以盲僧的中心来定义他的位置
self.rect.center = [300,300]
self.angle = 0
#改变盲僧的方向
def turn(self, direction):
self.angle = self.angle + direction
#限制盲僧的状态
if self.angle > 1:
self.angle = 1
if self.angle < -1:
self.angle = 1
center = self.rect.center
self.image = pygame.image.load(mangseng_images[self.angle])
self.rect = self.image.get_rect()
self.rect.center = center
#设定水平方向的速度
speed = [self.angle,0]
return speed
#动画函数,限定盲僧在窗口内运动
def move(self, speed):
self.rect.centerx = self.rect.centerx + speed[0]
if self.rect.centerx < 50:
self.rect.centerx = 50
if self.rect.centerx > 550:
self.rect.centerx = 550
#重绘屏幕
def animate():
screen.fill(THECOLORS['white'])
screen.blit(mangseng.image, mangseng.rect)
pygame.display.flip()
#设置窗口大小、游戏名称、颜色、速度范围
pygame.init()
size = width,height = 600,600
screen = pygame.display.set_mode(size)
pygame.display.set_caption('盲僧')
#创建Clock的实例
clock = pygame.time.Clock()
mangseng = MangSengClass()
speed = [0,6]
#主循环
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 = mangseng.turn(-1)
elif event.key == pygame.K_RIGHT:
speed = mangseng.turn(1)
elif event.key == pygame.K_SPACE:
running = False;
mangseng.move(speed)
animate()
pygame.quit()
【小练习】
怎样在这个程序中加入背景音乐呢?只需要在设定好窗口大小的命令行中插入以下代码就可以啦~
musicFileName = 'bg_music.ogg
pygame.mixer.music.load(musicFileName)
pygame.mixer.music.set_volume(0.3)
pygame.mixer.music.play()
今天就到这里啦,下期阿呆会和大家一起完成一个完整的小游戏哦,不见不散~
Believer (Kaskade Remix) - Imagine Dragons/Kaskade - 单曲 - 网易云音乐music.163.com