鱼C论坛

 找回密码
 立即注册
查看: 4167|回复: 0

[技术交流] 飞机大战的菜鸟学习笔记

[复制链接]
发表于 2018-2-26 16:52:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 fanghhh 于 2018-2-26 16:52 编辑

刚看完飞机大战,想看看自己能不能总结一下思路
有错误希望大家可以纠正

设计飞机游戏的要求:
1.我方飞机:有3条命,能发射子弹(1或2颗),通过按键能上下左右移动
  敌机:有大中小3种类型的敌机,大中型敌机有血条(生命值大于20%显示绿色,否则显示红色)
  补给:分全屏炸弹和超级子弹两种
  子弹:子弹击中敌机会摧毁敌机
以上当出现各种事件时会出现各种音效,当飞机被摧毁时会出现摧毁画面
加上一个main()函数我们一共要写5个函数,因为他们具有相同属性(面向对象的好处)

我是根据小甲鱼的视频来总结

编写代码的思路(从简单开始写起)
1 背景和游戏音效                        (完成后能出现游戏界面)
2 我方飞机,并使其能上下左右移动(完成后能出现一辆我方飞机)
在myplane函数里飞机上下左右移动需要写4个方法
在main函数里实例化出我方飞机并绘制出来且有突突突的飞行效果,并通过键盘响应调用不同方法
难点一:如何使飞机有突突突的视觉感受
思路: 加载两张飞机图片,然后不断切换,并延迟图片切换(5帧切换一次)
实现:
switch_image = True #定义一个变量switch_image用来切换飞机图片
delay = 100            #用于延迟
...
while running:
...
        #绘制我方飞机
        if switch_image:
                描绘图片1
        else:
                描绘图片2

        if not(delay % 5):    #当每次delay能整除5时才切换图片
                switch_image = not switch_image
        delay -= 1                    #每次delay-1
        if not delay:            #当delay=0时,使delay=100重新往下减
                delay = 100

3 创建敌机
在enemy函数中大中小型敌机分别写成3个类,比如小型敌机在-5个屏幕处到屏幕上方随机生成并垂直下降飞行
(注意:在pygame中游戏界面的左上顶点为坐标原点,左下顶点为正方向)
并给敌机类分别写上move方法和reset方法
在main函数中写添加大中小敌机的3个方法,每种类型的敌机放在一个group中,
然后把所有类型的敌机再放在一个group中,一边后面检测碰撞方便编程

难点一:不理解为什么当敌机飞过屏幕底面的时候为什么要重置他,直接放着不管不就行了吗
def move(self):
        if self.rect.top <self.height:
            self.rect.top += self .speed
        else:
            self.reset()
我后来发现不要的话小飞机就一直会变得越来越少,所以一过屏幕下方就要重置是游戏规则决定
如果不这么做得话小飞机的数量就会减少

难点二 :为什么要写reset()
因为生成敌机是批量的生成,以小型敌机为例,最开始直接生成15架add_small_enemies(small_enemies,enemies,15)
然后就不会再生成了,不写reset的话小飞机的数量会减少,而且当敌方飞机被击中时也要reset,摧毁图片才不会一直在显示

难点三 :为什么先划大型敌机再划中型敌机再画小型敌机
因为如果先画小型敌机,有可能大型敌机出现在小型敌机上面,然后影响游戏体验

难点四 :生成敌机需要写3个部分的内容,以小型敌机举例
(1) 先在main函数写添加小型敌机的方法
        def add_small_enemies(group1,group2,num):
              for i in range(num):
                    e1 = enemy.SmallEnemy(bg_size)       #实例化出飞机
                    group1.add(e1)
                    group2.add(e1)

(2) 用前面的方法在主函数中生成敌方小型飞机
        small_enemies = pygame.sprite.Group()
        add_small_enemies(small_enemies,enemies,15)

(3) 在主函数中绘制小型敌机
          for each in small_enemies:
                if each.active:
                    each.move()
                    screen.blit(each.image,each.rect)
                else:
                      ...

如果让我想可能会直接先把添加敌机的方法直接放在主函数中,这样的话主函数看起来就会非常乱
但是我感觉那些绘制飞机的内容是不是也可以写在外面,这样看起来不是更简洁吗?
有没有人告诉我这个想法是不是对的?


4.飞机摧毁时出现摧毁图片,这时需要定义一个变量active来判断飞机是否活着
检测我方飞机是否被撞

难点一:如何显示摧毁图片(由多张图片切换切成且只播放一轮),以大型敌机为例
(1) 首先定义中弹图片索引,因为每种类型的敌机摧毁图片的数量不同,所以各自有各自的索引变量
        e3_destroy_index =0
(2)  接着实现摧毁图片的播放           
                 if not(delay % 3):                                   #每隔3帧播放一张图片,才能使肉眼能开清楚
                        if e3_destroy_index == 0:
                            enemy3_down_sound.play()          #这样子写的好处是能使飞机摧毁的时候只播放一次音效  
                        screen.blit(each.destroy_images[e3_destroy_index],each.rect)
                        e3_destroy_index = (e3_destroy_index+1) % 6  #6张摧毁图片所以%6
                        if e3_destroy_index == 0:
                            enemy3_fly_sound.stop()
                            each.reset()

难点二:为了实现更好的碰撞检测(去除透明部分),需要用到mask模块

5.定义子弹,给中大型敌机添加血槽,此时需要定义一个变量energe去表示血量
判断子弹是否击中敌机,此时需要定义一个变量hit去表示是否击中

难点一:血槽终点如何表示(飞机左边位置+总长度乘以比例)
比例:energy_remain = each.energy/enemy.BigEnemy.energy
终点位置:each.rect.left+each.rect.width*energy_remain

6. 击中敌机可以得分,添加暂停开始按钮,分5个难度(定义一个变量level去表示难度)

7.添加全屏炸弹(一触发所有敌机bottom>0的全部active=False)

8.补给(超级子弹和全屏炸弹)

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-10-22 13:47

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表