Python3——坦克大战

# coding=utf-8
# Version:python3.6.1
__date__ = ‘2018/9/20 18:51‘
__author__ = ‘Lgsp_Harold‘

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

# 坦克大战主窗口
class TankMain(object):
    width = 600
    height = 500
    my_tank_missile_list = []  # 我方子弹列表
    my_tank = None
    # enemy_list = [] # 敌方坦克列表
    wall=None
    enemy_list = pygame.sprite.Group()  # 敌方坦克的组
    explode_list = []
    enemy_missile_list=pygame.sprite.Group()

    # 开始游戏的方法
    def startGame(self):
        pygame.init()  # pygame模块初始化,加载系统的资源
        # 创建一个窗口,窗口大小(宽,高)、窗口的特性(0,RESIZEBLE,RULLscreem)
        screem = pygame.display.set_mode((TankMain.width, TankMain.height), 0, 32)
        pygame.display.set_caption("坦克大战")

        #   创建一堵墙
        TankMain.wall = Wall(screem,65,160,30,120)

        # my_tank=My_Tank(screem) # 创建一个我方坦克,坦克显示在屏幕的中下部位置
        TankMain.my_tank = My_Tank(screem)  # 创建一个我方坦克,坦克显示在屏幕的中下部位置
        if len(TankMain.enemy_list)==0:
            # enemy_list=[]
            for i in range(1, 6):   #   游戏开始时初始化5个敌方坦克
                # TankMain.enemy_list.append(Enemy_Tank(screem))
                TankMain.enemy_list.add(Enemy_Tank(screem))  # 把敌方坦克放到组里面

        while True:
            if len(TankMain.enemy_list) < 5:
                TankMain.enemy_list.add(Enemy_Tank(screem))  # 把敌方坦克放到组里面
            # color RGB(0,0,0)
            # 设置窗口屏幕背景颜色
            screem.fill((0, 0, 0))

            # 面向过程的写法
            # pygame.draw.rect(screem,(0,255,0),Rect(400,30,100,30),5)

            # 显示左上角的文字
            for i, text in enumerate(self.write_text(), 0):
                screem.blit(text, (0, 5 + (15 * i)))

            #   显示游戏中的墙,并且对墙和其他对象进行碰撞检测
            TankMain.wall.display()
            TankMain.wall.hit_tank()

            self.get_event(TankMain.my_tank,screem)  # 获取事件,根据获取事件进行处理
            if TankMain.my_tank:
                TankMain.my_tank.hit_enemy_missile()    #   我方坦克和敌方的炮弹碰撞检测
            if TankMain.my_tank and TankMain.my_tank.live:
                TankMain.my_tank.display()  # 在屏幕上显示我方坦克
                TankMain.my_tank.move()  # 在屏幕上移动的我方坦克
            else:
                # del(TankMain.my_tank)
                # TankMain.my_tank=None
                # print("Game Over")
                # sys.exit()
                TankMain.my_tank=None
            #   显示和随机移动所有的敌方坦克
            for enemy in TankMain.enemy_list:
                enemy.display()
                enemy.random_move()
                enemy.random_fire()

            #  显示所有的我方炮弹
            for m in TankMain.my_tank_missile_list:
                if m.live:
                    m.display()
                    m.hit_tank()    # 炮弹打中敌方坦克
                    m.move()
                else:
                    TankMain.my_tank_missile_list.remove(m)

            #  显示所有的敌方炮弹
            for m in TankMain.enemy_missile_list:
                if m.live:
                    m.display()
                    m.move()
                else:
                    TankMain.enemy_missile_list.remove(m)

            for explode in TankMain.explode_list:
                explode.display()

            # 显示重置
            time.sleep(0.05)  # 每次休眠0.05秒跳到下一帧
            pygame.display.update()

    # 获取所有的事件(敲击键盘,鼠标点击事件)
    def get_event(self, my_tank,screem):
        for event in pygame.event.get():
            if event.type == QUIT:  # 程序退出
                self.stopGame()
            if event.type == KEYDOWN and (not my_tank) and event.key == K_n:
                TankMain.my_tank = My_Tank(screem)
            if event.type == KEYDOWN and my_tank:
                if event.key == K_LEFT or event.key == K_a:
                    my_tank.direction = "L"
                    my_tank.stop = False
                    # my_tank.move()
                if event.key == K_RIGHT or event.key == K_d:
                    my_tank.direction = "R"
                    my_tank.stop = False
                    # my_tank.move()
                if event.key == K_UP or event.key == K_w:
                    my_tank.direction = "U"
                    my_tank.stop = False
                    # my_tank.move()
                if event.key == K_DOWN or event.key == K_s:
                    my_tank.direction = "D"
                    my_tank.stop = False
                    # my_tank.move()
                if event.key == K_ESCAPE:
                    self.stopGame()
                if event.key == K_SPACE:
                    m = my_tank.fire()
                    m.good = True  # 我方坦克发射的炮弹,好炮弹
                    TankMain.my_tank_missile_list.append(m)

            if event.type == KEYUP and my_tank:
                if event.key == K_LEFT or K_RIGHT or K_UP or K_DOWN:
                    my_tank.stop = True

            if event.type == MOUSEBUTTONUP:
                pass

    # 关闭游戏
    def stopGame(self):
        sys.exit()

    # 在游戏窗口内左上角显示文字内容
    def write_text(self):
        font = pygame.font.SysFont("方正兰亭超细黑简体", 16)  # 定义一个字体
        # 文字,抗锯齿,字体颜色
        text_sf1 = font.render("敌方坦克数量为:%d" % len(TankMain.enemy_list), True, (255, 0, 0))  # 根据字体创建一个文件的图像
        text_sf2 = font.render("我方坦克炮弹数量为:%d" % len(TankMain.my_tank_missile_list), True, (255, 0, 0))  # 根据字体创建一个文件的图像
        return text_sf1, text_sf2

# 坦克大战游戏中所有对象的父类
class BaseItem(pygame.sprite.Sprite):
    def __init__(self, screem):
        pygame.sprite.Sprite.__init__(self)
        # 所有对象共享的属性
        self.screem = screem

    # 把坦克对应图片显示在游戏窗口上
    # 在游戏屏幕中显示当前游戏的对象
    def display(self):
        if self.live:
            self.image = self.images[self.direction]
            self.screem.blit(self.image, self.rect) #   把图片画在屏幕上

# 坦克公共父类
class Tank(BaseItem):
    # 定义类属性,所有坦克对象高和宽都是一样
    width = 50
    height = 50

    def __init__(self, screem, left, top):
        super().__init__(screem)
        # self.screem=screem  # 坦克在移动或者显示过程中需要用到当前游戏的屏幕
        self.direction = ‘D‘  # 坦克的方向,默认方向向下(上下左右)
        self.speed = 5  # 坦克移动的速度
        self.stop = False
        self.images = {}  # 坦克的所有图片,key:方向,value:图片路径(surface)
        self.images[‘L‘] = pygame.image.load("../img/p1tankL.gif")
        self.images[‘R‘] = pygame.image.load("../img/p1tankR.gif")
        self.images[‘U‘] = pygame.image.load("../img/p1tankU.gif")
        self.images[‘D‘] = pygame.image.load("../img/p1tankD.gif")
        self.image = self.images[self.direction]  # 坦克的图片由方向决定
        self.rect = self.image.get_rect()
        self.rect.left = left
        self.rect.top = top
        self.live = True  # 决定坦克是否消灭了
        self.oldTop=self.rect.top
        self.oldLeft=self.rect.left

    def stay(self):
        self.rect.left=self.oldLeft
        self.rect.top=self.oldTop

    # 坦克移动方法
    def move(self):
        if not self.stop:  # 如果坦克不是停止状态
            self.oldLeft=self.rect.left
            self.oldTop=self.rect.top
            if self.direction == "L":  # 如果坦克的方向向左,那么只需要改坦克的left就可以了,left在减少
                if self.rect.left > 0:  # 判断坦克是否在左边的边界上
                    self.rect.left -= self.speed
                else:
                    self.rect.left = 0
            elif self.direction == "R":
                if self.rect.right < TankMain.width:
                    self.rect.right += self.speed
                else:
                    self.rect.right = TankMain.width
            elif self.direction == "U":
                if self.rect.top > 0:
                    self.rect.top -= self.speed
                else:
                    self.rect.top = 0
            elif self.direction == "D":
                if self.rect.bottom < TankMain.height:
                    self.rect.bottom += self.speed
                else:
                    self.rect.bottom = TankMain.height

    def fire(self):
        m = Missile(self.screem, self)
        return m

# 我方坦克类
class My_Tank(Tank):
    def __init__(self, screem):
        super().__init__(screem, 275, 400)  # 创建一个我方坦克,坦克显示在屏幕的中下部位置
        self.stop = True
        self.live = True

    def hit_enemy_missile(self):
        hit_list=pygame.sprite.spritecollide(self,TankMain.enemy_missile_list,False)
        for m in hit_list:  #   我方坦克中弹
            m.live=False
            TankMain.enemy_missile_list.remove(m)
            self.live=False
            explode = Explode(self.screem,self.rect)
            TankMain.explode_list.append(explode)

# 敌方坦克类
class Enemy_Tank(Tank):

    def __init__(self, screem):
        super().__init__(screem, randint(1, 5) * 100, 200)
        self.speed = 3
        self.step = 12  # 坦克按照某个方向移动的步数
        self.get_random_direction()

    def get_random_direction(self):
        r = randint(0, 4)  # 得到一个坦克移动方向和停止的随机数
        if r == 4:
            self.stop = True
        elif r == 2:
            self.direction = "L"
            self.stop = False
        elif r == 0:
            self.direction = "R"
            self.stop = False
        elif r == 1:
            self.direction = "U"
            self.stop = False
        elif r == 3:
            self.direction = "D"
            self.stop = False

    #   敌方坦克按照一个确定的随机方向,连续移动12步,然后再次改变方向
    def random_move(self):
        if self.live:
            if self.step == 0:
                self.get_random_direction()
                self.step = 12
            else:
                self.move()
                self.step -= 1

    #随机开火
    def random_fire(self):
        r=randint(0,50)
        if r==10:
            m=self.fire()
            TankMain.enemy_missile_list.add(m)
        else:
            return

# 炮弹类
class Missile(BaseItem):
    width = 5
    height = 5

    def __init__(self, screem, tank):
        super().__init__(screem)
        self.tank = tank
        self.direction = tank.direction  # 炮弹的方向由所发射的坦克方向决定
        self.speed = 12  # 炮弹移动的速度
        enemymissileImg = pygame.image.load("../img/enemymissile.gif")
        self.images = {}  # 炮弹的所有图片,key:方向,value:图片路径(surface)
        self.images[‘L‘] = enemymissileImg
        self.images[‘R‘] = enemymissileImg
        self.images[‘U‘] = enemymissileImg
        self.images[‘D‘] = enemymissileImg
        self.image = self.images[self.direction]  # 坦克的图片由方向决定
        self.rect = self.image.get_rect()  # 炮弹的边界
        #   炮弹坐标
        self.rect.left = tank.rect.left + (tank.width - self.width) / 2
        self.rect.top = tank.rect.top + (tank.height - self.height) / 2
        self.live = True  # 决定炮弹是否消灭了
        self.good = False

    def move(self):
        if self.live:  # 如果炮弹还存在
            if self.direction == "L":  # 如果坦克的方向向左,那么只需要改坦克的left就可以了,left在减少
                if self.rect.left > 0:  # 判断坦克是否在左边的边界上
                    self.rect.left -= self.speed
                else:
                    self.live = False
            elif self.direction == "R":
                if self.rect.right < TankMain.width:
                    self.rect.right += self.speed
                else:
                    self.live = False
            elif self.direction == "U":
                if self.rect.top > 0:
                    self.rect.top -= self.speed
                else:
                    self.live = False
            elif self.direction == "D":
                if self.rect.bottom < TankMain.height:
                    self.rect.bottom += self.speed
                else:
                    self.live = False

    #   炮弹击中坦克,第一种我方炮弹击中敌方坦克;第二种敌方炮弹击中我方坦克
    def hit_tank(self):
        if self.good:  # 如果炮弹是我方的炮弹
            hit_list = pygame.sprite.spritecollide(self,TankMain.enemy_list,False)
            for e in hit_list:
                e.live=False
                TankMain.enemy_list.remove(e)   # 如果敌方坦克被击中,从列表中删除敌方坦克
                self.live=False
                expload = Explode(self.screem,e.rect)   # 产生一个爆炸对象
                TankMain.explode_list.append(expload)

# 爆炸类
class Explode(BaseItem):
    def __init__(self, screem, rect):
        super().__init__(screem)
        self.live = True
        self.images = [pygame.image.load("../img/blast1.gif"),                       pygame.image.load("../img/blast2.gif"),                       pygame.image.load("../img/blast3.gif"),                       pygame.image.load("../img/blast4.gif"),                       pygame.image.load("../img/blast5.gif"),                       pygame.image.load("../img/blast6.gif"),                       pygame.image.load("../img/blast7.gif"),                       pygame.image.load("../img/blast8.gif")]
        self.step = 0
        self.rect = rect  # 爆炸的位置和发生爆炸前,炮弹碰到的坦克位置一样。在构建爆炸的时候把坦克的rect传递进来。

    # display方法在整个游戏运行过程中,循环调用,每隔0.1秒调用一次
    def display(self):
        if self.live:
            if self.step == len(self.images):  # 最后一张爆炸图片已经显示
                self.live = False
            else:
                self.image = self.images[self.step]
                self.screem.blit(self.image, self.rect)
                self.step+=1
        else:
            pass    #   删除该对象

#   游戏中的墙
class Wall(BaseItem):
    def __init__(self,screem,left,top,width,height):
        super().__init__(screem)
        self.rect=Rect(left,top,width,height)
        # self.left=left
        # self.top=top
        # self.width=width
        # self.height=height
        self.color=(255,0,0)
    def display(self):
        self.screem.fill(self.color,self.rect)

    #针对墙和其他坦克或者炮弹的碰撞检测
    def hit_tank(self):
        if TankMain.my_tank:
            is_hit=pygame.sprite.collide_rect(self,TankMain.my_tank)
            if is_hit:
                TankMain.my_tank.stop=True
                TankMain.my_tank.stay()

        if len(TankMain.enemy_list)!=0:
            hit_list=pygame.sprite.spritecollide(self,TankMain.enemy_list,False)
            for e in hit_list:
                e.stop=True
                e.stay()

        #   敌方炮弹击中墙,子弹消失
        if TankMain.enemy_missile_list:
            enemy_missile_hit_list=pygame.sprite.spritecollide(self,TankMain.enemy_missile_list,False)
            for e in enemy_missile_hit_list:
                e.stop=True
                e.live=False

        #   我方炮弹击中墙,子弹消失
        if TankMain.my_tank_missile_list:
            my_tank_missile_hit_list=pygame.sprite.spritecollide(self,TankMain.my_tank_missile_list,False)
            for e in my_tank_missile_hit_list:
                e.stop=True
                e.live=False

tankMain = TankMain()
tankMain.startGame()

if __name__ == ‘__main__‘:
    pass

图片下载:https://pan.baidu.com/s/1bqlGB0

原文地址:https://www.cnblogs.com/Harold-Hua/p/9732945.html

时间: 2024-11-15 06:44:52

Python3——坦克大战的相关文章

坦克大战系列(3.0版)

无论头上是怎样的天空,我准备承受任何风暴.--拜伦 本讲内容:坦克3.0版(面向对象的思想) 要求:画出我方坦克会动并且会发射子弹.画出敌人坦克 一.同一个包下建二个文件分别为:MyTankGame.Members(负责其它成员譬如:制造坦克.子弹等) MyTankGame类 /** * 功能:坦克游戏的3.0版本 * 1:画出坦克 * 2:实现我方坦克移动并且會發子彈,并 画出敌人的坦克 */ package a; import javax.swing.*; import java.awt.*

C++代码训练之坦克大战(2)

这一篇中,我们继续继续进行我们的坦克大战. 位置信息数据结构 在游戏设计过程中,需要记录大量的位置信息,如果仅仅使用(x,y)坐标很容易出错.这一篇中,我们先定义两个简单的数据结构用来保存点和矩形的信息. 在项目中新建Model目录,创建下面四个文件: 代码如下: Point.h #ifndef __POINT_H__ #define __POINT_H__ class Point { public: Point(int x = 0, int y = 0) : m_x(x), m_y(y){};

坦克大战(版本2.5-版本2.9)

版本2.5 功能:添加“血块”步骤:        1)添加blood类        2)添加必要的方法:eat方法等        3)让blood对象固定轨迹运动, 并在一定时间后消失 具体代码实现: 新增的blood类: 1 import java.awt.Color; 2 import java.awt.Graphics; 3 import java.awt.Rectangle; 4 5 //模拟血块,坦克吃了可以补血 6 public class Blood { 7 int x, y

脚本游戏之四: 坦克大战源码注释(待续。。。)

要点: 1.echo的高级用法,主要包括:颜色.位置定位输出等 2.trap 信号捕捉, kill 发送信号 3.捕捉用户输入,控制后台进程 参考:坦克大战 文章结尾的几段代码 总体: 多个进程后台并行运行, 前端一个段接受用户输入的代码,根据用户输入通过发送信号控制后台进程. 几乎每一个组件都是一个后台运行的函数. #!/bin/bash # BY: LingYi # DATE: 2016.02.23 #place temporary files tmpdir='/tmp' #u:up d:d

NYOJ 284 坦克大战 【BFS】+【优先队列】

坦克大战 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 Many of us had played the game "Battle city" in our childhood, and some people (like me) even often play it on computer now. What we are discussing is a simple edition of this game. Given a map that co

Java__线程---基础知识全面实战---坦克大战系列为例

今天想将自己去年自己编写的坦克大战的代码与大家分享一下,主要面向学习过java但对java运用并不是很熟悉的同学,该编程代码基本上涉及了java基础知识的各个方面,大家可以通过练习该程序对自己的java进行一下实战. 每个程序版本代码中,都附有相关注释,看完注释大家就可以对本程序设计有个很明显的思路.真的很有趣,想对java重新温习的同学完全不必再对厚厚的java基础书籍进行阅读了,在跟着本次代码练习并分析后,大家一定会对java各方面基础知识 尤其是线程的知识有更深一步的了解!!! 本次坦克大

【Cocos2D-x 3.5实战】坦克大战(1)环境配置

前言: 最近课比较少,空闲时间比较多,一有时间就东想西想,想着想着就突然想到做手机游戏(android)了,学习下CoCos2d.看了一些CoCos2D的相关文档和教程,觉得是时候实战了,但是苦于没有什么新奇的游戏点子,只有写下被儿时玩过的坦克大战了(主要素材好找).而这个系列的文章来记录下我的开发过程. 开发环境: Win7(x64) VS2012  下载地址: http://www.itellyou.cn/ Eclipse  下载地址:http://www.eclipse.org/downl

坦克大战系列(8.0版)

人生在勤,不索何获.--张衡 本讲内容:坦克大战8.0版(面向对象的思想) 一.解决:防止敌人坦克重叠运动 1.定义一个Vector容器,装所有敌人的坦克(为了得到所有坦克坐标) 2.定义一个方法getEts()可以得到敌人的坦克(为了得到所有坦克坐标) 3.在我的我的面板的构造方法调用getEts() 4.定义一个判断是否碰到了别的敌人的坦克的方法isTouchOtherEnemy() 5.在设置敌人坦克随机走动那调用isTouchOtherEnemy() 二.解决:我方坦克死亡(即隐身)后,

【跟我一起学Unity3D】做一个2D的90坦克大战之地图编辑器

从10月20号到现在,Unity3D也学了10天了,对于Unity3D也有了一个大致的了解,有必要做一个小游戏来检测一下自己的学习成果了.经过两天的努力,终于总算是做出来了一个可以玩的坦克大战了.首先讲讲我的设计目标: 1.地图编辑器 2.道具系统 3.简单AI系统 4.计分器 其中,最重要的就是地图编辑器了,其次到AI系统,其他几个都挺简单的. ---------------------------------------------------------------------------