19坦克大战!

# coding=utf-8 
# Time    : 2018/8/4 9:20
# Author  : 云水君
# Email   : [email protected]
# File    : 坦克大战.py
import pygame
from random import randint


class TankMain():
    """
    坦克大战主程序
    """
    # 用于存储敌方坦克对象,使用pygame的sprite类里的Group方法,方便碰撞检测
    em_tanks = pygame.sprite.Group()
    # 用于存储敌方坦克发射的子弹对象的列表
    em_bullet = []
    my_tank = ""  # 用于存储我方坦克对象的类字段
    width = 1000
    height = 700

    def start_game(self):
        screen = pygame.display.set_mode((TankMain.width, TankMain.height))
        screen.fill((10, 10, 10))
        pygame.display.set_caption("坦克大战")
        TankMain.my_tank = my = MyTank(500, 600)
        my.displays(screen)
        pygame.display.flip()
        my_bullet = []
        
        # 产生敌方坦克,并且位置不重复
        while len(TankMain.em_tanks) < 10:
            emtank = EmTank(randint(70, 900), randint(70, 400))
            if TankMain.em_tanks:
                flag = True
                for em in TankMain.em_tanks:
                    if pygame.sprite.collide_rect(em, emtank): # pygame自带的碰撞检测方法
                        flag = False
                        break
                if flag:
                    TankMain.em_tanks.add(emtank)
            else:
                TankMain.em_tanks.add(emtank)


        while True:
            pygame.time.delay(15)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    exit()
                if event.type == pygame.KEYUP:
                    my.move_state = "stop"
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_w or event.key == pygame.K_UP:
                        my.direction = "up"
                        my.move_state = "move"
                    if event.key == pygame.K_s or event.key == pygame.K_DOWN:
                        my.direction = "down"
                        my.move_state = "move"
                    if event.key == pygame.K_d or event.key == pygame.K_RIGHT:
                        my.direction = "right"
                        my.move_state = "move"
                    if event.key == pygame.K_a or event.key == pygame.K_LEFT:
                        my.direction = "left"
                        my.move_state = "move"
                    if event.key == pygame.K_SPACE:
                        missile = my.fire(screen)
                        my_bullet.append(missile)

            screen.fill((10, 10, 10))
            my.move()
            my.displays(screen)
            my.hit()
            if my.hp == 0:
                print("游戏结束")
                # exit()
            if len(TankMain.em_tanks) > 0:
                for em_tank in TankMain.em_tanks:
                    em_tank.move_state = "move"
                    em_tank.displays(screen)
                    em_tank.hit()
                    em_tank.move()
                    # em_tank.hit()
                    if em_tank.hp == 0:
                        TankMain.em_tanks.remove(em_tank)
                    rand_num = randint(1, 30)
                    if rand_num == 2:
                        rand_num = randint(1, 4)
                        if rand_num == 1:
                            em_tank.direction = "down"
                        if rand_num == 2:
                            em_tank.direction = "up"
                        if rand_num == 3:
                            em_tank.direction = "left"
                        if rand_num == 4:
                            em_tank.direction = "right"
                    rand_num = randint(1, 30)
                    if rand_num == 3:
                        TankMain.em_bullet.append(em_tank.fire(screen))
                for bullet in TankMain.em_bullet:
                    bullet.move()
                    bullet.displays(screen)
                    if bullet.move_state == "stop" or bullet.hp == 0:
                        TankMain.em_bullet.remove(bullet)

            for bullet in my_bullet:
                bullet.move()
                bullet.hit()
                bullet.displays(screen)
                if bullet.move_state == "stop" or bullet.hp == 0:
                    my_bullet.remove(bullet)
            pygame.display.update()


class Operation(pygame.sprite.Sprite): 
    # 游戏中所有类的父类,把公共的方法和属性写在这个类里面。继承pygame的Sprite类,不然无法使用自带的碰撞检测方法
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)  # 初始化Sprit类 必须要有
        self.direction = "up"  # 默认的朝向为向上
        self.speed = 2
        self.move_state = "stop"

    def move(self):
        self.oldx = x = self.rect.left  # 用于回到碰撞前的X坐标
        self.oldy = y = self.rect.top   # 用于回到碰撞前的y坐标
        if self.move_state == "move":
            # 根据朝向来决定移动,到了边界就停止
            if self.direction == "right":
                if x >= TankMain.width-self.size:
                    self.move_state = "stop"
                else:
                    self.rect.left += self.speed
            if self.direction == "left":
                if x <= 0:
                    self.move_state = "stop"
                else:
                    self.rect.left -= self.speed
            if self.direction == "down":
                if y >= TankMain.height - self.size:
                    self.move_state = "stop"
                else:
                    self.rect.top += self.speed
            if self.direction == "up":
                if y <= 0:
                    self.move_state = "stop"
                else:
                    self.rect.top -= self.speed

    def displays(self, screen):
        self.image = self.images[self.direction]
        screen.blit(self.image, self.rect)


class Tank(Operation):
    def __init__(self):
        super().__init__()
        self.hp = 2
        self.size = 60
        self.images = {}
        self.oldx = 0   # 用于回到碰撞前的X坐标,开始默认为0,游戏开始后随着移动自动更新
        self.oldy = 0   # 用于回到碰撞前的y坐标

    def fire(self, screen): # 调用开火的方法 就产生一颗子弹,并且子弹的坐标由调用者自己的坐标产生
        return Bullet(self.rect.left+int(self.size/2), self.rect.top+int(self.size/2), self.direction, screen)
    
    def stay(self): # 发生了碰撞,就调用此方法 回到碰撞前的坐标,达到不能穿透的效果
        self.rect.left = self.oldx
        self.rect.top = self.oldy

class MyTank(Tank):
    def __init__(self, x, y):
        super().__init__()
        self.images["left"] = pygame.image.load(r"./images/my_left.jpg")
        self.images["up"] = pygame.image.load(r"./images/my_up.jpg")
        self.images["right"] = pygame.image.load(r"./images/my_right.jpg")
        self.images["down"] = pygame.image.load(r"./images/my_down.jpg")
        self.image = self.images[self.direction]  # 坦克显示的图片 由坦克的朝向决定
        # 这里是Sprite碰撞检测的关键.get_rect()方法返回的是一个RECT,自带的碰撞检测方法靠的就是这个来判断碰撞
        self.rect = self.image.get_rect()  
        self.rect.left = x  # RECT有四个属性 其中.left表示x坐标
        self.rect.top = y   # .top 表示y坐标

    def hit(self):  # 碰撞检测
        # .spritecollide方法 判断一个对象与一个组的碰撞 返回的是一个在组中发生了碰撞的对象的列表
        hit_list = pygame.sprite.spritecollide(self, TankMain.em_bullet, False) # 判断与敌方子弹的碰撞
        for em_bullet in hit_list:
            em_bullet.hp -= 1
            self.hp -= em_bullet.hurt # 与子弹碰撞了 就血量减少 并且子弹的血量也减少(用于后面删除子弹)

        hit_list2 = pygame.sprite.spritecollide(self, TankMain.em_tanks, False)  #判断与敌方坦克的碰撞
        for em_tank in hit_list2:
            em_tank.stay() # 发生了碰撞,敌方坦克回到碰撞前的坐标
            self.stay()    # 自己本身也回到碰撞前的坐标



class EmTank(Tank):
    def __init__(self, x, y):
        super().__init__()
        self.images["left"] = pygame.image.load(r"./images/em_left.jpg")
        self.images["up"] = pygame.image.load(r"./images/em_up.jpg")
        self.images["right"] = pygame.image.load(r"./images/em_right.jpg")
        self.images["down"] = pygame.image.load(r"./images/em_down.jpg")
        self.image = self.images[self.direction]
        self.rect = self.image.get_rect()
        self.rect.left = x
        self.rect.top = y

    def hit(self):
        for em in TankMain.em_tanks:
            if em != self:
                # .collide_rect()方法用于判断两个对象的碰撞 返回布尔值
                if pygame.sprite.collide_rect(self, em): # 判断 敌方坦克之间的碰撞
                    em.stay()
                    self.stay()


class Bullet(Operation):
    def __init__(self, x, y, direction, screen):
        super().__init__()
        self.hurt = 1
        self.hp = 1
        self.speed = 10
        self.move_state = "move"
        self.direction = direction
        self.size = 5
        # 画圆的方法返回的对象就之间是一个RECT
        self.rect = pygame.draw.circle(screen, (255, 0, 0), (x, y), self.size)
        self.rect.left = x
        self.rect.top = y

    def displays(self, screen):
        pygame.draw.circle(screen, (255, 0, 0), (self.rect.left-int(self.size/2), self.rect.top-int(self.size/2)), self.size)

    def hit(self):
        hit_list = pygame.sprite.spritecollide(self, TankMain.em_tanks, False)  #检测我方的子弹与敌方坦克的碰撞
        for em_tank in hit_list:
            em_tank.hp -= self.hurt
            self.hp -= 1


if __name__ == '__main__':
    pygame.init()
    game = TankMain() #创建一个游戏对象
    game.start_game() #开始游戏
19坦克大战!_第1张图片
运行效果

你可能感兴趣的:(19坦克大战!)