查看“射击游戏-ch17”的源代码
←
射击游戏-ch17
跳转至:
导航
、
搜索
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
# 导入模块 import pygame import random from os import path # 获取图片库和声音库路径 img_dir = path.join(path.dirname(__file__), '') # 图片路径C:\Users\Administrator\PycharmProjects\pythonProject sound_folder = path.join(path.dirname(__file__), '') # 声音路径 # 定义游戏窗口、玩家血量条尺寸,游戏运行速度、炮火持续时间等参数 WIDTH = 480 # 定义游戏窗口大小 HEIGHT = 600 FPS = 60 # 游戏运行速度 POWERUP_TIME = 5000 # 炮火持续时间 BAR_LENGTH = 100 # 血量条尺寸 BAR_HEIGHT = 10 # 定义白、黑、红、绿、蓝、黄的RGB参数 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模块,创建游戏窗口、游戏窗口命名、创建跟踪时间对象 pygame.init() # 初始化将导入所有pygame的模块 pygame.mixer.init() ## 初始化混音器模块 screen = pygame.display.set_mode((WIDTH, HEIGHT)) # 设置游戏窗口大小 pygame.display.set_caption("spaceShooter") # 设置标题 clock = pygame.time.Clock() ## 创建时钟对象 用于FPS同步 # 获取字体arial所在路径 font_name = pygame.font.match_font('arial') # 加载游戏背景图片 background = pygame.image.load(path.join(img_dir, 'ziyun.png')).convert() background_rect = background.get_rect() # 获取背景图片的矩形区域 # 加载飞机图片 player_img = pygame.image.load(path.join(img_dir, 'feiji2.png')).convert() # 飞机图片 player_mini_img = pygame.transform.scale(player_img, (25, 25)) player_mini_img.set_colorkey((255,255,255)) # 加载飞机炮弹、导弹图片 bullet_img = pygame.image.load(path.join(img_dir, 'zidan.png')).convert() missile_img = pygame.image.load(path.join(img_dir, 'zidan.png')).convert_alpha() # 加载敌人图片 meteor_images = [] meteor_list = [ 'lanhua.png', 'huanhua.png', 'chenghua.png', ] for image in meteor_list: meteor_images.append(pygame.image.load(path.join(img_dir, image)).convert()) # 加载盾牌、闪电图片 powerup_images = {} powerup_images['shield'] = pygame.image.load(path.join(img_dir, 'dunpai.png')).convert() powerup_images['gun'] = pygame.image.load(path.join(img_dir, 'dunpai.png')).convert() # 加载爆炸效果图 explosion_anim = {} explosion_anim['lg'] = [] explosion_anim['sm'] = [] explosion_anim['player'] = [] for i in range(9): # 敌人爆炸 filename = 'baozha.png'.format(i) img = pygame.image.load(path.join(img_dir, filename)).convert() img.set_colorkey((255,255,255)) # 大爆炸 img_lg = pygame.transform.scale(img, (75, 75)) # 将爆炸图片缩放到75×75 explosion_anim['lg'].append(img_lg) # 小爆炸 img_sm = pygame.transform.scale(img, (32, 32)) # 将爆炸图片缩放到32×32 explosion_anim['sm'].append(img_sm) # 玩家爆炸 filename = 'baozha.png'.format(i) img = pygame.image.load(path.join(img_dir, filename)).convert() img.set_colorkey((255,255,255)) explosion_anim['player'].append(img) # 加载炮弹、导弹发射声音 shooting_sound = pygame.mixer.Sound(path.join(sound_folder, 'y1030.wav')) missile_sound = pygame.mixer.Sound(path.join(sound_folder, 'y1030.wav')) # 加载敌人爆炸声音 expl_sounds = [] for sound in ['y1030.wav', 'y1030.wav']: expl_sounds.append(pygame.mixer.Sound(path.join(sound_folder, sound))) # 加载玩家爆炸的声音 player_die_sound = pygame.mixer.Sound(path.join(sound_folder, 'y1030.wav')) # 调低音量 pygame.mixer.music.set_volume(0.2) def main_menu(): global screen menu_song = pygame.mixer.music.load(path.join(sound_folder, "y1030.wav")) # 加载游戏初始界面背景音乐 pygame.mixer.music.play(-1) # 开始播放主界面音乐 -1表示无限循环播放 title = pygame.image.load(path.join(img_dir, "ziyun.png")).convert() # 加载主界面图片 title = pygame.transform.scale(title, (WIDTH, HEIGHT), screen) # 调整主界面图片适应主窗口大小即480*600 screen.blit(title, (0, 0)) # 在0,0位置显示主界面图片 pygame.display.update() # 更新显示在主界面上 # 界面出来,等待事件触发进入游戏或者退出游戏 while True: ev = pygame.event.poll() # 从队列中获取一个事件 if ev.type == pygame.KEYDOWN: if ev.key == pygame.K_SPACE: # 按Enter break elif ev.key == pygame.K_BACKSPACE: # 按q键 pygame.quit() quit() elif ev.type == pygame.QUIT: pygame.quit() quit() else: draw_text(screen, "Start the game", 60, WIDTH / 2, HEIGHT / 6) draw_text(screen, "Press [SPACE] To Begin", 30, WIDTH / 2, HEIGHT / 2) # 屏幕添加文字 draw_text(screen, "or [BACKSPACE] To Quit", 30, WIDTH / 2, (HEIGHT / 2) + 40) pygame.display.update() # 进入准备状态 ready = pygame.mixer.Sound(path.join(sound_folder, 'y1030.wav')) # 加载准备声音 ready.play() # 准备状态声音播放 screen.fill(BLACK) # 背景黑色 draw_text(screen, "GET READY!", 40, WIDTH / 2, HEIGHT / 2) pygame.display.update() def draw_text(surf, text, size, x, y): font = pygame.font.Font(font_name, size) # 设置字体格式大小 text_surface = font.render(text, True, GREEN) ## render(显示内容,是否抗锯齿,字体颜色,字体背景颜色) text_rect = text_surface.get_rect() # 获取文字矩形框 text_rect.midtop = (x, y) # 让文字的中部在x,y的位置上 surf.blit(text_surface, text_rect) # 显示文字 def draw_shield_bar(surf, x, y, pct): pct = max(pct, 0) fill = (pct / 100) * BAR_LENGTH # 当前血量计算 outline_rect = pygame.Rect(x, y, BAR_LENGTH, BAR_HEIGHT) # 设置总血量条长度100 fill_rect = pygame.Rect(x, y, fill, BAR_HEIGHT) # 当前血量 pygame.draw.rect(surf, GREEN, fill_rect) # 绘制矩形绿色当前血量框 pygame.draw.rect(surf, WHITE, outline_rect, 2) # 绘制矩形白色底总血量框 2代表线条宽度默认为0 def draw_lives(surf, x, y, lives, img): for i in range(lives): img_rect = img.get_rect() img_rect.x = x + 30 * i img_rect.y = y surf.blit(img, img_rect) def newmob(): mob_element = Mob() all_sprites.add(mob_element) mobs.add(mob_element) # pygame.sprite.Sprite存储 图像数据 image 和 位置 rect 的 对象 class Explosion(pygame.sprite.Sprite): # 构造函数 def __init__(self, center, size): # 执行父类的构造函数 pygame.sprite.Sprite.__init__(self) self.size = size # 爆炸类型 self.image = explosion_anim[self.size][0] # 选择爆炸图片 self.rect = self.image.get_rect() # 爆炸图片矩形 self.rect.center = center # 设置爆炸矩形的中心点 self.frame = 0 # 动画开始时间 self.last_update = pygame.time.get_ticks() # 最后一次刷新的时间 self.frame_rate = 75 # 动画间隔时间 # 子类可以重写update方法,在每次刷新屏幕时,更新精灵位置 def update(self): # 获取当前时间 now = pygame.time.get_ticks() if now - self.last_update > self.frame_rate: # 将最后一次时间设置成当前时间 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 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((255,255,255)) # 设置飞机图片不透明 self.rect = self.image.get_rect() # 获得飞机图片的矩形 self.radius = 20 # 飞机大小 self.rect.centerx = WIDTH / 2 # 放在中间底部 左上角坐标(0,0) self.rect.bottom = HEIGHT - 10 self.speedx = 0 # 默认所在位置 self.speedy = 0 self.shield = 100 # 血量 self.shoot_delay = 250 ## 子弹发射时间间隔 self.last_shot = pygame.time.get_ticks() # 最后一次发射完成时间 self.lives = 3 # 生命 self.hidden = False # 飞机的隐身状态 self.hide_timer = pygame.time.get_ticks() # 飞机的隐身时间 self.power = 1 # 子弹的初始火力值 self.power_timer = pygame.time.get_ticks() # 子弹的火力时间 # 飞机的更新函数 def update(self): # 消弱飞机的火力 if self.power >= 2 and pygame.time.get_ticks() - self.power_time > POWERUP_TIME: self.power -= 1 self.power_time = pygame.time.get_ticks() # 恢复飞机 取消隐身 if self.hidden and pygame.time.get_ticks() - self.hide_timer > 1000: self.hidden = False self.rect.centerx = WIDTH / 2 self.rect.bottom = HEIGHT - 10 self.speedx = 0 # 初始位置在屏幕中间定义坐标为0 self.speedy = 0 ## 检测事件 keystate = pygame.key.get_pressed() if keystate[pygame.K_LEFT]: # 左键左移 self.speedx = -5 elif keystate[pygame.K_RIGHT]: # 右键右移 self.speedx = 5 ## 检测事件 keystate = pygame.key.get_pressed() if keystate[pygame.K_UP]: # 左键左移 self.speedy = -5 elif keystate[pygame.K_DOWN]: # 右键右移 self.speedy = 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 # 移动位置 self.rect.y += self.speedy # 飞机射击方法 def shoot(self): # 描述子弹位置该在哪里显示 # 当前时间 now = pygame.time.get_ticks() # 判断 当前时间 = 最后一次发射时间 > 子弹发射时间间隔 if now - self.last_shot > self.shoot_delay: # 发射子弹 # 将最后一次发射子弹时间更改为当前时间 self.last_shot = now if self.power == 1: # 子弹数量1 # 生产(创建)一颗子弹 bullet = Bullet(self.rect.centerx, self.rect.top) # 将子弹添加到精灵组合中 all_sprites.add(bullet) # 将子弹添加到子弹的精灵组合中 bullets.add(bullet) # 播放射击音效 shooting_sound.play() if self.power == 2: # 子弹数量2 bullet1 = Bullet(self.rect.left, self.rect.centery) bullet2 = Bullet(self.rect.right, self.rect.centery) all_sprites.add(bullet1) all_sprites.add(bullet2) bullets.add(bullet1) bullets.add(bullet2) shooting_sound.play() if self.power >= 3: # 子弹数量3 bullet1 = Bullet(self.rect.left, self.rect.centery) bullet2 = Bullet(self.rect.right, self.rect.centery) missile1 = Missile(self.rect.centerx, self.rect.top) # Missile shoots from center of ship all_sprites.add(bullet1) all_sprites.add(bullet2) all_sprites.add(missile1) bullets.add(bullet1) bullets.add(bullet2) bullets.add(missile1) shooting_sound.play() missile_sound.play() # 子弹火力增加函数 def powerup(self): self.power += 1 self.power_time = pygame.time.get_ticks() # 飞机的隐身函数 def hide(self): self.hidden = True self.hide_timer = pygame.time.get_ticks() self.rect.center = (WIDTH / 2, HEIGHT + 200) 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((255,255,255)) # 设置陨石图片不透明 self.image = self.image_orig.copy() # 复制陨石的图片 self.rect = self.image.get_rect() ## 陨石图片的矩形 self.radius = int(self.rect.width * .40 / 2) # 陨石的半径 self.rect.x = random.randrange(0, WIDTH - self.rect.width) # 陨石的x坐标 x随机值 范围: 0 ~ 屏幕宽度-陨石本身的宽度 self.rect.y = random.randrange(-150, -100) # 陨石的y方向移动速度 陨石只允许向下 不允许向上 ## 随机下落速度 self.speedx = random.randrange(-3, 3) # 陨石的x方向移动速度 陨石可以左右运动 self.speedy = random.randrange(5, 20) # 陨石的y方向移动速度 陨石只允许向下 不允许向上 ## 添加旋转 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: # in milliseconds 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): # 重新生成陨石(为陨石重新设定坐标) self.rect.x = random.randrange(0, WIDTH - self.rect.width) self.rect.y = random.randrange(-100, -40) self.speedy = random.randrange(1, 8) 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((255,255,255)) # 设置陨石图片不透明 self.image = self.image_orig.copy() # 复制陨石的图片 self.rect = self.image.get_rect() ## 陨石图片的矩形 self.radius = int(self.rect.width * .90 / 2) # 陨石的半径 self.rect.x = random.randrange(0, WIDTH - self.rect.width) # 陨石的x坐标 x随机值 范围: 0 ~ 屏幕宽度-陨石本身的宽度 self.rect.y = random.randrange(-150, -100) # 陨石的y方向移动速度 陨石只允许向下 不允许向上 ## 随机下落速度 self.speedx = random.randrange(-3, 3) # 陨石的x方向移动速度 陨石可以左右运动 self.speedy = random.randrange(5, 20) # 陨石的y方向移动速度 陨石只允许向下 不允许向上 ## 添加旋转 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: # in milliseconds 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): # 重新生成陨石(为陨石重新设定坐标) self.rect.x = random.randrange(0, WIDTH - self.rect.width) self.rect.y = random.randrange(-100, -40) self.speedy = random.randrange(1, 8) class Pow(pygame.sprite.Sprite): def __init__(self, center): pygame.sprite.Sprite.__init__(self) self.type = random.choice(['shield', 'gun']) # 随机选择补给 self.image = powerup_images[self.type] self.image.set_colorkey((255,255,255)) self.rect = self.image.get_rect() self.rect.center = center self.speedy = 2 # 补给下落速度 def update(self): self.rect.y += self.speedy if self.rect.top > HEIGHT: # 将出屏幕的补给kill掉 self.kill() class Bullet(pygame.sprite.Sprite): # 构造函数 # 飞机在发射子弹的时候,由飞机当前位置计算子弹出现的x,y坐标 def __init__(self, x, y): pygame.sprite.Sprite.__init__(self) self.image = bullet_img self.image.set_colorkey((255,255,255)) self.rect = self.image.get_rect() # 获取图片矩形 self.rect.bottom = y # 底部边y坐标 self.rect.centerx = x # 中心点x坐标 self.speedy = -10 # 子弹的移动速度 # 子弹的更新函数 def update(self): self.rect.y += self.speedy if self.rect.bottom < 0: # 子弹超出界面消失 self.kill() class Missile(pygame.sprite.Sprite): # 同子弹类一样 def __init__(self, x, y): pygame.sprite.Sprite.__init__(self) self.image = missile_img self.image.set_colorkey((255,255,255)) self.rect = self.image.get_rect() self.rect.bottom = y self.rect.centerx = x self.speedy = -10 def update(self): self.rect.y += self.speedy if self.rect.bottom < 0: self.kill() running = True menu_display = True while running: if menu_display: # 显示主菜单 定义函数 main_menu() # pygame延迟操作 pygame.time.wait(3000) # 停止播放主菜单背景音乐 pygame.mixer.music.stop() # 获得游戏运行背景音乐 pygame.mixer.music.load(path.join(sound_folder, 'y1030.wav')) pygame.mixer.music.play(-1) # 循环播放 # 将主菜单显示状态切换为False menu_display = False ## 创建所有组让所有精灵在一起,以方便更新 all_sprites = pygame.sprite.Group() # 创建飞机 player = Player() # 将飞机精灵加入到所有组中 all_sprites.add(player) ## 创建陨石的精灵组合 mobs = pygame.sprite.Group() for i in range(8): # 新建陨石 newmob() ## 创建子弹组和道具组 bullets = pygame.sprite.Group() powerups = pygame.sprite.Group() # 分数 score = 0 clock.tick(FPS) # 设定帧数 # 检测是否退出游戏 ESC for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: running = False # 利用精灵组合执行精灵的变化函数 all_sprites.update() ## 检查子弹是否击中陨石 陨石与玩家炮弹碰撞检测 pygame提供的精灵组合与精灵组合之间的碰撞检测函数 hits = pygame.sprite.groupcollide(mobs, bullets, True, True) for hit in hits: # 添加分数 score += 50 - hit.radius # 播放爆炸音效 random.choice(expl_sounds).play() # 产生爆炸效果 expl = Explosion(hit.rect.center, 'lg') # 将爆炸效果添加到精灵组合中 all_sprites.add(expl) # 随机产生相应奖励 if random.random() > 0.9: pow = Pow(hit.rect.center) all_sprites.add(pow) powerups.add(pow) newmob() # 产生新的陨石 ## 陨石与玩家炮弹碰撞检测 hits = pygame.sprite.spritecollide(player, mobs, True, pygame.sprite.collide_circle) for hit in hits: # 飞机减少生命值 player.shield -= hit.radius * 2 # 产生爆炸效果 陨石 expl = Explosion(hit.rect.center, 'sm') # 将爆炸效果添加到精灵组合中 all_sprites.add(expl) # 产生新的陨石 newmob() # 判断飞机的生命值是否小于等于0 if player.shield <= 0: player_die_sound.play() # 播放飞机去世音效 death_explosion = Explosion(player.rect.center, 'player') # 飞机爆炸效果 # 将爆炸效果添加到精灵组合中 all_sprites.add(death_explosion) # 飞机爆炸效果 player.hide() # 飞机隐身效果 player.lives -= 1 # 飞机的生命-1 player.shield = 100 # 重新设置飞机的生命值100 ## 玩家与道具的碰撞检测 hits = pygame.sprite.spritecollide(player, powerups, True) for hit in hits: # 生命值(盾)奖励 if hit.type == 'shield': player.shield += random.randrange(10, 30) if player.shield >= 100: player.shield = 100 # 火力值奖励 if hit.type == 'gun': player.powerup() # 判断飞机的生命是否为0 同时 飞机爆炸动画结束 if player.lives == 0 and not death_explosion.alive(): # 设置游戏状态为False running = False menu_display = False pygame.display.update() # 将游戏屏幕填充为黑色 screen.fill(BLACK) # 设置游戏运行背景图片 screen.blit(background, background_rect) # 绘制精灵到屏幕中 all_sprites.draw(screen) draw_text(screen, str(score), 18, WIDTH / 2, 10) # 绘制分数 draw_shield_bar(screen, 5, 5, player.shield) # 绘制生命条 draw_lives(screen, WIDTH - 100, 5, player.lives, player_mini_img) # 绘制小飞机 ## 所有东西画上去后显示在屏幕上 pygame.display.flip() pygame.quit()
返回至
射击游戏-ch17
。
导航菜单
个人工具
登录
名字空间
页面
讨论
变种
视图
阅读
查看源代码
查看历史
更多
搜索
导航
首页
社区主页
新闻动态
最近更改
随机页面
帮助
华师附中老三届
站群链接
社友网(sn)
产品百科(cpwiki)
产品与服务(sn)
社区支持农业(sn)
工具
链入页面
相关更改
特殊页面
页面信息