19坦克大战!

# coding=utf-8 
# Time    : 2018/8/4 9:20
# Author  : 云水君
# Email   : 632942444@qq.com
# 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() #开始游戏
运行效果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和...
    Java小辰阅读 848评论 2 1
  • 冬天很冷,保温杯里滚烫的热水渐渐冷却! 冬天很冷,多年不穿的厚毛衣厚毛裤和加绒裤,终于有了重见天日的时候! 冬天很...
    fiona小蘑菇阅读 137评论 0 1
  • 这几天,一直在听由何亚珂老师朗读的李雪老师的《当你遇见一个人》. 说的那些事例,或者有很多的对话内容,完全说的就我...
    小莲蓬儿阅读 232评论 0 0
  • 管宏洋读《活法》第二章 学习要点:仅是知道不行,贯彻落实才有意义。 学习感悟:坚持自己的原则原理,时刻保持一颗反省...
    管宏洋阅读 113评论 0 0