截至目前为止,我们已经学会了Pygame 的事件、Pygame 图片的转换以及移动、基本的图形绘制、透明度调整这些内容。但距离我们真正的实现一个小游戏还差一个重要的环节,那就是碰撞检测,在讲碰撞检测之前,我们需要补充一个新的知识点,叫做动画精灵。
动画精灵是指在游戏开发中,那些被赋予灵魂的事物,像前面例子中的小蛇。
在真正的游戏开发中,远远不止只有一个精灵,数量随时都会发生变化,比如说:敌人不断地出现以及被消灭,它们的移动轨迹也并不都是一样的,既然移动轨迹不同,就一定会发生碰撞,这就说明我们的精灵还要支持碰撞检测,碰撞检测是游戏开发中一个重要的环节。
我记得在若干年前,网上还一直很流行面向对象和面向过程两大阵营的PK,不过现在这一类的讨论越来越少了。在此之前,我们一直使用面向过程的思维方式在写代码,先载入一张图片,构造一条小蛇,然后对各种事件进行按顺序的处理,让小蛇可以依照我们的想法去移动、去撞墙,我们的代码也越来越完善了。但是,这种思维方式有一定的局限性,比方说,你的精灵多起来了,你的小蛇一多,那你就需要花很多时间去考量大量重复的代码应该如何去部署才能使得你的代码更优美,语句之间不会产生冲突,然后你就焦头乱额了。
所以这一节课我们会教大家面向对象的游戏开发思维是怎样的。
从今天开始,这几节课,我来带大家完成一个小游戏来学习新的知识,同时,体验一个游戏开发的过程,这个小游戏的名字叫做 Play TheBall。
至此,游戏结束!
我们现在就来一步一步写这个小游戏:
我们刚才一直在说动画精灵,其实 Pygame 已经给我们准备了一个动画精灵的基类,我们继承它就可以了。
import pygame
import sys
from pygame.locals import * #把Pygame 的常量名导进去
from random import *
class Ball(pygame.sprite.Sprite): #继承动画精灵基类
def __init__(self, image, position, speed, bg_size):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image).convert_alpha()
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
self.speed = speed
self.width, self.height = bg_size[0], bg_size[1]
def move(self):
self.rect = self.rect.move(self.speed)
#实现小球从某侧出界,从对侧进来
if self.rect.right < 0:
self.rect.left = self.width
elif self.rect.left > self.width:
self.rect.right = 0
elif self.rect.bottom < 0:
self.rect.top = self.height
elif self.rect.top > self.height:
self.rect.bottom = 0
def main():
pygame.init()
ball_image = "gray_ball.png"
bg_image = "background.png"
running = True
bg_size = width, height = 1024, 681
screen = pygame.display.set_mode(bg_size)
pygame.display.set_caption("Play the ball - Python Demo")
background = pygame.image.load(bg_image).convert_alpha()
balls = []
for i in range(5): #创建5个球
position = randint(0, width-100), randint(0, height-100)
speed = [randint(-10, 10), randint(-10, 10)]
ball = Ball(ball_image, position, speed, bg_size)
balls.append(ball)
clock = pygame.time.Clock()
while running: #后面会在游戏结束时,给running 赋值 False。
for event in pygame.event.get():
if event.type == QUIT: #当按关闭时停止游戏
sys.exit()
screen.blit(background, (0, 0))
for each in balls:
each.move()
screen.blit(each.image, each.rect)
pygame.display.flip()
clock.tick(30)
if __name__ == "__main__":
main()