Python+Pygame实现怀旧游戏飞机大战

 更新时间:2022年11月25日 10:28:20   作者:热爱科技的刘同学  
第一次见到飞机大战是在小学五年级下半学期的时候,这个游戏中可以说包含了几乎所有我目前可接触到的pygame知识。本文就来利用Pygame实现飞机大战游戏,需要的可以参考一下

前言

我第一次见到飞机大战是在我小学五年级下半学期的时候(2020年),这个游戏中可以说包含了几乎所有我目前可接触到的pygame知识。

一、python飞机大战

下面用一个简单的飞机大战游戏,串一下pygame基础知识。

1.1 音乐

这里列举一些常用函数,详细内容请到pygame官网查看。

  • pygame.mixer.music.load() :加载一个音乐文件用于播放;
  • pygame.mixer.music.play() :播放音乐;
  • pygame.mixer.music.rewind() :重新播放音乐;
  • pygame.mixer.music.stop() : 结束音乐播放;
  • pygame.mixer.music.pause() :暂停音乐播放;
  • pygame.mixer.music.unpause() :恢复音乐播放;
  • pygame.mixer.music.set_volume() :设置音量;
  • pygame.mixer.music.get_volume() : 获取音量。

1.2 精灵(spirte)

pygame场景里的动态物体都可视为精灵,如主角,敌人,子弹,可移动背景等等,换句话说,精灵就是一些动态图片,你要对这些图片进行一些交互操作,如移动,碰撞,爆炸等等。

Pygame提供了一个处理精灵的模块,也就是sprite(pygame.sprite)模块。我们使用该类Sprite来创建一个子类,真正达到处理精灵的目的,该子类提供了操作精灵的常用属性和方法,如下所示:

  • self.image:加载要显示的精灵,控制图片大小和填充颜色;
  • self.rect:精灵图片显示在哪个位置;
  • Sprite.update():刷新图,相应效果生效;
  • Sprite.add():添加精灵图到精灵组中(groups);
  • Sprite.remove():从精灵组中删除删除的精灵图;
  • Sprite.kill():删除精灵组中所有的精灵;
  • Sprite.alive():判断某个精灵是否属于精灵组。

当游戏中有大量的精灵时,操作它们将变得复杂,此时通过构建精灵容器(group 类)也就是精灵组来统一管理这些精灵。构建方法如下:

# 创建精灵组
group = pygame.sprite.Group()
# 向组内添加一个精灵
group.add(sprite1)

1.3 事件(键盘事件,鼠标事件)

键盘事件,这些会涉及到的日程安排操作,比如游戏批量的上下左右,或者人物中的前进、后继等操作,都需要键盘来配合执行。

一个事件的关键点,该事件可以进行连续的连续性控制。一个关键点、组合属性等以连续性的方式提供一系列事件,一系列常用的属性将通过一系列的连续性的事件进行排序。

  • K_BACKSPACE:退格键(Backspace);
  • K_TAB:制表键(Tab);
  • K_CLEAR:清除键;
  • K_RETURN:回车键(Enter);
  • K_PAUSE:暂停键(Pause);
  • K_ESCAPE:退出键(Escape);
  • K_SPACE:空格键(空格);
  • K_DELETE:删除键(delete);
  • K_UP向上:箭头(向上箭头);
  • K_DOWN:箭头(向下箭头);
  • K_RIGHT:向左(右箭头);
  • K_LEFT:向左箭头(左箭头)。
  • KMOD_ALT:同时按下Alt键;

鼠标事件,Pygame 提供了三个鼠标事件:

pygame.event.MOUSEMOTION:鼠标移动事件;

pygame.event.MOUSEBUTTONUP:鼠标键释放事件;

pygame.event.MOUSEBUTTONDOWN:鼠标键按下事件。

1.4 碰撞检测

pygame.sprite.collide_rect():精灵之间的矩形检测,即两个矩形区域是否有交汇,返回一个布尔值;

pygame.sprite.collide_circle():两个精灵之间的圆形检测,即圆形区域是否有交汇,返回一个布尔值;

pygame.sprite.collide_mask():两个精灵之间的像素蒙版检测,更为精准的一种检测方式;

pygame.sprite.spritecollide():精灵和精灵组之间的矩形碰撞检测,一个组内的所有精灵会逐一地对另外一个单个精灵进行碰撞检测,返回值是一个列表,包含了发生碰撞的所有精灵;

pygame.sprite.spritecollideany():精灵和精灵组之间的矩形碰撞检测,上述函数的变体,当发生碰撞时,返回组内的一个精灵,无碰撞发生时,返回 None;

pygame.sprite.groupcollide():检测在两个组之间发生碰撞的所有精灵,它返回值是一个字典,将第一组中发生碰撞的精灵作为键,第二个组中发生碰撞的精灵作为值。

1.5 更新

  • pygame.display.update()
  • pygame.display.flip()

flip函数将重新绘制整个屏幕对应的窗口。update函数仅仅重新绘制窗口中有变化的区域。如果仅仅是几个物体在移动,那么他只重绘其中移动的部分,没有变化的部分,并不进行重绘。

update比flip速度更快。因此在一般的游戏中,如果不是场景变化非常频繁的时候,建议使用update函数,而不是flip函数。

1.6 总结及源码

pygame可用函数有很多,但是真的不难,用文字讲述很麻烦,所以我只是列举了一些常用函数与方法,当你用到的时候记得去官网或者百度搜搜就可以了,把完整代码附在下面,仅供参考

# 导入两个库
import pygame
import random

# 常量,屏幕宽高
WIDTH, HEIGHT = 800, 600
# 初始化操作
pygame.init()
pygame.mixer.init()
# 创建游戏窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))

# 设置游戏标题
pygame.display.set_caption('飞机大战')

# 添加音乐
pygame.mixer.music.load('./sound/bgLoop.wav')
pygame.mixer.music.set_volume(0.5)  # 音量
pygame.mixer.music.play(-1, 0)

# 添加系统时钟,用于设置帧的刷新
FPS = 40
clock = pygame.time.Clock()

# 创建用户自定义事件,每隔2000毫秒触发一次事件,随机创建敌人
CREATE_ENEMY = pygame.USEREVENT
# 每隔2000毫秒,会传递一个信号
pygame.time.set_timer(CREATE_ENEMY, 2000)

# 对于精灵定义了主角,子弹,敌人,爆炸,可移动背景四个。
#class Hero(pygame.sprite.Sprite)
#class Bullet(pygame.sprite.Sprite)
#class Enemy(pygame.sprite.Sprite)
#class Explode(pygame.sprite.Sprite)
#class BackGround(pygame.sprite.Sprite)
# 主角
class Hero(pygame.sprite.Sprite):
    def __init__(self, speed):
        super().__init__()  # 调用父类的初始化方法
        self.image = pygame.image.load('./image/plane.png')
        self.rect = self.image.get_rect()
        # 对图片进行一些尺寸处理
        self.rect.width *= 0.5
        self.rect.height *= 0.5
        self.image = pygame.transform.scale(self.image, (self.rect.width, self.rect.height))
        # 主角初始化位置
        self.rect.x, self.rect.y = 0, 100
        self.speed = speed
        self.ready_to_fire = 0

    def update(self, *args):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_UP]:
            self.rect.y -= self.speed
        if keys[pygame.K_DOWN]:
            self.rect.y += self.speed
        if keys[pygame.K_LEFT]:
            self.rect.x -= self.speed
        if keys[pygame.K_RIGHT]:
            self.rect.x += self.speed
        if keys[pygame.K_SPACE]:
            if self.ready_to_fire == 0:
                self.fire()
            self.ready_to_fire += 1
            if self.ready_to_fire > 5:
                self.ready_to_fire = 0
        else:
            self.ready_to_fire = 0
        if self.rect.x < 0:
            self.rect.x = 0
        if self.rect.y < 0:
            self.rect.y = 0
        if self.rect.y > HEIGHT - self.rect.height:
            self.rect.y = HEIGHT - self.rect.height
    # 子弹发射
    def fire(self):
        bullet = Bullet(10)
        bullet.rect.x = self.rect.right
        bullet.rect.centery = self.rect.centery
        bullet_sprite.add(bullet)
        # 音效
        sound = pygame.mixer.Sound('./sound/laser.wav')
        sound.play()


class Bullet(pygame.sprite.Sprite):
    def __init__(self, speed):
        super().__init__()
        self.image = pygame.image.load('./image/bullet.png')
        self.rect = self.image.get_rect()
        self.speed = speed

    def update(self, *args):
        self.rect.x += self.speed
        if self.rect.x > WIDTH:
            self.kill()


class Enemy(pygame.sprite.Sprite):
    def __init__(self, speed):
        super().__init__()
        self.image = pygame.image.load('./image/enemy1.png')
        self.rect = self.image.get_rect()
        self.rect.x = 800
        self.rect.y = random.randint(0, HEIGHT)
        self.speed = speed

    def update(self, *args):
        self.rect.x -= self.speed
        if self.rect.right < 0:
            self.kill()


class Explode(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.images = [pygame.image.load('./image/explode' + str(i) + '.png') for i in range(1, 4)]
        self.image_index = 0
        self.image = self.images[self.image_index]
        self.rect = self.image.get_rect()
        self.readt_to_change = 0
        sound = pygame.mixer.Sound('./sound/enemyExplode.wav')
        sound.play()

    def update(self, *args):
        if self.image_index < 2:
            self.readt_to_change += 1
            if self.readt_to_change % 4 == 0:
                self.image_index += 1
                self.image = self.images[self.image_index]
        else:
            self.kill()


class BackGround(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load('./image/background.jpg')
        self.rect = self.image.get_rect()
        self.ready_to_move = 0

    def update(self, *args):
        self.rect.x -= 3
        if self.rect.right <= 0:
            self.rect.x = self.rect.width


# 初始化精灵组
bg_sprite = pygame.sprite.Group()
hero_sprite = pygame.sprite.Group()
enemy_sprite = pygame.sprite.Group()
bullet_sprite = pygame.sprite.Group()
explode_sprite = pygame.sprite.Group()

# 定义人物

hero1 = Hero(4)
hero_sprite.add(hero1)

enemy1 = Enemy(5)
enemy2 = Enemy(7)

bg1 = BackGround()
bg2 = BackGround()
bg2.rect.x = bg2.rect.width
bg_sprite.add(bg1, bg2)

# 保持游戏运行状态(游戏循环)
while True:
    # ===========游戏帧的刷新===========
    clock.tick(FPS)

    # 检测事件
    for event in pygame.event.get():
        # 检测关闭按钮被点击的事件
        if event.type == pygame.QUIT:
            # 退出
            pygame.quit()
            exit()
        if event.type == CREATE_ENEMY:
            enemy_sprite.add(Enemy(random.randint(1, 7)))

    # 碰撞检测,返回字典,得到二者信息
    collision = pygame.sprite.groupcollide(enemy_sprite, bullet_sprite, True, True)
    for enemy in collision.keys():
        explode = Explode()
        explode.rect = enemy.rect
        explode_sprite.add(explode)

    # screen.fill((0,0,0))
    for group in [bg_sprite, hero_sprite, enemy_sprite, bullet_sprite, explode_sprite]:
        group.update()
        group.draw(screen)
    pygame.display.update()

到此这篇关于Python+Pygame实现怀旧游戏飞机大战的文章就介绍到这了,更多相关Python Pygame飞机大战内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python 异步之如何启动获取事件循环

    Python 异步之如何启动获取事件循环

    这篇文章主要为大家介绍了Python 异步之如何启动获取事件循环示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Python存储与读写二进制文件的示例代码

    Python存储与读写二进制文件的示例代码

    本文介绍了如何在Python中使用Numpy将数组转存为二进制文件,并通过内存映射的方式读取,提供了一个高效处理大量数据的方法,示例代码展示了完整的存储和读取过程,解释了页大小和数据存储的关系,适用于需要高性能计算和数据压缩的场景,感兴趣的朋友跟随小编一起看看吧
    2024-09-09
  • Python常见反爬虫机制解决方案

    Python常见反爬虫机制解决方案

    这篇文章主要介绍了Python常见反爬虫机制解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • Python中将图像转换为PDF的方法实现

    Python中将图像转换为PDF的方法实现

    本文主要介绍了Python中将图像转换为PDF的方法实现,主要使用img2pdf和PyPDF2软件包,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • python opencv 图像处理之图像算数运算及修改颜色空间

    python opencv 图像处理之图像算数运算及修改颜色空间

    这篇文章主要介绍了python opencv 图像处理之图像算数运算及修改颜色空间,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-08-08
  • Python中 Global和Nonlocal的用法详解

    Python中 Global和Nonlocal的用法详解

    global关键字用来在函数或其他局部作用域中使用全局变量, nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量。这篇文章主要介绍了Python中 Global和Nonlocal的用法,需要的朋友可以参考下
    2020-01-01
  • 如何利用Python快速统计文本的行数

    如何利用Python快速统计文本的行数

    这篇文章主要介绍了如何利用Python快速统计文本的行数,要快速统计一个文本文件中的行数,其实就是要统计这个文本文件中换行符的个数,下面我们就一起进入文章看看具体的操作过程吧
    2021-12-12
  • python3 实现函数写文件路径的正确方法

    python3 实现函数写文件路径的正确方法

    今天小编就为大家分享一篇python3 实现函数写文件路径的正确方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • 详解Python排序算法的实现(冒泡,选择,插入,快速)

    详解Python排序算法的实现(冒泡,选择,插入,快速)

    这篇文章主要为大家介绍了Python中常见的四种排序算法的实现:冒泡排序、选择排序、插入排序和快速排序,文中通过图片详细讲解了它们实现的原理与代码,需要的可以参考一下
    2022-04-04
  • Python 发送邮件方法总结

    Python 发送邮件方法总结

    这篇文章主要介绍了Python 发送邮件的几种方法,帮助大家更好的理解和学习Python,感兴趣的朋友可以了解下
    2020-08-08

最新评论