不知道大家有没有打过飞机,喜不喜欢打飞机。当我第一次接触这个东西的时候,我的内心是被震撼到的。第一次接触打飞机的时候作者本人是身心愉悦的,因为周边的朋友都在打飞机, 每次都会下意识彼此较量一下,看谁打得更好。打飞机也是需要有一定的技巧的,熟练的朋友一把能打上半个小时,生疏的则三五分钟就败下阵来。那么怎么实现自己的打飞机游戏?下面就跟大家一起来动手实现打飞机游戏。
# |1 a+ _7 [# }一.游戏设定3 k1 V! D) H7 F" t5 e
游戏界面如下图所示:' s# z+ i% k0 n* g8 j- R9 y* X
: ~7 H, j, {6 C G+ V2 t游戏的基本设定:
; n. H! u! t) u* H- \- H- 敌方共有大中小3款飞机,分为高中低三种速度;
- 子弹的射程并非全屏,而大概是屏幕长度的80%;
- 消灭小飞机需要1发子弹,中飞机需要8发,大飞机需要20发子弹;
- 每消灭一架小飞机得1000分,中飞机6000分,大飞机10000分;
- 每隔30秒有一个随机的道具补给,分为两种道具,全屏炸弹和双倍子弹;
- 全屏炸弹最多只能存放3枚,双倍子弹可以维持18秒钟的效果;
- 游戏将根据分数来逐步提高难度,难度的提高表现为飞机数量的增多以及速度的加快。
7 Z9 A* u8 D. d5 | 另外还对游戏做了一些改进,比如为中飞机和大飞机增加了血槽的显示,这样玩家可以直观地知道敌机快被消灭了没有;我方有三次机会,每次被敌人消灭,新诞生的飞机会有3秒钟的安全期;游戏结束后会显示历史最高分数。
0 h* B$ U: b4 J* Z. Y" f 这个游戏加上基本的注释代码量在800行左右,代码看上去比较多,多打代码少动脑。所以大家不要怕,越是多的代码,逻辑就越容易看得清楚,就越好学习。好,那让我们从无到有,从简单到复杂来一起打造这个游戏吧!
i+ @' `( i! T& c! l4 o二.我方飞机. |4 Q" ?3 y1 [9 q2 b5 q4 p
首先创建一个myplane. py模块来定义我方飞机:
. m7 ]2 F4 ?+ [
-
- import pygame
-
- class MyPlane(pygame.sprite.Sprite):
- def __init__(self, bg_size):
- pygame.sprite.Sprite.__init__(self)
-
- self.image1 = pygame.image.load("images/me1.png").convert_alpha()
- self.image2 = pygame.image.load("images/me2.png").convert_alpha()
- self.destroy_images = []
- self.destroy_images.extend([\
- pygame.image.load("images/me_destroy_1.png").convert_alpha(), \
- pygame.image.load("images/me_destroy_2.png").convert_alpha(), \
- pygame.image.load("images/me_destroy_3.png").convert_alpha(), \
- pygame.image.load("images/me_destroy_4.png").convert_alpha() \
- ])
- self.rect = self.image1.get_rect()
- self.width, self.height = bg_size[0], bg_size[1]
- self.rect.left, self.rect.top = \
- (self.width - self.rect.width) // 2, \
- self.height - self.rect.height - 60
- self.speed = 10
- self.active = True
- self.invincible = False
- self.mask = pygame.mask.from_surface(self.image1)
-
- # 分别定义moveUp()、moveDown()、moveLeft()和moveRight()控制我方飞机上、下、左、右移动:
-
- def moveUp(self):
- if self.rect.top > 0:
- self.rect.top -= self.speed
- else:
- self.rect.top = 0
-
- def moveDown(self):
- if self.rect.bottom < self.height - 60:
- self.rect.top += self.speed
- else:
- self.rect.bottom = self.height - 60
-
- def moveLeft(self):
- if self.rect.left > 0:
- self.rect.left -= self.speed
- else:
- self.rect.left = 0
-
- def moveRight(self):
- if self.rect.right < self.width:
- self.rect.left += self.speed
- else:
- self.rect.right = self.width
-
- def reset(self):
- self.rect.left, self.rect.top = \
- (self.width - self.rect.width) // 2, \
- self.height - self.rect.height - 60
- self.active = True
- self.invincible = True
三.敌方飞机+ O% E+ Z$ X/ ?% A; Y ^1 u
既然英雄已经有了,那现在就是需要创造敌人的时候。敌机分为小、中、大三个尺寸,它们的速度依次是快、中、慢,在游戏界面的上方位置创造位置随机的敌机,可以让它们不在同一排出现。将敌机的定义写在enemy. py模块中:7 [0 W& U7 s# f% r1 h. g4 H) {
- import pygame
- from random import *
- class SmallEnemy(pygame.sprite.Sprite):
- def __init__(self, bg_size):
- pygame.sprite.Sprite.__init__(self)
-
- self.image = pygame.image.load("images/enemy1.png").convert_alpha()
- self.destroy_images = []
- self.destroy_images.extend([ \
- pygame.image.load("images/enemy1_down1.png").convert_alpha(), \
- pygame.image.load("images/enemy1_down2.png").convert_alpha(), \
- pygame.image.load("images/enemy1_down3.png").convert_alpha(), \
- pygame.image.load("images/enemy1_down4.png").convert_alpha() \
- ])
- self.rect = self.image.get_rect()
- self.width, self.height = bg_size[0], bg_size[1]
- self.speed = 2
- self.active = True
- self.rect.left, self.rect.top = \
- randint(0, self.width - self.rect.width), \
- randint(-5 * self.height, 0)
- self.mask = pygame.mask.from_surface(self.image)
-
- def move(self):
- if self.rect.top < self.height:
- self.rect.top += self.speed
- else:
- self.reset()
-
- def reset(self):
- self.active = True
- self.rect.left, self.rect.top = \
- randint(0, self.width - self.rect.width), \
- randint(-5 * self.height, 0)
-
-
- class MidEnemy(pygame.sprite.Sprite):
- energy = 8
-
- def __init__(self, bg_size):
- pygame.sprite.Sprite.__init__(self)
-
- self.image = pygame.image.load("images/enemy2.png").convert_alpha()
- self.image_hit = pygame.image.load("images/enemy2_hit.png").convert_alpha()
- self.destroy_images = []
- self.destroy_images.extend([ \
- pygame.image.load("images/enemy2_down1.png").convert_alpha(), \
- pygame.image.load("images/enemy2_down2.png").convert_alpha(), \
- pygame.image.load("images/enemy2_down3.png").convert_alpha(), \
- pygame.image.load("images/enemy2_down4.png").convert_alpha() \
- ])
- self.rect = self.image.get_rect()
- self.width, self.height = bg_size[0], bg_size[1]
- self.speed = 1
- self.active = True
- self.rect.left, self.rect.top = \
- randint(0, self.width - self.rect.width), \
- randint(-10 * self.height, -self.height)
- self.mask = pygame.mask.from_surface(self.image)
- self.energy = MidEnemy.energy
- self.hit = False
-
- def move(self):
- if self.rect.top < self.height:
- self.rect.top += self.speed
- else:
- self.reset()
-
- def reset(self):
- self.active = True
- self.energy = MidEnemy.energy
- self.rect.left, self.rect.top = \
- randint(0, self.width - self.rect.width), \
- randint(-10 * self.height, -self.height)
-
-
- class BigEnemy(pygame.sprite.Sprite):
- energy = 20
-
- def __init__(self, bg_size):
- pygame.sprite.Sprite.__init__(self)
-
- self.image1 = pygame.image.load("images/enemy3_n1.png").convert_alpha()
- self.image2 = pygame.image.load("images/enemy3_n2.png").convert_alpha()
- self.image_hit = pygame.image.load("images/enemy3_hit.png").convert_alpha()
- self.destroy_images = []
- self.destroy_images.extend([ \
- pygame.image.load("images/enemy3_down1.png").convert_alpha(), \
- pygame.image.load("images/enemy3_down2.png").convert_alpha(), \
- pygame.image.load("images/enemy3_down3.png").convert_alpha(), \
- pygame.image.load("images/enemy3_down4.png").convert_alpha(), \
- pygame.image.load("images/enemy3_down5.png").convert_alpha(), \
- pygame.image.load("images/enemy3_down6.png").convert_alpha() \
- ])
- self.rect = self.image1.get_rect()
- self.width, self.height = bg_size[0], bg_size[1]
- self.speed = 1
- self.active = True
- self.rect.left, self.rect.top = \
- randint(0, self.width - self.rect.width), \
- randint(-15 * self.height, -5 * self.height)
- self.mask = pygame.mask.from_surface(self.image1)
- self.energy = BigEnemy.energy
- self.hit = False
-
- def move(self):
- if self.rect.top < self.height:
- self.rect.top += self.speed
- else:
- self.reset()
-
- def reset(self):
- self.active = True
- self.energy = BigEnemy.energy
- self.rect.left, self.rect.top = \
- randint(0, self.width - self.rect.width), \
- randint(-15 * self.height, -5 * self.height)
四.发射子弹
* L; z! ]: \+ _ 现在的情况是我方飞机处于落后挨打的状态,敌强我弱,所以应该拿起武器进行反击! 接下来定义子弹,子弹分为两种: 一种是普通子弹一次只发射一颗; 另一种是补给发放的超级子弹一次可以发射两颗。我们将子弹定义为独立的模块bullet.py:# D1 T! d3 X! }0 P) B7 v$ F9 j
-
- import pygame
- class Bullet1(pygame.sprite.Sprite):
- def __init__(self, position):
- pygame.sprite.Sprite.__init__(self)
-
- self.image = pygame.image.load("images/bullet1.png").convert_alpha()
- self.rect = self.image.get_rect()
- self.rect.left, self.rect.top = position
- self.speed = 12
- self.active = False
- self.mask = pygame.mask.from_surface(self.image)
-
- def move(self):
- self.rect.top -= self.speed
-
- if self.rect.top < 0:
- self.active = False
-
- def reset(self, position):
- self.rect.left, self.rect.top = position
- self.active = True
-
-
- class Bullet2(pygame.sprite.Sprite):
- def __init__(self, position):
- pygame.sprite.Sprite.__init__(self)
-
- self.image = pygame.image.load("images/bullet2.png").convert_alpha()
- self.rect = self.image.get_rect()
- self.rect.left, self.rect.top = position
- self.speed = 14
- self.active = False
- self.mask = pygame.mask.from_surface(self.image)
-
- def move(self):
- self.rect.top -= self.speed
-
- if self.rect.top < 0:
- self.active = False
-
- def reset(self, position):
- self.rect.left, self.rect.top = position
- self.active = True
- 五.发放补给包
-
-
-
- 游戏设计每30秒随机发放一个补给包,可 能是超级子弹,也可能是全屏炸弹。补给包有自己的图像和运动轨迹,定义一个模块supply.py:
-
- import pygame
- from random import *
-
-
- class Bullet_Supply(pygame.sprite.Sprite):
- def __init__(self, bg_size):
- pygame.sprite.Sprite.__init__(self)
-
- self.image = pygame.image.load("images/bullet_supply.png").convert_alpha()
- self.rect = self.image.get_rect()
- self.width, self.height = bg_size[0], bg_size[1]
- self.rect.left, self.rect.bottom = \
- randint(0, self.width - self.rect.width), -100
- self.speed = 5
- self.active = False
- self.mask = pygame.mask.from_surface(self.image)
-
- def move(self):
- if self.rect.top < self.height:
- self.rect.top += self.speed
- else:
- self.active = False
-
- def reset(self):
- self.active = True
- self.rect.left, self.rect.bottom = \
- randint(0, self.width - self.rect.width), -100
-
-
- class Bomb_Supply(pygame.sprite.Sprite):
- def __init__(self, bg_size):
- pygame.sprite.Sprite.__init__(self)
-
- self.image = pygame.image.load("images/bomb_supply.png").convert_alpha()
- self.rect = self.image.get_rect()
- self.width, self.height = bg_size[0], bg_size[1]
- self.rect.left, self.rect.bottom = \
- randint(0, self.width - self.rect.width), -100
- self.speed = 5
- self.active = False
- self.mask = pygame.mask.from_surface(self.image)
-
- def move(self):
- if self.rect.top < self.height:
- self.rect.top += self.speed
- else:
- self.active = False
-
- def reset(self):
- self.active = True
- self.rect.left, self.rect.bottom = \
- randint(0, self.width - self.rect.width), -100
六.主模块
" r( L: n& W( P# u* `( i6 n 所有的模块都到齐了,接下来就该实现我们的主模块:
& T9 ~$ L# g& s- # main.py
- import pygame
- import sys
- import traceback
- import myplane
- import enemy
- import bullet
- import supply
-
- from pygame.locals import *
- from random import *
-
- pygame.init()
- pygame.mixer.init()
-
- bg_size = width, height = 480, 700
- screen = pygame.display.set_mode(bg_size)
- pygame.display.set_caption("飞机大战 -- FishC Demo")
-
- background = pygame.image.load("images/background.png").convert()
-
- BLACK = (0, 0, 0)
- WHITE = (255, 255, 255)
- GREEN = (0, 255, 0)
- RED = (255, 0, 0)
-
- # 载入游戏音乐
- pygame.mixer.music.load("sound/game_music.ogg")
- pygame.mixer.music.set_volume(0.2)
- bullet_sound = pygame.mixer.Sound("sound/bullet.wav")
- bullet_sound.set_volume(0.2)
- bomb_sound = pygame.mixer.Sound("sound/use_bomb.wav")
- bomb_sound.set_volume(0.2)
- supply_sound = pygame.mixer.Sound("sound/supply.wav")
- supply_sound.set_volume(0.2)
- get_bomb_sound = pygame.mixer.Sound("sound/get_bomb.wav")
- get_bomb_sound.set_volume(0.2)
- get_bullet_sound = pygame.mixer.Sound("sound/get_bullet.wav")
- get_bullet_sound.set_volume(0.2)
- upgrade_sound = pygame.mixer.Sound("sound/upgrade.wav")
- upgrade_sound.set_volume(0.2)
- enemy3_fly_sound = pygame.mixer.Sound("sound/enemy3_flying.wav")
- enemy3_fly_sound.set_volume(0.2)
- enemy1_down_sound = pygame.mixer.Sound("sound/enemy1_down.wav")
- enemy1_down_sound.set_volume(0.2)
- enemy2_down_sound = pygame.mixer.Sound("sound/enemy2_down.wav")
- enemy2_down_sound.set_volume(0.2)
- enemy3_down_sound = pygame.mixer.Sound("sound/enemy3_down.wav")
- enemy3_down_sound.set_volume(0.5)
- me_down_sound = pygame.mixer.Sound("sound/me_down.wav")
- me_down_sound.set_volume(0.2)
-
-
- def add_small_enemies(group1, group2, num):
- for i in range(num):
- e1 = enemy.SmallEnemy(bg_size)
- group1.add(e1)
- group2.add(e1)
-
-
- 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)
-
-
- def inc_speed(target, inc):
- for each in target:
- each.speed += inc
-
-
- def main():
- pygame.mixer.music.play(-1)
-
- # 生成我方飞机
- me = myplane.MyPlane(bg_size)
-
- enemies = pygame.sprite.Group()
-
- # 生成敌方小型飞机
- small_enemies = pygame.sprite.Group()
- add_small_enemies(small_enemies, enemies, 15)
-
- # 生成敌方中型飞机
- mid_enemies = pygame.sprite.Group()
- add_mid_enemies(mid_enemies, enemies, 4)
-
- # 生成敌方大型飞机
- big_enemies = pygame.sprite.Group()
- add_big_enemies(big_enemies, enemies, 2)
-
- # 生成普通子弹
- bullet1 = []
- bullet1_index = 0
- BULLET1_NUM = 4
- for i in range(BULLET1_NUM):
- bullet1.append(bullet.Bullet1(me.rect.midtop))
-
- # 生成超级子弹
- bullet2 = []
- bullet2_index = 0
- BULLET2_NUM = 8
- for i in range(BULLET2_NUM // 2):
- bullet2.append(bullet.Bullet2((me.rect.centerx - 33, me.rect.centery)))
- bullet2.append(bullet.Bullet2((me.rect.centerx + 30, me.rect.centery)))
-
- clock = pygame.time.Clock()
-
- # 中弹图片索引
- e1_destroy_index = 0
- e2_destroy_index = 0
|