![v2-6705a36d15a6c57a338b42e219f574cf_1440w.jpg?source=172ae18b](http://img-01.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-6705a36d15a6c57a338b42e219f574cf_1440w.jpg?source=172ae18b)
好久不见呀~
![v2-3fa8f8b575c14d6a14ede51713a4617a_b.png](http://img-03.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-3fa8f8b575c14d6a14ede51713a4617a_b.png)
Long long ago...
有一群野人,他们的手脚都被锁链绑着,日日夜夜面对着地下洞穴的墙壁,洞外有一些拿着火把的生物走过,在墙壁上投下斑驳的影子。这群野人自出生所看到的唯一事物就是这些“皮影戏”,忽然有一天,一个野人挣脱了锁链...
![v2-aceee21787be6ada7594637e0c76306d_b.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic2.zhimg.com/v2-aceee21787be6ada7594637e0c76306d_b.jpg)
柏拉图认为,属于“物质世界”的每一样东西必然是由某种物质做成。这种物质会受时间侵蚀,但做成这些东西的“模子”却永恒不变,柏拉图将这些“模子”称为“理型”或观念。
![v2-353ad817b81245835116d9ac69945231_b.png](http://img-02.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic2.zhimg.com/v2-353ad817b81245835116d9ac69945231_b.png)
咳咳,装X结束~咱们这一期,就来看看洞穴外的世界吧~
这是素材:
链接:https://pan.baidu.com/s/1p7SAAHIdM2dbTBuDWQEY9g 提取码:ataf
Part1 钥匙啊~
各位看官还记得咱们在Pygame(一)所讲的图片导入的方法吗?温馨小提示:定义一个变量>load函数加载图片>像素复制(blit)
jpgFileName = 'lanbo800_600.jpg'
imgRect = pygame.image.load(jpgFileName)
screen.blit(imgRect,[0,0])
Part2 运动
![v2-2e2f76e167079585fe18b7743670d8ea_b.gif](http://img-02.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-2e2f76e167079585fe18b7743670d8ea_b.gif)
一、移动与擦除
计算机动画实际上就是把图像从一个地方移动到另一个地方。要向让小鸟移动,我们需要两步:在新的位置上画出图形and把原来的图形擦掉。
我们在导入小鸟的图片后,小鸟的位置为(300,200),接着需要输入小鸟移动后的位置,接着加入时间延迟。为了让我们清楚地看到小鸟位置的变化过程,我们需要将这个时间设置得长一些,代码如下:
pygame.time.delay(1000)
screen.blit(birdRect,[400, 300])
pygame.display.flip()
![v2-78725a923ca9147eef6917764430910f_b.jpg](http://img-01.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic4.zhimg.com/v2-78725a923ca9147eef6917764430910f_b.jpg)
我们可以看到,小鸟移动到了新的位置。然而原来的位置还留着它的传说~这就需要将这个痕迹“擦除”。我们的背景色是白的,所以需要白色矩形覆盖原来的图片。我们的小鸟图大约为80*80像素,这也是白色矩形的大小,将如下代码加入会块移(bilt)的命令行下:
pygame.draw.rect(screen,THECOLORS['white'],[300,200,80,80],0)
![v2-47f8821e3200fd395d15ee593291ff0f_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic4.zhimg.com/v2-47f8821e3200fd395d15ee593291ff0f_b.jpg)
二、连续移动
为了让小鸟能灵活地飞行,我们需要将它每次移动的距离设置地小一些,并连续移动许多次。这就需要将x、y值设为变量,并引入循环语句:
在引入pygame之前,需要增加两个参数:
bird_x = 0
bird_y = 0
加载小鸟图片后,用两个参数表示小鸟的位置:
screen.blit(birdRect,[bird_x, bird_y])
为了让画面流畅,我们需要缩短延迟时间,让人眼几乎分辨不出从位置1到位置2过程,并且之前设置的x、y的值是不断变化的。我们在主循环中加入以下代码:
pygame.time.delay(20)
pygame.draw.rect(screen,THECOLORS['white'],[bird_x,bird_y,100,100],0)
bird_x = bird_x + 3
bird_y = bird_y + 3
screen.blit(birdRect,[bird_x, bird_y])
pygame.display.flip()
运行后,我们发现几秒钟的时间小鸟就逃走啦~
![v2-3f5ae07bb6d5f685a3b422e6207873f4_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-3f5ae07bb6d5f685a3b422e6207873f4_b.jpg)
三、青春的小鸟回来啦~
如果想让小鸟飞回来,就需要知道它什么时候“撞到”窗口边界,然后让它朝反方向移动。如果想让小鸟一直来回飞行,就需要要在窗口的上下左右都做同样的处理。
在左(left)边界与顶部(top)边界,我们只需要检查球的位置是不是等于 0(或者某个很小的数)。在右(right)边界与底部(bottom)边界,我们需要减去球的宽度与高度:
![v2-a29f27837eb6bb1a84af77a575b40738_b.jpg](http://img-01.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-a29f27837eb6bb1a84af77a575b40738_b.jpg)
同时,我们引入一个新的变量speed,用来确定小鸟以多快的速度飞行:
bird_speed_x = 5
bird_speed_y = 5
在主循环中,我们可以不断加小鸟速度值来表示位置的变化。接着用if语句判断小鸟是否碰壁,来决定它是否需要以相同速度往会飞:
bird_x = bird_x + bird_speed_x
bird_y = bird_y + bird_speed_y
if bird_x > 720 or bird_x < 0:
bird_speed_x = -bird_speed_x
if bird_y > 520 or bird_y < 0:
bird_speed_y = -bird_speed_y
为了让大家有个直观的认识,我不擦除痕迹,可以清晰地看见小鸟的运动轨迹:
![v2-e7d2d2fe5e05ffc0f2e0fa7146a8eb18_b.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-e7d2d2fe5e05ffc0f2e0fa7146a8eb18_b.jpg)
哈哈,新发明了一种设计迷宫的方法~
![v2-3303ad443590f660f1a784d536ddb4ac_b.png](http://img-02.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-3303ad443590f660f1a784d536ddb4ac_b.png)
这里是完整代码:
# 文件名: movingBird.py
#参数准备
bird_x = 0
bird_y = 0
bird_speed_x = 5
bird_speed_y = 5
# 导入
import pygame
from pygame.color import THECOLORS
# 初始化
pygame.init()
# 创建一个窗口
screen = pygame.display.set_mode([800,600])
# 用白色填充屏幕
screen.fill(THECOLORS['white'])
# 加载愤怒小鸟的图片,更新图像
pngFileName = 'redBird.png'
birdRect = pygame.image.load(pngFileName)
screen.blit(birdRect,[bird_x, bird_y])
# 翻转
pygame.display.flip()
# 主循环
mRunning = True
while mRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
mRunning = False
#时间延迟
pygame.time.delay(20)
#覆盖痕迹
pygame.draw.rect(screen,THECOLORS['white'],[bird_x,bird_y,100,100],0)
#小鸟的位置
bird_x = bird_x + bird_speed_x
bird_y = bird_y + bird_speed_y
#小鸟碰壁后飞回
if bird_x > 720 or bird_x < 0:
bird_speed_x = -bird_speed_x
if bird_y > 520 or bird_y < 0:
bird_speed_y = -bird_speed_y
screen.blit(birdRect,[bird_x, bird_y])
pygame.display.flip()
pygame.quit()
【小练习】
想要让小鸟回来,还有一种方式:翻转,即小鸟从一边飞出,又从对边飞入。只需要对限制边框的if语句做如下修改:
if bird_x > 720 or bird_x < 0:
bird_x = 0
if bird_y > 520 or bird_y < 0:
bird_y = 0
![v2-0cbd09d692183ab19ae1ed37df27fcbb_b.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic4.zhimg.com/v2-0cbd09d692183ab19ae1ed37df27fcbb_b.jpg)
Part3 动画精灵
还记得开始时的洞穴故事吗?野人们看到的墙壁上的影子实际上就是Python中的对象,即具体的实例,如一只叼着树枝的小鸟的影子。而我们现在就是要走出洞穴外,看看这个树枝的纹理、小鸟的颜色和飞行的特点等,这就是我们所说的类,即对象的属性和方法(函数)。
在Part2部分,我们可以直观地感受到看似简单的动画实际上并不简单它包括有有大量的图像移动,擦除痕迹、碰撞检测等。Pygame 有一个特殊的模块(sprite)来处理这些四处移动的单个图像(动画精灵),这个模块模块提供了一个动画精灵基类,即Sprite。正常情况下,我们不会直接使用基类,而是基于pygame.sprite.Sprite 来创建自己的子类。
首先创建一个类定义,接着用__init__ 方法传递参数,这样创建实例对象时就会把属性设置为咱们希望的值。我们刚才提到的“洞穴故事”中,小鸟有各种形态的影子,Python的类可以生成无数对象,当一个对象的方法被调用的时候,对象会将自身的应用作为第一个参数传给该方法,self通知Python需要操作哪个对象的方法。接着初始化动画精灵、载入图像、得到定义图像边界的矩形并设置球的初始位置、速度属性等:
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
我们创建好小鸟的类后,使用一个名为move()的类方法来让小鸟飞翔,接着检查小鸟是否碰到了窗口,如果碰到,就让它以相反的速度运动:
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]
定义好类后,就需要创建一些对象实例,我们用以前的方法创建一个特定大小的窗口,载入图片,接着创建一个按照行列排列的小鸟群,用一个列表birds = []来跟踪所有小鸟,小鸟的速度用random.choice()函数来设置,最后把各个小鸟增加到列表中:
birds = []
for row in range(0,2):
for column in range(0,2):
location = [column*180+10,row*180+10]
speed = [random.choice([-2,2]),random.choice([-2,2])]
bird = AngryBirdClass(img_file,location,speed)
birds.append(bird)
刷新屏幕后,就有四只小鸟在不规则运动啦~
![v2-9b99f885da001ef20692696bb6769678_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-9b99f885da001ef20692696bb6769678_b.jpg)
完整代码如下:
#引入:
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]
#设置窗口大小、颜色、载入图片
size = width,height = 800,600
screen = pygame.display.set_mode(size)
screen.fill(THECOLORS['white'])
img_file = 'redBird.png'
#创建一个小鸟列表
birds = []
for row in range(0,2):
for column in range(0,2):
#每次循环都有一个不同的位置
location = [column*180+10,row*180+10]
#速度随机
speed = [random.choice([-2,2]),random.choice([-2,2])]
bird = AngryBirdClass(img_file,location,speed)
#将各个小鸟添加到列表中
birds.append(bird)
#主循环
mRunning = True
while mRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
mRunning = False
#时间延迟
pygame.time.delay(20)
screen.fill(THECOLORS['white'])
for bird in birds:
bird.move()
screen.blit(bird.image,bird.rect)
pygame.display.flip()
pygame.quit()
【小练习】
一种小鸟太单调啦,如何引入两种类型的鸟呢?只需要再创建一个带有for循环的小鸟对象就可以啦,大家动手试试吧~
![v2-f4ab5883bf08d4780754ae6ececc2119_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic2.zhimg.com/v2-f4ab5883bf08d4780754ae6ececc2119_b.jpg)
我们可以发现,在这个过程中类不需要做任何改变,是的,这就是柏拉图所说的“理型”。而我们不同颜色的小鸟就是理型的影子~
运行程序后,大家有木有发现小鸟有重叠呢?
![v2-ac6b751ccf486899c97e3e23c880fd21_b.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic2.zhimg.com/v2-ac6b751ccf486899c97e3e23c880fd21_b.jpg)
这种动画效果也太假了吧!想知道怎么解决这个问题嘛,期待阿呆下次的展示吧~
对了,临走前该干点啥呢?
![v2-5a189bc716d6a5caf067d9c565b05e19_b.png](http://img-01.proxy.5ce.com/view/image?&type=2&guid=d3ef3529-1c30-eb11-8da9-e4434bdf6706&url=https://pic2.zhimg.com/v2-5a189bc716d6a5caf067d9c565b05e19_b.png)