前言
大家之前用python编写过飞机大战的部分代码,只能够展示英雄飞机,背景,敌机和发射子弹,今天把背景音乐,击毁敌机,爆
炸特效,得分等等相关功能一并加入进来,代码有点长,三百多行,你们要的代码来了哦?
编程思路
主要使用pygame库,类的创建,函数的调用等等来实现,话不多说,上程序。
编程实现
Python学习交流Q群:906715085####
import pygame # 导入动态模块(.dll .pyd .so) 不需要在包名后边跟模块名
from pygame.locals import *
import time
import random
import sys
# 定义常量(定义后,不再改值)
WINDOW_HEIGHT = 768
WINDOW_WIDTH = 512
enemy_list = []
score = 0
is_restart = False
class Map:
def __init__(self, img_path, window):
self.x = 0
self.bg_img1 = pygame.image.load(img_path)
self.bg_img2 = pygame.image.load(img_path)
self.bg1_y = - WINDOW_HEIGHT
self.bg2_y = 0
self.window = window
def move(self):
# 当地图1的 y轴移动到0,则重置
if self.bg1_y >= 0:
self.bg1_y = - WINDOW_HEIGHT
# 当地图2的 y轴移动到 窗口底部,则重置
if self.bg2_y >= WINDOW_HEIGHT:
self.bg2_y = 0
# 每次循环都移动1个像素
self.bg1_y += 3
self.bg2_y += 3
def display(self):
"""贴图"""
self.window.blit(self.bg_img1, (self.x, self.bg1_y))
self.window.blit(self.bg_img2, (self.x, self.bg2_y))
class HeroBullet:
"""英雄子弹类"""
def __init__(self, img_path, x, y, window):
self.img = pygame.image.load(img_path)
self.x = x
self.y = y
self.window = window
def display(self):
self.window.blit(self.img, (self.x, self.y))
def move(self):
"""子弹向上飞行距离"""
self.y -= 6
def is_hit_enemy(self, enemy):
if pygame.Rect.colliderect(
pygame.Rect(self.x, self.y, 20, 31),
pygame.Rect(enemy.x, enemy.y, 100, 68)
): # 判断是否交叉
return True
else:
return False
class EnemyPlane:
"""敌人飞机类"""
def __init__(self, img_path, x, y, window):
self.img = pygame.image.load(img_path) # 图片对象
self.x = x # 飞机坐标
self.y = y
self.window = window # 飞机所在的窗口
self.is_hited = False
self.anim_index = 0
self.hit_sound = pygame.mixer.Sound("E:/飞机大战/baozha.ogg")
def move(self):
self.y += 10
# 到达窗口下边界,回到顶部
if self.y >= WINDOW_HEIGHT:
self.x = random.randint(0, random.randint(0, WINDOW_WIDTH - 100))
self.y = 0
def plane_down_anim(self):
"""敌机被击中动画"""
if self.anim_index >= 21: # 动画执行完
self.anim_index = 0
self.img = pygame.image.load(
"E:/飞机大战/img-plane_%d.png" % random.randint(1, 7))
self.x = random.randint(0, WINDOW_WIDTH - 100)
self.y = 0
self.is_hited = False
return
elif self.anim_index == 0:
self.hit_sound.play()
self.img = pygame.image.load(
"E:/飞机大战/bomb-%d.png" % (self.anim_index // 3 + 1))
self.anim_index += 1
def display(self):
"""贴图"""
if self.is_hited:
self.plane_down_anim()
self.window.blit(self.img, (self.x, self.y))
class HeroPlane:
def __init__(self, img_path, x, y, window):
self.img = pygame.image.load(img_path) # 图片对象
self.x = x # 飞机坐标
self.y = y
self.window = window # 飞机所在的窗口
self.bullets = [] # 记录该飞机发出的所有子弹
self.is_hited = False
self.is_anim_down = False
self.anim_index = 0
def is_hit_enemy(self, enemy):
if pygame.Rect.colliderect(
pygame.Rect(self.x, self.y, 120, 78),
pygame.Rect(enemy.x, enemy.y, 100, 68)
): # 判断是否交叉
return True
else:
return False
def plane_down_anim(self):
"""敌机被击中动画"""
if self.anim_index >= 21: # 动画执行完
self.is_hited = False
self.is_anim_down = True
return
self.img = pygame.image.load(
"E:/飞机大战/bomb-%d.png" % (self.anim_index // 3 + 1))
self.anim_index += 1
def display(self):
"""贴图"""
for enemy in enemy_list:
if self.is_hit_enemy(enemy):
enemy.is_hited = True
self.is_hited = True
self.plane_down_anim()
break
self.window.blit(self.img, (self.x, self.y))
def display_bullets(self):
# 贴子弹图
deleted_bullets = []
for bullet in self.bullets:
# 判断 子弹是否超出 上边界
if bullet.y >= -31: # 没有出边界
bullet.display()
bullet.move()
else: # 飞出边界
deleted_bullets.append(bullet)
for enemy in enemy_list:
if bullet.is_hit_enemy(enemy): # 判断是否击中敌机
enemy.is_hited = True
deleted_bullets.append(bullet)
global score
score += 10
break
for out_window_bullet in deleted_bullets:
self.bullets.remove(out_window_bullet)
def move_left(self):
"""往左飞"""
if self.x >= 0 and not self.is_hited:
self.x -= 10
def move_right(self):
"""往右飞"""
if self.x <= WINDOW_WIDTH - 120 and not self.is_hited:
self.x += 10
def move_up(self):
"""往上飞"""
if self.y >= 0 and not self.is_hited:
self.y -= 5
def move_down(self):
"""往下飞"""
if self.y <= WINDOW_HEIGHT - 78 and not self.is_hited:
self.y += 5
def fire(self):
"""发射子弹"""
# 创建子弹对象 子弹x = 飞机x + 飞机宽度的一半 - 子弹宽度的一半
bullet = HeroBullet("E:/飞机大战/bullet_17.png", self.x +
60 - 10, self.y - 31, self.window)
# 显示子弹(贴子弹图)
bullet.display()
self.bullets.append(bullet) # 为了避免子弹对象被释放(只有局部变量引用对象,方法一执行完就会释放)
class Game:
def __init__(self):
pygame.init()
# 设置标题
pygame.display.set_caption("飞机大战 v1.0")
# 设置图标
game_ico = pygame.image.load("E:/飞机大战/app.ico")
pygame.display.set_icon(game_ico)
pygame.mixer.music.load("E:/飞机大战/bg2.ogg")
# 游戏结束的音效(超级玛丽)
self.gameover_sound = pygame.mixer.Sound("E:/飞机大战/gameover.wav")
# 循环播放背景音乐
pygame.mixer.music.play(-1)
# 创建窗口 set_mode((窗口尺寸))
self.window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
# 创建地图对象
self.game_map = Map("E:/飞机大战/img_bg_level_%d.jpg" %
random.randint(1, 5), self.window)
# 创建对象
self.hero_plane = HeroPlane("E:/飞机大战/hero2.png", 240, 500, self.window)
enemy_plane1 = EnemyPlane("E:/飞机大战/img-plane_%d.png" % random.randint(
1, 7), random.randint(0, WINDOW_WIDTH - 100), 0, self.window)
enemy_plane2 = EnemyPlane("E:/飞机大战/img-plane_%d.png" % random.randint(1, 7), random.randint(0, WINDOW_WIDTH - 100), random.randint(-150, -68),
self.window)
enemy_plane3 = EnemyPlane("E:/飞机大战/img-plane_%d.png" % random.randint(1, 7), random.randint(0, WINDOW_WIDTH - 100), random.randint(-300, -140),
self.window)
enemy_list.append(enemy_plane1)
enemy_list.append(enemy_plane2)
enemy_list.append(enemy_plane3)
self.enemy_list = enemy_list
# 创建文字对象
# self.score_font = pygame.font.SysFont("simhei", 40)
self.score_font = pygame.font.Font("E:/飞机大战/SIMHEI.TTF", 40)
def draw_text(self, content, size, x, y):
# font_obj = pygame.font.SysFont("simhei", size)
font_obj = pygame.font.Font("E:/飞机大战/SIMHEI.TTF", size)
text = font_obj.render(content, 1, (255, 255, 255))
self.window.blit(text, (x, y))
def wait_game_input(self):
while True:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
sys.exit()
pygame.quit()
elif event.key == K_RETURN:
global is_restart, score
is_restart = True
score = 0
return
def game_start(self):
# 贴背景图片
self.game_map.display()
self.draw_text("飞机大战", 40, WINDOW_WIDTH / 2 - 100, WINDOW_HEIGHT / 3)
self.draw_text("按Enter开始游戏, Esc退出游戏.", 28, WINDOW_WIDTH /3 - 140, WINDOW_HEIGHT /2)
pygame.display.update()
self.wait_game_input()
def game_over(self):
# 先停止背景音乐
pygame.mixer.music.stop()
# 再播放音效
self.gameover_sound.play()
# 贴背景图片
self.game_map.display()
self.draw_text("战机被击落,得分为 %d" % score, 28, WINDOW_WIDTH / 3 - 100, WINDOW_HEIGHT / 3)
self.draw_text("按Enter重新开始, Esc退出游戏.", 28, WINDOW_WIDTH / 3 - 140, WINDOW_HEIGHT / 2)
pygame.display.update()
self.wait_game_input()
self.gameover_sound.stop()
def key_control(self):
# 获取事件,比如按键等 先显示界面,再根据获取的事件,修改界面效果
for event in pygame.event.get():
# 判断是否是点击了退出按钮
if event.type == QUIT:
sys.exit() # 让程序终止
pygame.quit()
# 判断是否是按下了键
elif event.type == KEYDOWN:
# 检测按键是否是空格键
if event.key == K_SPACE:
self.hero_plane.fire()
# 获取连续按下的情况
pressed_keys = pygame.key.get_pressed()
if pressed_keys[pygame.K_LEFT]:
self.hero_plane.move_left()
if pressed_keys[pygame.K_RIGHT]:
self.hero_plane.move_right()
if pressed_keys[pygame.K_UP]:
self.hero_plane.move_up()
if pressed_keys[pygame.K_DOWN]:
self.hero_plane.move_down()
def display(self):
# 贴背景图
self.game_map.display()
self.game_map.move()
# 贴飞机图
self.hero_plane.display()
self.hero_plane.display_bullets()
# 贴敌机图
for enemy in enemy_list:
enemy.display()
# 让敌机移动
if not enemy.is_hited:
enemy.move()
# 贴得分文字
score_text = self.score_font.render("得分:%d" % score, 1, (255, 255, 255))
self.window.blit(score_text, (10, 10))
# 刷新界面 不刷新不会更新显示的内容
pygame.display.update()
def run(self):
if is_restart == False:
self.game_start()
while True:
# 显示界面
self.display()
if self.hero_plane.is_anim_down:
self.hero_plane.is_anim_down = False
global enemy_list
enemy_list = []
break
# 键盘控制
self.key_control()
# 每次循环,让程序休眠一会儿
time.sleep(0.01)
self.game_over()
def main():
"""主函数 一般将程序的入口"""
# 运行游戏
while True:
# 创建游戏对象
game = Game()
game.run()
if __name__ == '__main__': # 判断是否主动执行该文件
main()
import pygame # 导入动态模块(.dll .pyd .so) 不需要在包名后边跟模块名
from pygame.locals import *
import time
import random
import sys
# 定义常量(定义后,不再改值)
WINDOW_HEIGHT = 768
WINDOW_WIDTH = 512
enemy_list = []
score = 0
is_restart = False
class Map:
def __init__(self, img_path, window):
self.x = 0
self.bg_img1 = pygame.image.load(img_path)
self.bg_img2 = pygame.image.load(img_path)
self.bg1_y = - WINDOW_HEIGHT
self.bg2_y = 0
self.window = window
def move(self):
# 当地图1的 y轴移动到0,则重置
if self.bg1_y >= 0:
self.bg1_y = - WINDOW_HEIGHT
# 当地图2的 y轴移动到 窗口底部,则重置
if self.bg2_y >= WINDOW_HEIGHT:
self.bg2_y = 0
# 每次循环都移动1个像素
self.bg1_y += 3
self.bg2_y += 3
def display(self):
"""贴图"""
self.window.blit(self.bg_img1, (self.x, self.bg1_y))
self.window.blit(self.bg_img2, (self.x, self.bg2_y))
class HeroBullet:
"""英雄子弹类"""
def __init__(self, img_path, x, y, window):
self.img = pygame.image.load(img_path)
self.x = x
self.y = y
self.window = window
def display(self):
self.window.blit(self.img, (self.x, self.y))
def move(self):
"""子弹向上飞行距离"""
self.y -= 6
def is_hit_enemy(self, enemy):
if pygame.Rect.colliderect(
pygame.Rect(self.x, self.y, 20, 31),
pygame.Rect(enemy.x, enemy.y, 100, 68)
): # 判断是否交叉
return True
else:
return False
class EnemyPlane:
"""敌人飞机类"""
def __init__(self, img_path, x, y, window):
self.img = pygame.image.load(img_path) # 图片对象
self.x = x # 飞机坐标
self.y = y
self.window = window # 飞机所在的窗口
self.is_hited = False
self.anim_index = 0
self.hit_sound = pygame.mixer.Sound("E:/飞机大战/baozha.ogg")
def move(self):
self.y += 10
# 到达窗口下边界,回到顶部
if self.y >= WINDOW_HEIGHT:
self.x = random.randint(0, random.randint(0, WINDOW_WIDTH - 100))
self.y = 0
def plane_down_anim(self):
"""敌机被击中动画"""
if self.anim_index >= 21: # 动画执行完
self.anim_index = 0
self.img = pygame.image.load(
"E:/飞机大战/img-plane_%d.png" % random.randint(1, 7))
self.x = random.randint(0, WINDOW_WIDTH - 100)
self.y = 0
self.is_hited = False
return
elif self.anim_index == 0:
self.hit_sound.play()
self.img = pygame.image.load(
"E:/飞机大战/bomb-%d.png" % (self.anim_index // 3 + 1))
self.anim_index += 1
def display(self):
"""贴图"""
if self.is_hited:
self.plane_down_anim()
self.window.blit(self.img, (self.x, self.y))
class HeroPlane:
def __init__(self, img_path, x, y, window):
self.img = pygame.image.load(img_path) # 图片对象
self.x = x # 飞机坐标
self.y = y
self.window = window # 飞机所在的窗口
self.bullets = [] # 记录该飞机发出的所有子弹
self.is_hited = False
self.is_anim_down = False
self.anim_index = 0
def is_hit_enemy(self, enemy):
if pygame.Rect.colliderect(
pygame.Rect(self.x, self.y, 120, 78),
pygame.Rect(enemy.x, enemy.y, 100, 68)
): # 判断是否交叉
return True
else:
return False
def plane_down_anim(self):
"""敌机被击中动画"""
if self.anim_index >= 21: # 动画执行完
self.is_hited = False
self.is_anim_down = True
return
self.img = pygame.image.load(
"E:/飞机大战/bomb-%d.png" % (self.anim_index // 3 + 1))
self.anim_index += 1
def display(self):
"""贴图"""
for enemy in enemy_list:
if self.is_hit_enemy(enemy):
enemy.is_hited = True
self.is_hited = True
self.plane_down_anim()
break
self.window.blit(self.img, (self.x, self.y))
def display_bullets(self):
# 贴子弹图
deleted_bullets = []
for bullet in self.bullets:
# 判断 子弹是否超出 上边界
if bullet.y >= -31: # 没有出边界
bullet.display()
bullet.move()
else: # 飞出边界
deleted_bullets.append(bullet)
for enemy in enemy_list:
if bullet.is_hit_enemy(enemy): # 判断是否击中敌机
enemy.is_hited = True
deleted_bullets.append(bullet)
global score
score += 10
break
for out_window_bullet in deleted_bullets:
self.bullets.remove(out_window_bullet)
def move_left(self):
"""往左飞"""
if self.x >= 0 and not self.is_hited:
self.x -= 10
def move_right(self):
"""往右飞"""
if self.x <= WINDOW_WIDTH - 120 and not self.is_hited:
self.x += 10
def move_up(self):
"""往上飞"""
if self.y >= 0 and not self.is_hited:
self.y -= 5
def move_down(self):
"""往下飞"""
if self.y <= WINDOW_HEIGHT - 78 and not self.is_hited:
self.y += 5
def fire(self):
"""发射子弹"""
# 创建子弹对象 子弹x = 飞机x + 飞机宽度的一半 - 子弹宽度的一半
bullet = HeroBullet("E:/飞机大战/bullet_17.png", self.x +
60 - 10, self.y - 31, self.window)
# 显示子弹(贴子弹图)
bullet.display()
self.bullets.append(bullet) # 为了避免子弹对象被释放(只有局部变量引用对象,方法一执行完就会释放)
class Game:
def __init__(self):
pygame.init()
# 设置标题
pygame.display.set_caption("飞机大战 v1.0")
# 设置图标
game_ico = pygame.image.load("E:/飞机大战/app.ico")
pygame.display.set_icon(game_ico)
pygame.mixer.music.load("E:/飞机大战/bg2.ogg")
# 游戏结束的音效(超级玛丽)
self.gameover_sound = pygame.mixer.Sound("E:/飞机大战/gameover.wav")
# 循环播放背景音乐
pygame.mixer.music.play(-1)
# 创建窗口 set_mode((窗口尺寸))
self.window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
# 创建地图对象
self.game_map = Map("E:/飞机大战/img_bg_level_%d.jpg" %
random.randint(1, 5), self.window)
# 创建对象
self.hero_plane = HeroPlane("E:/飞机大战/hero2.png", 240, 500, self.window)
enemy_plane1 = EnemyPlane("E:/飞机大战/img-plane_%d.png" % random.randint(
1, 7), random.randint(0, WINDOW_WIDTH - 100), 0, self.window)
enemy_plane2 = EnemyPlane("E:/飞机大战/img-plane_%d.png" % random.randint(1, 7), random.randint(0, WINDOW_WIDTH - 100), random.randint(-150, -68),
self.window)
enemy_plane3 = EnemyPlane("E:/飞机大战/img-plane_%d.png" % random.randint(1, 7), random.randint(0, WINDOW_WIDTH - 100), random.randint(-300, -140),
self.window)
enemy_list.append(enemy_plane1)
enemy_list.append(enemy_plane2)
enemy_list.append(enemy_plane3)
self.enemy_list = enemy_list
# 创建文字对象
# self.score_font = pygame.font.SysFont("simhei", 40)
self.score_font = pygame.font.Font("E:/飞机大战/SIMHEI.TTF", 40)
def draw_text(self, content, size, x, y):
# font_obj = pygame.font.SysFont("simhei", size)
font_obj = pygame.font.Font("E:/飞机大战/SIMHEI.TTF", size)
text = font_obj.render(content, 1, (255, 255, 255))
self.window.blit(text, (x, y))
def wait_game_input(self):
while True:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
sys.exit()
pygame.quit()
elif event.key == K_RETURN:
global is_restart, score
is_restart = True
score = 0
return
def game_start(self):
# 贴背景图片
self.game_map.display()
self.draw_text("飞机大战", 40, WINDOW_WIDTH / 2 - 100, WINDOW_HEIGHT / 3)
self.draw_text("按Enter开始游戏, Esc退出游戏.", 28, WINDOW_WIDTH /3 - 140, WINDOW_HEIGHT /2)
pygame.display.update()
self.wait_game_input()
def game_over(self):
# 先停止背景音乐
pygame.mixer.music.stop()
# 再播放音效
self.gameover_sound.play()
# 贴背景图片
self.game_map.display()
self.draw_text("战机被击落,得分为 %d" % score, 28, WINDOW_WIDTH / 3 - 100, WINDOW_HEIGHT / 3)
self.draw_text("按Enter重新开始, Esc退出游戏.", 28, WINDOW_WIDTH / 3 - 140, WINDOW_HEIGHT / 2)
pygame.display.update()
self.wait_game_input()
self.gameover_sound.stop()
def key_control(self):
# 获取事件,比如按键等 先显示界面,再根据获取的事件,修改界面效果
for event in pygame.event.get():
# 判断是否是点击了退出按钮
if event.type == QUIT:
sys.exit() # 让程序终止
pygame.quit()
# 判断是否是按下了键
elif event.type == KEYDOWN:
# 检测按键是否是空格键
if event.key == K_SPACE:
self.hero_plane.fire()
# 获取连续按下的情况
pressed_keys = pygame.key.get_pressed()
if pressed_keys[pygame.K_LEFT]:
self.hero_plane.move_left()
if pressed_keys[pygame.K_RIGHT]:
self.hero_plane.move_right()
if pressed_keys[pygame.K_UP]:
self.hero_plane.move_up()
if pressed_keys[pygame.K_DOWN]:
self.hero_plane.move_down()
def display(self):
# 贴背景图
self.game_map.display()
self.game_map.move()
# 贴飞机图
self.hero_plane.display()
self.hero_plane.display_bullets()
# 贴敌机图
for enemy in enemy_list:
enemy.display()
# 让敌机移动
if not enemy.is_hited:
enemy.move()
# 贴得分文字
score_text = self.score_font.render("得分:%d" % score, 1, (255, 255, 255))
self.window.blit(score_text, (10, 10))
# 刷新界面 不刷新不会更新显示的内容
pygame.display.update()
def run(self):
if is_restart == False:
self.game_start()
while True:
# 显示界面
self.display()
if self.hero_plane.is_anim_down:
self.hero_plane.is_anim_down = False
global enemy_list
enemy_list = []
break
# 键盘控制
self.key_control()
# 每次循环,让程序休眠一会儿
time.sleep(0.01)
self.game_over()
def main():
"""主函数 一般将程序的入口"""
# 运行游戏
while True:
# 创建游戏对象
game = Game()
game.run()
if __name__ == '__main__': # 判断是否主动执行该文件
main()
#代码有点长,得使劲往下拉...
效果图
最后
今天给大家分享的飞机大战小游戏到这里就结束了,代码就放在上面吧,喜欢的小伙伴就拿去试试手吧。