用pygame模块做个小游戏
Pygame是一个Python中专门用于多媒体应用(如电子游戏)的开发模块,其中包含对图像、声音、视频、事件、碰撞等的支持。Pygame建立在SDL的基础上,SDL是一套跨平台的多媒体开发库,用C语言实现,被广泛的应用于游戏、模拟器、播放器等的开发。下面将用Pygame做一个“大球吃小球”的游戏,主要是加深对面向对象编程的理解。
制作游戏窗口
import pygame
def main():
# 初始化导入的pygame中的模块
pygame.init()
# 初始化用于显示的窗口并设置窗口尺寸
screen = pygame.display.set_mode((800, 600))
# 设置当前窗口的标题
pygame.display.set_caption('大球吃小球')
running = True
# 开启一个事件循环处理发生的事件
while running:
# 从消息队列中获取事件并对事件进行处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if __name__ == '__main__':
main()
在窗口中绘图
绘制好图形化窗口后,使用draw模块的函数在窗口上绘制我们需要的图形:线条,矩形,圆形等等,值的注意的是屏幕的坐标系原点在左上角,x轴正向朝右,y抽正向朝下。在表示位置和大小时,默认的单位都是像素,而像素就是屏幕上的一个点。pygame中颜色用的是色光的三原色:红绿蓝,通过一个元组或列表来指定颜色的RGB值,每个值都在0-255之间。
import pygame
def main():
# 初始化导入的pygame中的模块
pygame.init()
# 初始化用于显示的窗口并设置窗口尺寸
screen = pygame.display.set_mode((800, 600))
# 设置当前窗口的标题
pygame.display.set_caption('大球吃小球')
# 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)
screen.fill((242, 242, 242))
# 绘制一个圆(参数分别是: 屏幕, 颜色, 圆心位置, 半径, 0表示填充圆)
pygame.draw.circle(screen, (255, 0, 0,), (100, 100), 30, 0)
# 刷新当前窗口(渲染窗口将绘制的图像呈现出来)
pygame.display.flip()
running = True
# 开启一个事件循环处理发生的事件
while running:
# 从消息队列中获取事件并对事件进行处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if __name__ == '__main__':
main()
实现动画效果
动画效果的实现其实就是让不连续的图片连续的播放,只要每秒中达到了一定的帧数,就能做出流畅的动画效果,而让小球动起来可以在循环中改变小球的位置,并刷新实现。
import pygame
def main():
# 初始化导入的pygame中的模块
pygame.init()
# 初始化用于显示的窗口并设置窗口尺寸
screen = pygame.display.set_mode((800, 600))
# 设置当前窗口的标题
pygame.display.set_caption('大球吃小球')
# 定义变量来表示小球在屏幕上的位置
x, y = 50, 50
running = True
# 开启一个事件循环处理发生的事件
while running:
# 从消息队列中获取事件并对事件进行处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255))
pygame.draw.circle(screen, (255, 0, 0,), (x, y), 30, 0)
pygame.display.flip()
# 每隔50毫秒就改变小球的位置再刷新窗口
pygame.time.delay(50)
x, y = x + 5, y + 5
if __name__ == '__main__':
main()
碰撞检测
要求小球碰到墙壁会反弹,而2个球相撞,大球会吃掉小球。这里的碰撞检测直接检查2个小球的圆心距与半径和的关系就好,为了制造更多的小球,我们可以通过鼠标事件处理,在鼠标点击位置创建颜色、大小和移动速度不同的小球,这里就要使用面向对象的知识。
class Ball(object):
'''定义球'''
def __init__(self, center, color, radius, sx, sy):
'''初始化'''
self._center = center
self._color = color
self._radius = radius
self._sx = sx
self._sy = sy
@property
def center(self):
return self._center
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, radius):
self._radius = radius
def move(self):
'''移动'''
x, y = self._center[0], self._center[1]
x += self._sx
y += self._sy
self._center = (x, y)
if x + self._radius >= 800 or x - self._radius <= 0:
self._sx = -self._sx
if y + self._radius >= 600 or y - self._radius <= 0:
self._sy = -self._sy
def draw(self, screen):
'''画球'''
pygame.draw.circle(screen, self._color, self._center,self._radius, 0)#0表示实心,
def eat(self, other):
'''吃球'''
x, y = self._center[0], self._center[1]
x1, y1 = other.center[0], other.center[1]
line = ((x - x1) ** 2 + (y - y1) ** 2) ** 0.5
if line < (self._radius + other.radius):
if self._radius < other.radius:
other.radius += round(((3.14*self._radius**2*0.5)**0.5 / 3.14)**0.5)
self._radius = 0
elif self._radius > other.radius:
self._radius += round(((3.14*other.radius**2*0.5)**0.5 / 3.14)**0.5)
other.radius = 0
def refresh(screen, balls):
bg_color = (250, 250, 250)
screen.fill(bg_color)
for ball in balls:
ball.draw(screen)
pygame.display.flip()
def random_color():
red = randint(0, 255)
green = randint(0, 255)
blue = randint(0, 255)
return red, green, blue
事件处理
游戏中通过点击鼠标获得不同小球,因此通过事件对象的type属性来判定事件类型,利用pos属性来获取鼠标点击位置。
def main():
balls = []
pygame.init()
screen = pygame.display.set_mode([800, 600])
red_color = (255, 0, 0)
ball = Ball((100, 100), red_color, 30, 3, 3)
x, y = 200, 200
pygame.display.set_caption('大球吃小球')
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#处理鼠标事件,1表示左键
elif event.type == pygame.MOUSEBUTTONDOWN and \
event.button == 1:
center = event.pos
color = random_color()
radius = randrange(10, 50)
sx, sy = randint(-10, 10), randint(-10, 10)
ball = Ball(center, color, radius, sx, sy)
balls.append(ball)
refresh(screen, balls)
clock.tick(50)
for index, ball in enumerate(balls):
ball.move()
for i in range(index,len(balls)):
ball.eat(balls[i])
pygame.quit()#退出
if __name__ == '__main__':
main()
合并以上2段代码就能做出一个很简单的小游戏,pygame做2D游戏尚可,如果要做3D游戏,可以使用Panda3D。