美文网首页
Pygame 实现飞机大战

Pygame 实现飞机大战

作者: wjundong | 来源:发表于2020-02-18 22:54 被阅读0次
#coding=utf-8

import pygame
from pygame import *
from pygame.locals import *
from random import randint
import sys

SCREEN_WIDTH = 480
SCREEN_HEIGHT = 640


# 材质类
class Texture():
    def __init__(self):
        texture = pygame.image.load('resources/image/texture.png')
        self.enemy3_down6 = texture.subsurface( 0, 747, 166, 261 )
        self.enemy3_hit = texture.subsurface( 166, 750, 169, 258 )
        self.enemy3_n1 = texture.subsurface( 335, 750, 169, 258 )
        self.enemy3_n2 = texture.subsurface( 504, 750, 169, 258 )
        self.enemy3_down1 = texture.subsurface( 0, 486, 165, 261 )
        self.enemy3_down2 = texture.subsurface( 0, 225, 165, 261 )
        self.enemy3_down5 = texture.subsurface( 673, 748, 166, 260 )
        self.enemy3_down3 = texture.subsurface( 839, 748, 165, 260 )
        self.enemy3_down4 = texture.subsurface( 165, 486, 165, 261 )
        self.hero1 = texture.subsurface( 0, 99, 102, 126)
        self.hero2 = texture.subsurface( 165, 360, 102, 126)
        self.hero_blowup_n1 = texture.subsurface( 165, 234, 102, 126 )
        self.hero_blowup_n2 = texture.subsurface( 330, 624, 102, 126 )
        self.hero_blowup_n3 = texture.subsurface( 330, 498, 102, 126 )
        self.hero_blowup_n4 = texture.subsurface( 432, 624, 102, 126 )
        self.enemy2 = texture.subsurface( 0, 0, 69, 99 )
        self.enemy2_hit = texture.subsurface( 432, 525, 69, 99 )
        self.ufo2 = texture.subsurface( 102, 118, 60, 107 )
        self.enemy2_down1 = texture.subsurface( 534, 655, 69, 95 )
        self.enemy2_down2 = texture.subsurface( 603, 655, 69, 95 )
        self.enemy2_down3 = texture.subsurface( 672, 653, 69, 95 )
        self.enemy2_down4 = texture.subsurface( 741, 653, 69, 95 )
        self.ufo1 = texture.subsurface( 267, 398, 58, 88 )
        self.bomb = texture.subsurface( 810, 691, 63, 57 )
        self.enemy1_down1 = texture.subsurface( 267, 347, 57, 51 )
        self.enemy1_down2 = texture.subsurface( 873, 697, 57, 51 )
        self.enemy1_down3 = texture.subsurface( 267, 296, 57, 51 )
        self.enemy1_down4 = texture.subsurface( 930, 697, 57, 51 )
        self.game_pause_nor = texture.subsurface( 267, 251, 60, 45 )
        self.game_pause_pressed = texture.subsurface( 810, 646, 60, 45 )
        self.enemy1 = texture.subsurface( 534, 612, 57, 43 )
        self.bullet1 = texture.subsurface( 1004, 987, 9, 21 )
        self.bullet2 = texture.subsurface( 69, 78, 9, 21 )


class Bullet(pygame.sprite.Sprite):
    def __init__(self, image, initPos):
        super().__init__()
        # 加载资源
        self.image = image
        self.rect = self.image.get_rect()
        # 设置初始位置
        self.rect.x = initPos[0]
        self.rect.y = initPos[1]
        self.speed = 10

    def update(self):
        self.rect.y -= self.speed
        if self.rect.bottom < 0:
            self.kill()


      
class Enemy1(pygame.sprite.Sprite):
    def __init__(self, texture):
        super().__init__()
        # 加载资源
        self.texture = texture
        self.image = texture.enemy1
        self.rect = self.image.get_rect()
        # 随机生成的位置
        self.rect.x = randint(0, SCREEN_WIDTH - self.rect.width)
        self.rect.y = randint(0, 30)
        # 飞行速度
        self.speed = 4
        self.downIndex = 0

    def finishDownAnimation(self):
        self.downIndex += 1
        if self.downIndex == 4:
            self.image = self.texture.enemy1_down1
        elif self.downIndex == 8:
            self.image = self.texture.enemy1_down2
        elif self.downIndex == 12:
            self.image = self.texture.enemy1_down3
        elif self.downIndex == 16:
            self.image = self.texture.enemy1_down4
        elif self.downIndex == 20:
            self.kill()
            return True
        return False

    def update(self):
        self.rect.y += self.speed
        # if self.life < 0:

        if self.rect.top > SCREEN_HEIGHT:
            self.kill()

class Enemy1Group():
    def __init__(self, texture):
        # 生成间隔
        self.texture = texture
        self.frameIndex = 0
        self.createSpan = 30
        self.group = pygame.sprite.Group()
    
    def createEnemy(self):
        self.frameIndex += 1
        if self.frameIndex > self.createSpan:
            self.group.add(Enemy1(self.texture))
            self.frameIndex = 0

# 中型敌机   
class Enemy2(pygame.sprite.Sprite):
    def __init__(self, texture, screen):
        super().__init__()
        # 加载资源
        self.texture = texture
        self.image = texture.enemy2
        self.screen = screen
        self.rect = self.image.get_rect()
        # 随机生成的位置
        self.rect.x = randint(0, SCREEN_WIDTH - self.rect.width)
        self.rect.y = randint(0, 30)
        # 飞行速度
        self.speed = 2
        
        # 生命值
        self.life = 100
        # 防御值
        self.downIndex = 0
        # 血槽图层
        self.bloodBox = pygame.Surface((self.rect.width, 2))
        
    # 完成被击中动画
    def finishDownAnimation(self):
        self.downIndex += 1
        if self.downIndex == 4:
            self.image = self.texture.enemy2_down1
        elif self.downIndex == 8:
            self.image = self.texture.enemy2_down2
        elif self.downIndex == 12:
            self.image = self.texture.enemy2_down3
        elif self.downIndex == 16:
            self.image = self.texture.enemy2_down4
        elif self.downIndex == 20:
            return True
        return False

    # 被击中, 返回是否死亡
    def behit(self, type):
        if self.life > 0:
            if type == 1:
                self.life -= 30
            elif type == 2:
                self.life -= 50
            elif type == 3:
                self.life -= 100

    # 绘制血量
    def drawBlood(self):
        self.bloodBox.fill((255, 255, 255, 255))
        pygame.draw.rect(self.bloodBox, [237, 28, 36, 90], [0, 0, int(self.rect.width*(self.life/100)), 2])
        self.screen.blit(self.bloodBox, (self.rect.x, self.rect.y))

    def update(self):
        self.drawBlood()
        if self.life <= 0:
            if self.finishDownAnimation():
                self.kill()
        self.rect.y += self.speed
        # if self.life < 0:
        if self.rect.top > SCREEN_HEIGHT:
            self.kill()

class Enemy2Group():
    def __init__(self, texture):
        # 生成间隔
        self.texture = texture
        self.frameIndex = 0
        self.createSpan = 200
        self.group = pygame.sprite.Group()
    
    def collide(self, bulletGroup):
        for ememy in self.group:
            if pygame.sprite.spritecollide(ememy, bulletGroup, True):
                if ememy.behit(1):
                    self.kill()

    def createEnemy(self, screen):
        self.frameIndex += 1
        if self.frameIndex > self.createSpan:
            self.createSpan = randint(200, 500)
            self.group.add(Enemy2(self.texture, screen))
            self.frameIndex = 0


class enemy3Bullet(pygame.sprite.Sprite):
    def __init__(self, image, initPos):
        super().__init__()
        # 加载资源
        self.image = image
        self.rect = self.image.get_rect()
        # 设置初始位置
        self.rect.x = initPos[0]
        self.rect.y = initPos[1]
        self.speed = 1

    def update(self):
        x = randint(-1, 1)
        self.rect.y += self.speed
        if self.rect.bottom < 0:
            self.kill()


class Enemy3(pygame.sprite.Sprite):
    def __init__(self, texture, screen):
        super().__init__()
        # 加载资源
        self.texture = texture
        self.image = texture.enemy3_n2
        self.screen = screen
        self.rect = self.image.get_rect()
        # 随机生成的位置
        self.rect.x = randint(0, SCREEN_WIDTH - self.rect.width)
        self.rect.y = 10
        # 飞行速度
        self.speed = 0
        # 生命值
        self.life = 1000
        self.downIndex = 0
        # 血槽图层
        self.bloodBox = pygame.Surface((self.rect.width, 2))
        # 敌人子弹精灵组
        self.bulletGroup = pygame.sprite.Group()

    def finishDownAnimation(self):
        self.downIndex += 1
        if self.downIndex == 4:
            self.image = self.texture.enemy3_down1
        elif self.downIndex == 8:
            self.image = self.texture.enemy3_down2
        elif self.downIndex == 12:
            self.image = self.texture.enemy3_down3
        elif self.downIndex == 16:
            self.image = self.texture.enemy3_down4
        elif self.downIndex == 20:
            self.image = self.texture.enemy3_down5
        elif self.downIndex == 25:
            self.image = self.texture.enemy3_down6
        elif self.downIndex == 30:
            return True
        return False

    # 被击中, 返回是否死亡
    def behit(self, type):
        if self.life > 0:
            if type == 1:
                self.life -= 30
            elif type == 2:
                self.life -= 50
            elif type == 3:
                self.life -= 100

    # 绘制血量
    def drawBlood(self):
        self.bloodBox.fill((255, 255, 255, 255))
        pygame.draw.rect(self.bloodBox, [237, 28, 36, 90], [0, 0, int(self.rect.width*(self.life/1000)), 2])
        self.screen.blit(self.bloodBox, (self.rect.x, self.rect.y))
 
    def update(self):
        self.drawBlood()
        if self.life <= 0:
            if self.finishDownAnimation():
                self.kill()
        self.rect.y += self.speed
        # if self.life < 0:
        if self.rect.top > SCREEN_HEIGHT:
            self.kill()

class Enemy3Group():
    def __init__(self, texture):
        # 生成间隔
        self.texture = texture
        self.frameIndex = 0
        self.createSpan = 300
        self.group = pygame.sprite.Group()
    
    def collide(self, bulletGroup):
        for ememy in self.group:
            if pygame.sprite.spritecollide(ememy, bulletGroup, True):
                if ememy.behit(1):
                    self.kill()

    def createEnemy(self, screen):
        self.frameIndex += 1
        if self.frameIndex > self.createSpan:
            self.createSpan = randint(500, 1000)
            self.group.add(Enemy3(self.texture, screen))
            self.frameIndex = 0

# 物资类
class Supply(pygame.sprite.Sprite):
    def __init__(self, texture):
        super().__init__()
        # self.type = randint(0, 3)
        # if self.type == 1:
        self.image = texture.bomb
        self.rect = self.image.get_rect()
        # 随机生成位置
        self.rect.x = randint(0, SCREEN_WIDTH - self.rect.width)
        self.rect.y = 0
        self.speed = 1
        self.moveIndex = 1
        self.direction = 1

    def update(self):
        self.moveIndex -= 1
        self.rect.x += self.speed*self.direction
        self.rect.y += self.speed

        if self.moveIndex <= 0:
            self.moveIndex = randint(0, 120)
            self.direction = randint(-1, 1)

        if self.rect.top > SCREEN_HEIGHT:
            self.kill()


class SupplyGroup():
    def __init__(self, texture):
        self.texture = texture
        self.frameIndex = 0
        self.createSpan = 50
        self.group = pygame.sprite.Group()

    def createSupply(self, screen):
        self.frameIndex += 1
        if self.frameIndex > self.createSpan:
            self.createSpan = randint(100, 500)
            self.group.add(Supply(self.texture))
            self.frameIndex = 0


class Player(pygame.sprite.Sprite):
    def __init__(self, texture, screen):
        super().__init__()
        # 加载资源
        self.screen = screen
        self.texture = texture
        self.image = texture.hero1
        self.rect = self.image.get_rect()
        # 设置初始位置
        self.initpos = [200, 500]
        self.rect.x, self.rect.y = self.initpos 
        # 设置飞机速度
        self.shootSpan = 10 
        self.speed = 6
        # 设置帧数
        self.frameIndex = 0
        self.MAX_FRAME_INDEX = 120
        self.life = 100
        # 由玩家控制的子弹精灵组
        self.bulletGroup = pygame.sprite.Group()
        self.bulletType = 1
        # 血槽图层
        self.bloodBox = pygame.Surface((self.rect.width, 4))
        self.downIndex = 0

    
    # 飞机飞行动画
    def flightAnimation(self):
        # 每 30 帧更换一次图片
        if self.frameIndex % 30 == 0:
            if self.image == self.texture.hero1:
                self.image = self.texture.hero2
            else: 
                self.image = self.texture.hero1
    # 绘制血量
    def drawBlood(self):
        self.bloodBox.fill((255, 255, 255, 255))
        pygame.draw.rect(self.bloodBox, [0, 128, 64, 90], [0, 0, int(self.rect.width*(self.life/100)), 4])
        self.screen.blit(self.bloodBox, (self.rect.left, self.rect.bottom))

    # 飞机移动方法
    def moveUp(self):
        self.rect.y -= self.speed
        if self.rect.top < 0:
            self.rect.top = 0

    def moveDown(self):
        self.rect.y += self.speed
        if self.rect.bottom > SCREEN_HEIGHT:
            self.rect.bottom = SCREEN_HEIGHT

    def moveLeft(self):
        self.rect.x -= self.speed
        if self.rect.left < 0:
            self.rect.left = 0

    def moveRight(self):
        self.rect.x += self.speed
        if self.rect.right > SCREEN_WIDTH:
            self.rect.right = SCREEN_WIDTH

    # 射击函数
    def shoot(self):
        if self.frameIndex % self.shootSpan == 0:
            if self.bulletType == 1:
                self.bulletGroup.add(Bullet(self.texture.bullet1, self.rect.midtop))
            elif self.bulletType == 2:
                self.bulletGroup.add(Bullet(self.texture.bullet2, self.rect.midtop))
    
    def finishDownAnimation(self):
        self.downIndex += 1
        if self.downIndex == 5:
            self.image = self.texture.hero_blowup_n1
        elif self.downIndex == 10:
            self.image = self.texture.hero_blowup_n2
        elif self.downIndex == 15:
            self.image = self.texture.hero_blowup_n3
        elif self.downIndex == 20:
            self.image = self.texture.hero_blowup_n4
        elif self.downIndex == 25:
            return True
        return False


    def behit(self):
        if self.life >= 0:
            self.life -= 10

    # 碰撞检测
    def collide(self, ememyGroup):
        if pygame.sprite.spritecollide(self, ememyGroup, True):
            self.behit()

    # 获取物资检测
    def supplyCollide(self, supplyGroup):
        if pygame.sprite.spritecollide(self, supplyGroup, True):
            supplyType = randint(1, 3)
            if supplyType == 1:
                self.bulletType = 1
            elif supplyType == 2:
                self.bulletType = 2
            elif supplyType == 3:
                self.life += 100 - self.life


    def update(self):
        self.drawBlood()
        if self.life <= 0:
            if self.finishDownAnimation():
                self.kill()

        self.frameIndex += 1
        if(self.frameIndex > self.MAX_FRAME_INDEX):
            frameIndex = 0
        self.flightAnimation()
        self.shoot()


if __name__ == "__main__":

    # 初始化窗口
    pygame.init()
    screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
    pygame.display.set_caption('飞机大战')
    colck = pygame.time.Clock()
    
    # 加载背景图片和导入所有材质
    background = pygame.image.load('resources/image/background.png') 
    gameover = pygame.image.load('resources/image/gameover.png') 
    texture = Texture()
    
    # 创建敌人
    enemy1Group = Enemy1Group(texture)
    enemy2Group = Enemy2Group(texture)
    enemy3Group = Enemy3Group(texture)
    # 创建击毁敌人组
    enemy1DownGroup = pygame.sprite.Group()
    enemy2DownGroup = pygame.sprite.Group()
    enemy3DownGroup = pygame.sprite.Group()

    # 创建玩家
    player = Player(texture, screen)
    spriteGroup = pygame.sprite.Group()
    spriteGroup.add(player)

    # 物资类型
    supplyGroup = SupplyGroup(texture)

    yindex = 0
    while True:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            
        # 检测按键按下
        keys = pygame.key.get_pressed()

        if(keys[pygame.K_w]):
            player.moveUp()

        if(keys[pygame.K_s]):
            player.moveDown()

        if(keys[pygame.K_a]):
            player.moveLeft()

        if(keys[pygame.K_d]):
            player.moveRight()
        
        # 动态背景
        screen.blit(background, (0, yindex))
        screen.blit(background, (0, yindex - SCREEN_HEIGHT))
        yindex += 10
        if(yindex >= SCREEN_HEIGHT):
            yindex = 0
        
        enemy1DownGroup.add(pygame.sprite.groupcollide(enemy1Group.group, player.bulletGroup, False, True))
        for enemy1Down in enemy1DownGroup:
            # 完成击毁动画再删除
            if enemy1Down.finishDownAnimation() == True:
                enemy1DownGroup.remove(enemy1Down)
        
        # 碰撞检测
        enemy2Group.collide(player.bulletGroup)
        enemy3Group.collide(player.bulletGroup)
        player.collide(enemy1Group.group)
        player.collide(enemy2Group.group)
        player.supplyCollide(supplyGroup.group)

        # 更新玩家状态
        player.bulletGroup.draw(screen)
        player.bulletGroup.update()
        spriteGroup.draw(screen)
        spriteGroup.update()

        # 更新敌人状态
        enemy1Group.createEnemy()
        enemy1Group.group.draw(screen)
        enemy1Group.group.update()
        enemy2Group.createEnemy(screen)
        enemy2Group.group.draw(screen)
        enemy2Group.group.update()
        enemy3Group.createEnemy(screen)
        enemy3Group.group.draw(screen)
        enemy3Group.group.update()

        # 更新物资状态
        supplyGroup.createSupply(screen)
        supplyGroup.group.draw(screen)
        supplyGroup.group.update()

        if player.life <= 0:
            screen.blit(gameover, (0, 0))
        
        # 更新屏幕
        # pygame.display.update()
        pygame.display.flip()
        colck.tick(60)
        

运行效果


运行效果.PNG
碰撞爆炸.PNG
碰撞爆炸.PNG 游戏结束.PNG 运行效果.PNG 空中物资.PNG

材质资源链接 提取码:e7rh

相关文章

网友评论

      本文标题:Pygame 实现飞机大战

      本文链接:https://www.haomeiwen.com/subject/oztofhtx.html