用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。

python能做游戏 python用来做游戏_事件循环