pygame实现弹球游戏流程

 更新时间:2023年01月17日 08:56:06   作者:永远的麦田  
这篇文章主要介绍了pygame实现弹球游戏流程,弹球游戏(Pinball Pro)是安卓手机上排名第一的弹球游戏,真实再现了一直以来最经典的弹珠台游戏的玩法

一、事件

鼠标事件:

pygame.mouse.get_pos():获取鼠标当前点的坐标

pygame.mouse.get_pressed()[0]:获取鼠标左键是否为点击

二、复习碰撞精灵

1、首先是3个球在窗口上移动的最基础的版本:

import pygame, sys
class MyBall(pygame.sprite.Sprite):
    def __init__(self, point, speed):
        self.image = pygame.image.load("beach_ball.png")
        self.rect = self.image.get_rect()
        self.rect.left = point[0]
        self.rect.top = point[1]
        self.speed = speed
    def move(self):
        self.rect = self.rect.move(self.speed)
        screen.blit(self.image, self.rect)
pygame.init()
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
screen.fill([255, 255, 255])
balls = []
for i in range(3):
    ball = MyBall([180+i*180, 200], [8, 8])
    balls.append(ball)
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    screen.fill([255, 255, 255])
    for i in range(len(balls)):
        balls[i].move()
    pygame.display.flip()
    pygame.time.delay(20)

这三个球有一个缺点,一旦移动到窗口外,就移不回来了,因此,我们要在移动时,进行窗口边沿的判断

2、增加上下左右边框的判断

这样当球试图超出边界时,将对应方向的速度取反,使得重新回到窗口中来:

    def move(self):
        self.rect = self.rect.move(self.speed)
        if self.rect.right > width:  # 新增右边框判断
            self.speed[0] = -abs(self.speed[0])
        if self.rect.left < 0:  # 新增左边框判断
            self.speed[0] = abs(self.speed[0])
        if self.rect.bottom > height:  # 新增下边框判断
            self.speed[1] = -abs(self.speed[1])
        if self.rect.top < 0:  # 新增上边框判断
            self.speed[1] = abs(self.speed[1])
        screen.blit(self.image, self.rect)

进行到这一步,我们发现小球碰到一起时没有发生碰撞事件,即碰到一起的小球没有互相撤退,这时碰撞检测就使用起来了:

通过pygame.sprite.spritecollide我们可以检测当前小球与别的小球是否发生碰撞,如果发生碰撞,就将小球当前速度取反

3、碰撞处理

1)碰撞后的处理

    def crash(self, balls): 
        balls.remove(self)  # 将自身从碰撞组中删除
        if pygame.sprite.spritecollide(self, balls, False): # 检测碰撞发生,将自身的速度取反
            self.speed[0] = -self.speed[0]
            self.speed[1] = -self.speed[1]

2)针对小球两两组合进行碰撞处理:

    for i in range(len(balls)):
        for j in range(len(balls)):
            if i == j:
                continue
            balls[i].crash([balls[i], balls[j]])

这样小球互相碰到就会向相反的方向弹去。

三、画出球杆并击打小球

我们可以设想当小球停止下来后才好进行击打小球的动作,因此,可以针对小球做一个减速处理

然后当小球的x,y方向的速度都低于1时即认为小球静止了

1、减速逻辑

    def dec_speed(self):
        """减速"""
        self.speed[0] *= 0.995
        self.speed[1] *= 0.995

2、画出球杆

当小球静时后,我们需要画出一个球杆,画法为小球中心点到当前鼠标的位置画一条线段:

    def wait_hit(self):
        if abs(self.speed[0]) > 1 or abs(self.speed[1]) > 1:  # 在运动状态,退出,注意需要用abs,原因是速度有正和负
            pass
        else:
            pos = pygame.mouse.get_pos()    # 获取鼠标坐标
            pygame.draw.line(screen, [255, 0, 0], self.rect.center, pos, 5) # 画出小球到鼠标的红线
            if pygame.mouse.get_pressed()[0]:   # 按下鼠标左键
                self.speed[0] = 0.1 * (self.rect.center[0] - pos[0])    # 给小球初始速度
                self.speed[1] = 0.1 * (self.rect.center[1] - pos[1])

然后加上调用:

    for i in range(len(balls)):
        if i == 0:
            balls[i].wait_hit() # 只有0号小球静止时画出球杆
        balls[i].move()
        balls[i].dec_speed()    # 减速,使得小球最终静止下来

至此,一开始3个小球都会运动,运动过程中碰到一起也会发生碰撞反弹,随着时间推移,小球越来越慢,最终停下来,然后在0号球处画出了红线,点击鼠标左键,小球会向红线的相反方向移动,就是存在一个问题,当小球碰到静止的小球时,静止的小球不会动

3、碰撞发生后,当发现自身没有速度,使用对方的速度

    def crash(self, groups):
        groups.remove(self)  # 将自身从碰撞组中删除
        if pygame.sprite.spritecollide(self, groups, False):  # 检测碰撞发生,将自身的速度取反
            if abs(self.speed[0]) > 1:  # 运动状态用自身的反速度
                self.speed[0] = -self.speed[0]
            else:
                self.speed[0] = -groups[0].speed[0] # 静止状态,用对方的反速度
            if abs(self.speed[1]) > 1:
                self.speed[1] = -self.speed[1]
            else:
                self.speed[1] = -groups[0].speed[1]

至此一个简单的弹球游戏就结束了

附完整源代码:

import pygame, sys
class MyBall(pygame.sprite.Sprite):
    def __init__(self, point, speed):
        self.image = pygame.image.load("beach_ball.png")
        self.rect = self.image.get_rect()
        self.rect.left = point[0]
        self.rect.top = point[1]
        self.speed = speed
    def move(self):
        self.rect = self.rect.move(self.speed)
        if self.rect.right > width:  # 新增右边框判断
            self.speed[0] = -abs(self.speed[0])
        if self.rect.left < 0:  # 新增左边框判断
            self.speed[0] = abs(self.speed[0])
        if self.rect.bottom > height:  # 新增下边框判断
            self.speed[1] = -abs(self.speed[1])
        if self.rect.top < 0:  # 新增上边框判断
            self.speed[1] = abs(self.speed[1])
        screen.blit(self.image, self.rect)
    def crash(self, groups):
        groups.remove(self)  # 将自身从碰撞组中删除
        if pygame.sprite.spritecollide(self, groups, False):  # 检测碰撞发生,将自身的速度取反
            if abs(self.speed[0]) > 1:  # 运动状态用自身的反速度
                self.speed[0] = -self.speed[0]
            else:
                self.speed[0] = -groups[0].speed[0] # 静止状态,用对方的反速度
            if abs(self.speed[1]) > 1:
                self.speed[1] = -self.speed[1]
            else:
                self.speed[1] = -groups[0].speed[1]
    def dec_speed(self):
        """减速"""
        self.speed[0] *= 0.995
        self.speed[1] *= 0.995
    def wait_hit(self):
        if abs(self.speed[0]) > 1 or abs(self.speed[1]) > 1:  # 在运动状态,退出,注意需要用abs,原因是速度有正和负
            pass
        else:
            pos = pygame.mouse.get_pos()    # 获取鼠标坐标
            pygame.draw.line(screen, [255, 0, 0], self.rect.center, pos, 5) # 画出小球到鼠标的红线
            if pygame.mouse.get_pressed()[0]:   # 按下鼠标左键
                self.speed[0] = 0.1 * (self.rect.center[0] - pos[0])    # 给小球初始速度
                self.speed[1] = 0.1 * (self.rect.center[1] - pos[1])
pygame.init()
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
screen.fill([255, 255, 255])
balls = []
for i in range(3):
    ball = MyBall([180 + i * 180, 200], [8, 8])
    balls.append(ball)
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    screen.fill([255, 255, 255])
    for i in range(len(balls)):
        if i == 0:
            balls[i].wait_hit() # 只有0号小球静止时画出球杆
        balls[i].move()
        balls[i].dec_speed()    # 减速,使得小球最终静止下来
    for i in range(len(balls)):
        for j in range(len(balls)):
            if i == j:
                continue
            balls[i].crash([balls[i], balls[j]])
    pygame.display.flip()
    pygame.time.delay(10)

到此这篇关于pygame实现弹球游戏流程的文章就介绍到这了,更多相关pygame弹球游戏内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python中网络请求的12种方式

    Python中网络请求的12种方式

    今天,我们要用一行简洁的Python代码来揭开网络请求的神秘面纱,别看这行代码短小,它背后的魔法可强大了,能帮你轻松获取网页数据、实现API调用,甚至更多,无论你是想做数据分析、网站爬虫还是简单的信息查询,这12种方式都是你的得力助手,需要的朋友可以参考下
    2024-07-07
  • Python中用append()连接后多出一列Unnamed的解决

    Python中用append()连接后多出一列Unnamed的解决

    Python中用append()连接后多出一列Unnamed的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • python爬虫租房信息在地图上显示的方法

    python爬虫租房信息在地图上显示的方法

    这篇文章主要介绍了python爬虫租房信息在地图上显示的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • pandas筛选某列出现编码错误的解决方法

    pandas筛选某列出现编码错误的解决方法

    今天小编就为大家分享一篇pandas筛选某列出现编码错误的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-11-11
  • OpenCV实现机器人对物体进行移动跟随的方法实例

    OpenCV实现机器人对物体进行移动跟随的方法实例

    这篇文章主要给大家介绍了关于OpenCV实现机器人对物体进行移动跟随的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • pytest-fixture简介及其用法讲解

    pytest-fixture简介及其用法讲解

    这篇文章主要介绍了pytest-fixture及其用法,最基本的用法就是一个fixture作为一个测试用例的参数传入,然后就可以在该测试用例中使用该fixture,需要的朋友可以参考下
    2023-01-01
  • python关于os.walk函数查找windows文件方式

    python关于os.walk函数查找windows文件方式

    这篇文章主要介绍了python关于os.walk函数查找windows文件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • python实战之Scrapy框架爬虫爬取微博热搜

    python实战之Scrapy框架爬虫爬取微博热搜

    前面讲解了Scrapy中各个模块基本使用方法以及代理池、Cookies池。接下来我们以一个反爬比较强的网站新浪微博为例,来实现一下Scrapy的大规模爬取。
    2021-09-09
  • python多线程中获取函数返回值的三种方法

    python多线程中获取函数返回值的三种方法

    本文主要介绍了python多线程中获取函数返回值的三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Python报错TypeError: tuple indices must be integers or slices, not str的问题分析及解决方法

    Python报错TypeError: tuple indices must be

    在Python编程过程中,我们经常会遇到各种各样的报错信息,其中,“TypeError: tuple indices must be integers or slices, not str”这个报错,对于很多开发者来说,可能既熟悉又陌生,今天,我们就来深入探讨一下这个报错,看看它是如何产生的,以及如何快速有效地解决它
    2025-01-01

最新评论