python练习,飞机大战(1)小甲鱼

    技术2025-02-01  10

    游戏基本设定 敌方共有大中小三款飞机 ,分为 高中低三种速度; 子弹的射程并非 全屏,而大概是屏幕长度的80%; 消灭小飞机需要 1发 子弹,中飞机 需要8发,大飞机需要20发; 每消灭一家小飞机得1000分 ,中飞机6000分,大飞机10000分; 每个30秒有一个随机的道具补给,分为两种道具,全屏炸弹 和双倍子弹; 全屏炸弹最多只能存放 3枚,双倍子弹可以维持18秒钟的效果; 游戏将根据分数逐步提高难度,难度的提高表示飞机数量的增多 以及速度的加快。 中飞机和大飞机增加血槽的显示;

    道具补给还未实现,逐渐提高难度也没有实现,剩下的都实现了。

    飞机的碰撞检测: 首先是类要继承pygame.sprite.Sprite,然后设置一个mask属性,用于完美检测,也就是飞机透明部分的内容碰撞不会击毁,self.mask = pygame.mask.from_surface(self.image),enemies_dowm = pygame.sprite.spritecollide(me, enemies, False,pygame.sprite.collide_mask)#me这个 精灵是否跟Enemies里面的任何一个精灵有碰撞,如果有碰撞,返回跟他碰撞的精灵列表。

    后面可能会继续写,不过现在我对爬虫比较好奇,想先学习爬虫了

    关于字体和图片资源,好像 不能添加附件,有想要的可以留邮箱发给你~ ^ ^!

    main.py

    import pygame import sys import traceback import myplane import enemy import supply import bullet from random import * from pygame.locals import * pygame.init() #混音器初始化 pygame.mixer.init() #屏幕大小,就是背景图片的大小 bg_size = width, height = 480, 700 screen = pygame.display.set_mode(bg_size) pygame.display.set_caption("飞机大战 -- Plane Wars") background = pygame.image.load("images/background.png").convert() BLACK = (0,0,0) GREEN = (0, 255, 0) RED = (255, 0, 0) WHITE = (255, 255, 255) #载入游戏音乐 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.1) 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 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)) #中弹图片索引 e1_destroy_index = 0 e2_destroy_index = 0 e3_destroy_index = 0 me_destroy_index = 0 #统计得分 score = 0 score_font = pygame.font.Font("font/font.ttf" , 36) #标志是否暂停游戏 paused = False #加载暂停图片 按下 还有鼠标放上 有不同效果 pause_nor_image = pygame.image.load("images/pause_nor.png").convert_alpha() pause_pressed_image = pygame.image.load("images/pause_pressed.png").convert_alpha() resume_nor_image = pygame.image.load("images/resume_nor.png").convert_alpha() resume_pressed_image = pygame.image.load("images/resume_pressed.png").convert_alpha() paused_rect = pause_nor_image.get_rect() # 设定暂停图标位置 paused_rect.left, paused_rect.top = width - paused_rect.width - 10,10 paused_image = pause_nor_image #用于切换我方飞机图片 switch_image = True #用于切换我方飞机时延时 delay = 100 clock = pygame.time.Clock() running = True #运行游戏 while running: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == MOUSEBUTTONDOWN: if event.button == 1 and paused_rect.collidepoint(event.pos): paused = not paused #修改暂停按钮的图标样式 elif event.type == MOUSEMOTION: if paused_rect.collidepoint(event.pos): #鼠标移动到图标上时 if paused: paused_image = resume_pressed_image else: paused_image = pause_pressed_image else: if paused: paused_image = resume_nor_image else: paused_image = pause_nor_image # 屏幕打印输出背景 screen.blit(background, (0, 0)) # 屏幕打印输出 # 绘制分数 score_text = score_font.render("Score:%s" % str(score), True, WHITE) # 把字符串转换成surface对象 screen.blit(score_text, (10, 5)) #主流层 if not paused: #检测用户的键盘操作 key_pressed = pygame.key.get_pressed() #获得一个序列,这个序列包含整个键盘按键的布尔类型值 if key_pressed[K_w] or key_pressed[K_UP]: #按下 上 me.moveUp() if key_pressed[K_s] or key_pressed[K_DOWN]: #按下 上 me.moveDown() if key_pressed[K_a] or key_pressed[K_LEFT]: #按下 上 me.moveLeft() if key_pressed[K_d] or key_pressed[K_RIGHT]: #按下 上 me.moveRight() #检测我放飞机是否被撞 enemies_dowm = pygame.sprite.spritecollide(me, enemies, False,pygame.sprite.collide_mask)#me这个 精灵是否跟Enemies里面的任何一个精灵有碰撞,如果有碰撞,返回跟他碰撞的精灵列表 if enemies_dowm: # me.active = False #这里注释了飞机就是无敌状态了!!! for e in enemies_dowm: e.active = False #屏幕绘制我放飞机 if me.active: if switch_image: screen.blit(me.image1, me.rect) else: screen.blit(me.image2, me.rect) else: # 毁灭,放死亡图组 if not (delay % 3): if e3_destroy_index == 0: me_down_sound.play() # 死亡声效 # 在窗口逐张打印 screen.blit(me.destroy_images[me_destroy_index], me.rect) # e3的索引下一个 打印到第六张 全部打印完毕,变量为0 me_destroy_index = (me_destroy_index + 1) % 4 if me_destroy_index == 0: # 死亡画面播放完毕 print("Game over") # 重生 running = False #发射子弹 if not(delay % 10): bullet1[bullet1_index].reset(me.rect.midtop) bullet1_index = (bullet1_index + 1) % BULLET1_NUM #监测子弹是否击中敌机 for b in bullet1: if b.active: b.move() screen.blit(b.image, b.rect) #被击中的敌机 enemy_hit = pygame.sprite.spritecollide(b, enemies,False, pygame.sprite.collide_mask) #如果子弹击中 if enemy_hit: b.active = False for e in enemy_hit: if e in mid_enemies or e in big_enemies: e.hit = True #表示被打到 了 e.energy -= 1 if e.energy == 0: e.active = False else: e.active = False #绘制大型敌机 for each in big_enemies: #检测是否活着 if each.active: each.move() if each.hit: #绘制被打到的特效 screen.blit(each.image_hit,each.rect) each.hit = False else: if switch_image: screen.blit(each.image1, each.rect) else: screen.blit(each.image2, each.rect) #绘制血量条 pygame.draw.line(screen, BLACK, \ (each.rect.left, each.rect.top - 5), \ (each.rect.right, each.rect.top -5), \ 2) #绘制直线,表明位置,宽度2个像素 #当生命大于20%显示绿色,否则显示红色 energy_remain = each.energy / enemy.BigEnemy.energy #当前剩余声明 if energy_remain > 0.2: energy_color = GREEN else: energy_color = RED pygame.draw.line(screen, energy_color, \ (each.rect.left, each.rect.top - 5), \ (each.rect.left + each.rect.width * energy_remain, \ each.rect.top - 5), 2) #即将出现在画面中会出现音效 if each.rect.bottom == -50: #在屏幕上方50个像素 enemy3_fly_sound.play(-1) else: #毁灭,放死亡图组 if not(delay % 3): if e3_destroy_index == 0: enemy3_down_sound.play() # 死亡声效 #在窗口逐张打印 screen.blit(each.destroy_images[e3_destroy_index], each.rect) #e3的索引下一个 打印到第六张 全部打印完毕,变量为0 e3_destroy_index = (e3_destroy_index + 1) % 6 if e3_destroy_index == 0: #死亡画面播放完毕 # enemy3_fly_sound.stop() enemy3_fly_sound.stop() score += 10000 each.reset() #重生 #绘制中型敌机 for each in mid_enemies: if each.active: each.move() if each.hit: screen.blit(each.image_hit, each.rect) each.hit = False else: screen.blit(each.image, each.rect) # 绘制血量条 pygame.draw.line(screen, BLACK, \ (each.rect.left, each.rect.top - 5), \ (each.rect.right, each.rect.top - 5), \ 2) # 绘制直线,表明位置,宽度2个像素 # 当生命大于20%显示绿色,否则显示红色 energy_remain = each.energy / enemy.MidEnemy.energy # 当前剩余声明 if energy_remain > 0.2: energy_color = GREEN else: energy_color = RED pygame.draw.line(screen, energy_color, \ (each.rect.left, each.rect.top - 5), \ (each.rect.left + each.rect.width * energy_remain, \ each.rect.top - 5), 2) else: #毁灭,放死亡图组 if not(delay % 3): if e2_destroy_index == 0: enemy2_down_sound.play() # 死亡声效 #在窗口逐张打印 screen.blit(each.destroy_images[e2_destroy_index], each.rect) #e3的索引下一个 打印到第六张 全部打印完毕,变量为0 e2_destroy_index = (e2_destroy_index + 1) % 4 if e2_destroy_index == 0: #死亡画面播放完毕 score += 6000 each.reset() #重生 #绘制小型敌机 for each in small_enemies: if each.active: each.move() screen.blit(each.image, each.rect) else: #毁灭,放死亡图组 if not(delay % 3): if not (delay % 3): if e1_destroy_index == 0: enemy1_down_sound.play() # 死亡声效 #在窗口逐张打印 screen.blit(each.destroy_images[e1_destroy_index], each.rect) #e3的索引下一个 打印到第六张 全部打印完毕,变量为0 e1_destroy_index = (e1_destroy_index + 1) % 4 if e1_destroy_index == 0: #死亡画面播放完毕 score += 1000 each.reset() #重生 #绘制暂停按钮 screen.blit(paused_image, paused_rect) #切换图片,只有被5整除才切换,一秒60帧,相当于一秒切换12次 if not(delay % 5): switch_image = not switch_image delay -= 1 if not delay: delay = 100 pygame.display.flip() clock.tick(60) #刷新率 if __name__ == "__main__": try: main() except SystemExit: pass except: traceback.print_exc() pygame.quit() input()

    enemy.py

    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.mask = pygame.mask.from_surface(self.image) self.rect.left, self.rect.top = \ randint(0, self.width - self.rect.width), \ randint(-5 * self.height, 0) 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.active = True self.speed = 2 # 用于完美碰撞 self.mask = pygame.mask.from_surface(self.image) self.rect.left, self.rect.top = \ randint(0, self.width - self.rect.width), \ randint(-10 * self.height, -self.height) #速度更慢,出现位置最少在一个屏幕之外,这样不会一开始就有中飞机 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.speed = 2 # 用于完美碰撞 self.mask = pygame.mask.from_surface(self.image1) self.rect.left, self.rect.top = \ randint(0, self.width - self.rect.width), \ randint(-15 * self.height, -5 * self.height) #速度更慢,出现位置最少在一个屏幕之外,这样不会一开始就有中飞机 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)

    bullet.py

    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 = True 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

    myplane.py

    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.mask = pygame.mask.from_surface(self.image1) #上下左右移动 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 #下移是加top属性的值, else: self.rect.bottom = self.height - 60 #如果飞机矩形判断框超过屏幕范围,那就把判断框底部与屏幕最低平行,减去的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

    结果:

    Processed: 0.008, SQL: 9