Python编写微信打飞机小游戏(四)

  之前的工作已经基本上将我方飞机的图形显示工作做的差不多了,这篇博客中我们将开始添加敌方飞机——小型敌机、中型敌机(直升机)和大型敌机(坦克)。新建一个enemy.py文件,导入pygame和random模块,开始编写吧(还是要注意文件编码问题,以后就不再啰嗦了)。

  敌方飞机类与我方飞机模块有一定的相似性,但不会左右移动,不会发射子弹等等。小型敌机是敌方飞机中最基本的类型,一击毙命,没有血量、没有出场音效。中型敌机有一定血量,损毁时附带特殊音效。大型敌机血量最多,出场和损毁时都有特殊音效,游戏中中型敌机和大型敌机都将显示血槽。

  1、小型敌机类

  和我方飞机一样,小型敌机类也是继承自Pygame的精灵类,在初始化过程中需要先调用基类的初始化函数,在加载飞机图像、获取飞机图像尺寸,设置小飞机的移动速度等等:

class SmallEnemy(pygame.sprite.Sprite):
    def __init__(self, bg_size):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("image/enemy1.png")  # 加载敌方飞机图片
        self.rect = self.image.get_rect()  # 获得敌方飞机的位置
        self.width, self.height = bg_size[0], bg_size[1]  # 本地化背景图片位置
        self.speed = 2  # 设置敌机的速度

  在初始化小飞机的位置时,需要稍微做一点工作:

        self.rect.left, self.rect.top = (randint(0, self.width - self.rect.width),  # 定义敌机出现的位置
                                         randint(-5 * self.rect.height, -5)  # 保证敌机不会在程序已开始就立即出现
                                         )

  小飞机在初始化时需要随机指定其位置,其x左边(横向宽度)在(0,width - rect.width)之间,保证飞机能够在整个屏幕的X轴的任何位置出现并且不会越界。其top(纵向高度)在(-5 * rect.height, -5)之间,这里之所以最大值设置为负数(-5),是为了保证程序开始运行时敌机不会立即出现,给用户以反应时间。这里还有一个小细节需要注意,就是如果Python的代码太长,在换行时建议使用小括号来指定范围,不推荐只使用“\”来连接各个行。

  2、move()和reset()函数

  在定义完小型飞机的数据结构之后,需要定义其移动操作move()函数(成员函数)。敌机的移动函数功能相对单一,只是在屏幕上以固定速度向下移动:

    def move(self):  # 定义敌机的移动函数
        if self.rect.top < self.height:
            self.rect.top += self.speed
        else:
            self.reset()

  这里即可体现出speed参数的作用。当然还需要编写一个reset()成员函数来将已经移动出屏幕的敌机进行重置:

    def reset(self):  # 当敌机向下移动出屏幕时
        self.rect.left, self.rect.top = (randint(0, self.width - self.rect.width),
                                         randint(-5 * self.rect.height, 0)
                                         )

  3、中型敌机

  中型敌机结构与小型敌机类此,区别在于中型敌机的图标、血量以及损毁音效等方面,其中敌机血量以及损毁音效的添加我们在之后的博文中再加以介绍:

class MidEnemy(pygame.sprite.Sprite):
    def __init__(self, bg_size):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("image/enemy2.png")  # 加载敌方飞机图片
        self.rect = self.image.get_rect()  # 获得敌方飞机的位置
        self.width, self.height = bg_size[0], bg_size[1]  # 本地化背景图片位置
        self.speed = 1  # 设置敌机的速度,应该比小型敌机速度稍慢
        self.rect.left, self.rect.top = (randint(0, self.width - self.rect.width),  # 定义敌机出现的位置
                                         randint(-10 * self.rect.height, -self.rect.height)
                                         )

    def move(self):  # 定义敌机的移动函数
        if self.rect.top < self.height:
            self.rect.top += self.speed
        else:
            self.reset()

    def reset(self):  # 当敌机向下移动出屏幕时
        self.rect.left, self.rect.top = (randint(0, self.width - self.rect.width),  # 定义敌机出现的位置
                                         randint(-10 * self.rect.height, -self.rect.height)  # 保证一开始不会有中型敌机出现
                                         )

  4、大型敌机

  大型敌机作为boss级别的存在,其不仅仅具有高血量、特殊出场音效以及损毁音效,其在移动过程中也存在图片切换的特效(与我方飞机尾部喷气特效类似),因此在加载图片时同样需要加载两张图片,以便在主程序显示的过程中进行切换:

class BigEnemy(pygame.sprite.Sprite):
    def __init__(self, bg_size):
        pygame.sprite.Sprite.__init__(self)
        self.image1 = pygame.image.load("image/enemy3_n1.png")  # 加载敌方飞机图片,其中大型飞机有帧切换的特效
        self.image2 = pygame.image.load("image/enemy3_n2.png")
        self.rect = self.image1.get_rect()  # 获得敌方飞机的位置
        self.width, self.height = bg_size[0], bg_size[1]  # 本地化背景图片位置
        self.speed = 2  # 设置敌机的速度
        self.rect.left, self.rect.top = (randint(0, self.width - self.rect.width),  # 定义敌机出现的位置
                                         randint(-15 * self.rect.height, -5 * self.rect.height)
                                         )

    def move(self):  # 定义敌机的移动函数
        if self.rect.top < self.height:
            self.rect.top += self.speed
        else:
            self.reset()

    def reset(self):  # 当敌机向下移动出屏幕时
        self.rect.left, self.rect.top = (randint(0, self.width - self.rect.width),  # 定义敌机出现的位置
                                         randint(-15 * self.rect.height, -5 * self.rect.height)
                                         )

  5、敌方飞机实例化控制函数

  在完成敌机模块enemy.py的构建之后,我们开始在主程序中将敌机实例化并显示在屏幕上,首先在程序开始时导入已经编写好的模块:

import enemy

  注意我们的打飞机程序在设计时是设计成有难度分级的,玩家得分越多、需要挑战的难度等级就越高;难度等级越高,所出现的敌机数量就越多,可见敌机的实例数量是随时可能发生变化的,直接实例化具体数量的敌机显然不满足要求,在此我们通过编写一个实例化控制函数来实现敌机对象的动态添加,以小型敌机添加函数为例:

# ====================敌方飞机生成控制函数====================
def add_small_enemies(group1, group2, num):
    for i in range(num):
        e1 = enemy.SmallEnemy(bg_size)
        group1.add(e1)
        group2.add(e1)

  这个函数结构简单,通俗易懂,即将指定个敌机对象添加到精灵组(sprite.group)中。参数group1、group2是两个精灵组类型的形参,用以存储多个精灵对象(敌机)。需要注意的一点是group既然是特定的精灵组结构体,在向其内部添加精灵对象时需要调用其对应的成员函数add(),不能使用列表添加函数append()。至于for循环这些python的基础知识这里就不再赘述

  以此类推,编写中型敌机和大型敌机的实例化控制函数:

def add_mid_enemies(group1, group2, num):
    for i in range(num):
        e2 = enemy.MidEnemy(bg_size)
        group1.add(e2)
        group2.add(e2)

def add_big_enemies(group1, group2, num):
    for i in range(num):
        e3 = enemy.BigEnemy(bg_size)
        group1.add(e3)
        group2.add(e3)

  友情提示,所有函数都应该在第一次使用之前进行定义,也就是说以上三个函数都应该定义在main()函数之前,以保证在main()函数中顺利调用。

  6、敌机实例化

  第一步,在main函数中,在进入while循环之前,调用enemy.py模块,向精灵组中添加敌机精灵对象:

    # ====================实例化敌方飞机====================
    enemies = pygame.sprite.Group()  # 生成敌方飞机组
    small_enemies = pygame.sprite.Group()   # 敌方小型飞机组
    add_small_enemies(small_enemies, enemies, 1)  # 生成若干敌方小型飞机
    mid_enemies = pygame.sprite.Group()   # 敌方小型飞机组
    add_mid_enemies(mid_enemies, enemies, 1)  # 生成若干敌方中型飞机
    big_enemies = pygame.sprite.Group()   # 敌方小型飞机组
    add_big_enemies(big_enemies, enemies, 1)  # 生成若干敌方大型飞机

  先调用pygame.sprite.Group()生成精灵组,这里需要生成两种精灵组,一种精灵组用以存储所有敌机精灵(不区分小型中型大型),另一种则是针对不同型号敌机创建不同的精灵组来存储。之所以这样做,是因为不同类型的敌机之前既有共同属性,又有各自的特殊属性,在处理中更为方便。精灵组生成之后调用对应的生成控制函数来向其中添加敌机精灵对象即可(这里先将添加数量均设置为1)。

  第二步,显示敌机。绘制小型敌机和中型敌机的方法类似,即将当前精灵组中的所有对象通过for()循环进行索引,并逐个blit()到屏幕对象中,并激活其内部的移动函数使其移动,注意这部分代码应该位于while循环之内:

            for each in small_enemies:  # 绘制小型敌机并自动移动
                each.move()
                screen.blit(each.image, each.rect)
            for each in mid_enemies:
                if each.active:
                each.move()
                screen.blit(each.image, each.rect)

  大型敌机在绘制时需要添加图片切换的特效,参照之前我方飞机的尾部喷气特效的实现方法:

            for each in big_enemies:  # 绘制大型敌机并自动移动
                each.move()
                if switch_image:
                    screen.blit(each.image1, each.rect)  # 绘制大型敌机的两种不同的形式
                else:
                    screen.blit(each.image2, each.rect)
         if each.rect.bottom == -50:             big_enemy_flying_sound.play(-1) 
 

  这里当大型敌机即将出场时rect.bottom == -50,需要实现播放出场音效,并且是循环播放(参数设置为-1),如上所示。OK,运行代码,就会看到敌方飞机陆续从屏幕上飞过,不过这里应该有一个bug,就是大型敌机出场时不能顺利播放出场音效,这涉及Pygame的一个声道阻塞的问题,我们将在后续的博文中进行总结,今天就先进行到这里吧。

时间: 2024-10-10 06:32:32

Python编写微信打飞机小游戏(四)的相关文章

Python编写微信打飞机小游戏(十一)

在这篇博文中,我们准备为打飞机小游戏添加一个暂停的功能,即用户在游戏过程中随时可以通过单击屏幕右上方的一个暂停按钮来暂停和恢复游戏.这个功能看似比较简单,但其中涉及了鼠标操作.图片切换.代码结构的重置等等,接下来我们一一进行介绍. 1.加载暂停按钮图标 在image文件夹下一共有四张暂停按钮的图片,分别为深色和浅色两组,首先在main()函数中加载相关图片资源并初始化暂停/开始标志位: paused = False # 标志是否暂停游戏 pause_nor_image = pygame.imag

Python编写微信打飞机小游戏(一)

最近开始学习Python语言,发现Python有一个神奇的Pygame模块,在编写小游戏时显得非常方便,于是参照教学视频编写了一个微信打飞机的小游戏,网上有很多相关的博客,但都不是很详细,大都是直接贴代码,于是决定沉下心来把编写程序的过程记录下来,与大家分享. 首先声明一点,这篇博客完全参照了小甲鱼的<零基础入门学习Python>教学视频,为了尊重原创,特将原作者的视频地址公布如下:<零基础入门学习Python> Python编译器和Pygame模块的安装网上的教程很多,这里不再赘

Python编写微信打飞机小游戏(八)

现在飞机已经能够带着血条突突突飞下来让玩家虐,于是我们给用户一点打飞机的成就感——计分系统以及难度递增机制. 1.计分系统 首先,我们在main()函数中添加全局变量(score)并初始化为零用以统计当前用户的打飞机得分: score = 0 # 统计用户得分 接下来只需要在敌机销毁时对score进行累加就可以了,我们在这里先给敌机标个价:小型敌机一架值500分,中型敌机一架值2000分,大型敌机一架值6000分,然后在敌机损毁时根据敌机类型选择加多少分,对于小型敌机: for each in

Python编写微信打飞机小游戏(三)

通过之前的任务,我们已经能够实现小飞机在屏幕上自由移动了,这次博客的任务是是的我们的小飞机看起来更有灵性——尾部喷气特效的绘制. 1.帧率 说道帧率,玩游戏的人可能并不陌生.如果你是一个lol的玩家,那你肯定最关心两件事,一是帧率(FPS),二是延迟.延迟取决于网络性能,而帧率则取决于电脑的硬件配置,自然是帧率越高游戏画面就越流畅.帧率,简单老理解就是游戏在一秒钟进行多少次画面刷新.Pygame支持的帧率大约是从30到120,为了避免游戏程序因为电脑性能的差异出现太大差别,我们在此为程序指定一个

Python编写微信打飞机小游戏(七)

这边博客我们为大型敌机和中型敌机设置血量并以血槽的形式显示出来,同时解决之前遇到的声道阻塞的BUG(声道阻塞的问题详见之前的博文). 1.为敌机添加表示血量的成员变量 所谓敌机血量,就是指敌机在挂掉之前能够挨几发子弹,这是敌机对象的一个成员属性,因此我们在中型敌机(MidEnemy)和大型敌机(BigEnemy)中添加energy成员变量: class MidEnemy(pygame.sprite.Sprite): energy = 5 def __init__(self, bg_size):

10分钟教你用Python做个打飞机小游戏超详细教程

更多精彩尽在微信公众号[程序猿声] 我知道你们一定想先看效果如何 00 目录 整体框架 开始之前-精灵类Sprite 子弹类class Bullet 玩家飞机类class Player 敌机类class Enemy 游戏主体循环以及帧率设置 让子弹飞 刷出敌机 打怪 把飞机敌机子弹都画出来 处理键盘事件 分数显示 和 GameOver 最终代码 01 前言 这次还是用python的pygame库来做的游戏.关于这个库的内容,读者可以上网了解一下.本文只讲解用到的知识.代码参考自网上,自己也做了一

C语言射击类打飞机小游戏

使用c语言编写一个打飞机小游戏,使用键盘按键来进行游戏,击中敌机可获得积分,被敌机撞中死亡一次,每次游戏有3次机会. 在网上查询资料并且和同学讨论之后,对原来的代码有了一些改进, 改进:增加了颜色函数,在你所需要改变窗口颜色的位置调用函数 system("color xx") xx分别指的是背景颜色和文字(前景)颜色.x为一位16进制数,即1-f都可以使用.可以随意组合.增加了终止函数,使游戏在死亡三次后自动结束游戏,并且可以选择是否重新开始游戏:另外增添了设置函数,使得可以对游戏进行

python编写微信公众号首图思路详解

前言 之前一直在美图秀秀调整自己的微信公众号首图,效果也不尽如人意,老是调来调去,最后发出来的图片被裁剪了一大部分,丢失部分关键信息,十分恼火,于是想着用python写一个程序,把微信公众号首图的模式固定下来,方便以后写公众号. 思路 根据微信公众号首图要求,可以上传一个不超过5M的图片,且图片尺寸要是2.35:1的尺寸,换算成像素是900:383,有了这些参数就可以做文章了,这里有两种思路 把今天推文的标题(文字)用图片展示出来,使得文字排列错落有致,简单粗暴,而又不失美感,这里可以利用mat

原生js打飞机小游戏

最近为了巩固一下原生的知识,然后拿了一个js小游戏来入手.主要也是为了学习和练手. js代码如下: 1 window.onload = function(){ 2 var oBtn = document.getElementById('gameBtn'); 3 oBtn.onclick = function(){ 4 this.style.display = 'none'; 5 Game.init('div1');//把父级传进去 6 }; 7 }; 8 //创建Game单体 9 10 var