|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
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.补给(超级子弹和全屏炸弹)
|
|