# 导入模块
import random # 随机数模块
import pygame # 制作游戏模块
from os import path # 系统路径模块
# 游戏资源路径
img_dir = path.join(path.dirname(__file__), 'assets')
sound_folder = path.join(path.dirname(__file__), 'sounds')
# 游戏中的值
WIDTH = 480
HEIGHT = 600
FPS = 60
# 常用颜色值
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
# 初始化游戏
pygame.init()
# 音频初始化
pygame.mixer.init()
# 初始化屏幕显示窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
# 设置游戏显示标题
pygame.display.set_caption("太空射击")
# 时钟
clock = pygame.time.Clock()
# 获取游戏背景图片
background = pygame.image.load(path.join(img_dir, 'starfield.png')).convert()
# 获取游戏背景图片矩形
background_rect = background.get_rect()
# 获取字体
font_name = pygame.font.match_font('楷体', 16)
# 获取飞机类的图片资源
player_img = pygame.image.load(path.join(img_dir, 'playerShip1_orange.png')).convert()
# 获取子弹类的图片资源
bullet_img = pygame.image.load(path.join(img_dir, 'laserRed16.png')).convert()
# 获取陨石类的图片资源
meteor_images = []
meteor_list = [
'meteorBrown_tiny1.png',
'meteorBrown_small2.png',
'meteorBrown_small1.png',
'meteorBrown_med3.png',
'meteorBrown_med1.png',
'meteorBrown_big2.png',
'meteorBrown_big1.png',
]
# 遍历
for image in meteor_list:
meteor_images.append(pygame.image.load(path.join(img_dir, image)).convert())
# 获取爆炸类的图片资源
explosion_anim = {}
explosion_anim['lg'] = []
explosion_anim['sm'] = []
for i in range(9):
filename = 'regularExplosion0{}.png'.format(i)
img = pygame.image.load(path.join(img_dir, filename)).convert()
img.set_colorkey(BLACK)
img_lg = pygame.transform.scale(img, (75, 75))
explosion_anim['lg'].append(img_lg)
img_sm = pygame.transform.scale(img, (32, 32))
explosion_anim['sm'].append(img_sm)
##音频资源
# 飞机射击音频资源
shooting_sound = pygame.mixer.Sound(path.join(sound_folder, 'pew.wav'))
# 陨石爆炸的音频资源
expl_sounds = []
for sound in ['expl3.wav', 'expl6.wav']:
expl_sounds.append(pygame.mixer.Sound(path.join(sound_folder, sound)))
# 绘制字体
# parm1 屏幕
# Parm2 文本内容
# parm3 字体大小
# parm4 x坐标
# parm5 y坐标
def draw_text(surf, text, size, x, y):
# 游戏字体设置
font = pygame.font.Font(font_name, size)
# 文本的显示样式
text_surface = font.render(text, True, WHITE)
# 文本区域矩形
text_rect = text_surface.get_rect()
# 设置文本区域矩形顶点坐标
text_rect.midtop = (x, y)
# 将文本内容绘制到屏幕上
surf.blit(text_surface, text_rect)
# 绘制主菜单函数
def main_menu():
# 全局变量 屏幕
global screen
# 主菜单音频资源获取
menu_song = pygame.mixer.music.load(path.join(sound_folder, 'menu.ogg'))
# 主菜单音频资源播放
pygame.mixer.music.play(-1)
## 设置游戏主菜单标题
# 获取标题图片资源
title = pygame.image.load(path.join(img_dir, 'main.png')).convert()
# 标题图片资源等比例缩放
title = pygame.transform.scale(title, (WIDTH, HEIGHT), screen)
# 绘制标题图片到屏幕上
screen.blit(title, (0, 0))
# 部分刷新显示
pygame.display.update()
# 监听用户操作
while True:
ev = pygame.event.poll()
# 判断用户操作(事件类型是否是按键按下事件)
if ev.type == pygame.KEYDOWN:
# 判断用户是否按下了回车键
if ev.key == pygame.K_RETURN:
break
# 判断用户是否按下了Q键
elif ev.key == pygame.K_q:
# 游戏退出
pygame.quit()
# 程序退出
quit()
# 判断用户操作(事件类型是否是用户点击退出事件)
elif ev.type == pygame.QUIT:
# 游戏退出
pygame.quit()
# 程序退出
quit()
# 否则
else:
# 绘制提示字
# 首先绘制提示字:按回车按键开始游戏
draw_text(screen, "Press [ENTER] TO Begin", 30, WIDTH / 2, HEIGHT / 2)
# 绘制提示字: 按Q键退出游戏
draw_text(screen, "or [Q] To Quit", 30, WIDTH / 2, (HEIGHT / 2) + 40)
# 部分刷新显示
pygame.display.update()
# #游戏准备界面
# 获取游戏准备界面音频资源
ready_song = pygame.mixer.Sound(path.join(sound_folder, 'getready.ogg'))
# 播放游戏准备界面音频资源
ready_song.play()
# 填充游戏屏幕为黑色
screen.fill(BLACK)
# 绘制游戏准备界面字体
draw_text(screen, "GET READY!", 60, WIDTH / 2, HEIGHT / 2)
# 部分刷新显示
pygame.display.update()
# #子弹类
class Bullet(pygame.sprite.Sprite):
# 子弹类的构造函数
def __init__(self, x, y):
# 将子弹类设置成精灵
pygame.sprite.Sprite.__init__(self)
# 图片
self.image = bullet_img
self.image.set_colorkey(BLACK)
# 矩形形状
self.rect = self.image.get_rect()
# 矩形的中心的x值
self.rect.centerx = x
# 矩形底部的值
self.rect.bottom = y
# 子弹的移动速度
self.speedy = -10
# 子弹类的更新方法
def update(self):
# 子弹移动实现
self.rect.y += self.speedy
# 子弹超出边界问题
if self.rect.bottom < 0:
self.kill()
# 石头类
class Mob(pygame.sprite.Sprite):
# 石头的构造函数
def __init__(self):
# 将陨石设置为精灵
pygame.sprite.Sprite.__init__(self)
# 图片
self.image_orig = random.choice(meteor_images)
self.image_orig.set_colorkey(BLACK)
# 复制初始图片
self.image = self.image_orig.copy()
# 图片的矩形形状
self.rect = self.image.get_rect()
# x坐标
self.rect.x = random.randrange(0, WIDTH - self.rect.width)
# y坐标
self.rect.y = random.randrange(-150, -100)
# 纵向移动速度
self.speedy = random.randrange(5, 20)
# 横向移动速度
self.speedx = random.randrange(-3, 3)
# 半径
self.radius = int(self.rect.width * .90 / 2)
# 旋转角度
self.rotation = 0
# 旋转角度变化速度
self.rotation_speed = random.randrange(-8, 8)
# 最后一次变化时间
self.last_update = pygame.time.get_ticks()
# 旋转函数
def rotate(self):
# 获取当前时间
time_now = pygame.time.get_ticks()
# 判断是否超出旋转时间
if time_now - self.last_update > 50:
# 将最后一次变化时间改为当前时间
self.last_update = time_now
# 改变旋转角度
self.rotation = (self.rotation + self.rotation_speed) % 360
# 旋转图片
new_image = pygame.transform.rotate(self.image_orig, self.rotation)
# 获得旋转中心点
old_center = self.rect.center
# 重新赋值、
self.image = new_image
# 重新获得图片矩形
self.rect = self.image.get_rect()
# 重新获得图片矩形设置中心点
self.rect.center = old_center
# 更新变化函数
def update(self):
# 执行旋转函数
self.rotate()
# 改变x
self.rect.x += self.speedx
# 改变y
self.rect.y += self.speedy
# 判断陨石是否出界
if (self.rect.top > HEIGHT + 10) or (self.rect.left < -25) or (self.rect.right > WIDTH + 20):
# 改变陨石的想,x,y,y方向的移动速度
self.rect.x = random.randrange(0, WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
# 创建陨石类对象函数
def newmob():
# 创建陨石类对象
mob_element = Mob()
# 将陨石类添加到精灵组合
all_sprites.add(mob_element)
# 将陨石添加到陨石组合
mobs.add(mob_element)
# #爆炸类
class Explosion(pygame.sprite.Sprite):
# 爆炸类构造函数
def __init__(self, center, size):
# 将爆炸类设为精灵
# #大小
self.size = size
pygame.sprite.Sprite.__init__(self)
# 图片
self.image = explosion_anim[self.size][0]
# 图片的矩形形状
self.rect = self.image.get_rect()
# 图片矩形的中心点
self.rect.center = center
# 设计
self.frame = 0
# 设计时间
self.frame_rete = 75
# 最后一次更新时间
self.last_update = pygame.time.get_ticks()
# 更新函数
def update(self):
# 现在的时间
now = pygame.time.get_ticks()
# 判断现在的时间减去最后一次更新时间是否大于设计时间
if now - self.last_update > self.frame_rete:
# 将最后一次更新时间变换为现在时间
self.last_update = now
self.frame += 1
if self.frame == len(explosion_anim[self.size]):
self.kill()
else:
center = self.rect.center
self.image = explosion_anim[self.size][self.frame]
self.rect = self.image.get_rect()
self.rect.center = center
# #飞机类
# sprite
class Player(pygame.sprite.Sprite):
# 飞机类的构造函数
def __init__(self):
# 将飞机类设置为精灵
pygame.sprite.Sprite.__init__(self)
# 飞机类的图片
self.image = pygame.transform.scale(player_img, (50, 38))
self.image.set_colorkey(BLACK)
# 矩形形状
self.rect = self.image.get_rect()
# 半径
self.redius = 20
# 矩形x中心点
self.rect.centerx = WIDTH / 2
# 矩形底部
self.rect.bottom = HEIGHT - 10
# x方向移动速度
self.speedx = 0
# 射击延迟时间
self.shoot_delay = 250
# 射击的最后时间
self.last_shoot = pygame.time.get_ticks()
# 飞机的更新函数
def update(self):
# x方向移动速度
self.speedx = 0
pygame.event.poll()
# 获取键盘监听
keystate = pygame.key.get_pressed()
# 判断用户是否按了left键
if keystate[pygame.K_LEFT]:
self.speedx = -5
# 判断right
elif keystate[pygame.K_RIGHT]:
self.speedx = 5
# 判断用户是否获得空格键
if keystate[pygame.K_SPACE]:
# 执行射击方法
self.shoot()
# 飞机超出边界
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.left < 0:
self.rect.left = 0
# 让飞机实现移动
self.rect.x += self.speedx
# 飞机的射击函数、
def shoot(self):
# 获得现在时间
now = pygame.time.get_ticks()
# 判断是否超出延迟时间
if now - self.last_shoot > self.shoot_delay:
# 将飞机最后时间改为当前时间
self.last_shoot = now
# 创建子弹对象
bullet = Bullet(self.rect.centerx, self.rect.top)
# 将子弹添加到精灵组合中
all_sprites.add(bullet)
# 将子弹添加到子弹集合中
bullets.add(bullet)
# 播放射击声音
shooting_sound.play()
# # 游戏的主循环(死循环)
# 游戏状态
running = True
# 菜单显示状态
menu_display = True
while running:
# 判断菜单是否显示
if menu_display:
main_menu()
# 进入游戏准备界面的时间
pygame.time.wait(2000)
# 停止播放主菜单音频
pygame.mixer.music.stop()
# 播放玩游戏时的背景音乐
# 获取资源
pygame.mixer.music.load(path.join(sound_folder, 'tgfcoder-FrozenJam-SeamlessLoop.ogg'))
# 播放音频
pygame.mixer.music.play(-1)
# 菜单显示状态设置为false
menu_display = False
# 创造精灵组合
all_sprites = pygame.sprite.Group()
# 创建飞机对象
player = Player()
# 将飞机对象添加到精灵组合中
all_sprites.add(player)
# 创建子弹精灵组合
bullets = pygame.sprite.Group()
# 创建陨石精灵组合
mobs = pygame.sprite.Group()
# 创建陨石函数
for i in range(8):
# 调用创建陨石函数
newmob()
clock.tick(FPS)
# 遍历事件
for event in pygame.event.get():
# 判断事件
if event.type == pygame.QUIT:
# 设置游戏状态
running = False
# 判断事件类型 按键按下
if event.type == pygame.KEYDOWN:
# 判断是否按下eSC
if event.key == pygame.K_ESCAPE:
# 设置游戏状态
running = False
# update
all_sprites.update()
# #游戏中的碰撞检测
# 陨石雨与子弹
hits = pygame.sprite.groupcollide(mobs, bullets, True, True)
# 遍历hits表
for hit in hits:
# 爆炸音效
random.choice(expl_sounds).play()
# 爆炸动画
expl = Explosion(hit.rect.center, 'lg')
all_sprites.add(expl)
# 产生新陨石
newmob()
# 填充屏幕
screen.fill(BLACK)
# 在屏幕中绘制游戏背景图片
screen.blit(background, background_rect)
all_sprites.draw(screen)
# 更新整个待显示的绘制内容到屏幕中
pygame.display.flip()
pygame.quit()
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:太空射击python - Python技术站