一篇博文:带你用Typescript实现飞机大战,附(详细思路注释),建议收藏!

Posted 贪吃ღ大魔王

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇博文:带你用Typescript实现飞机大战,附(详细思路注释),建议收藏!相关的知识,希望对你有一定的参考价值。



站点结构:😉

在这里插入图片描述

图片素材:

地图:经典原图

在这里插入图片描述

飞机图片:

在这里插入图片描述

由于图片太多,这里用的是精灵图。为了方便,精灵图的数据存在json中。

json文件:

arts.json:
在这里插入图片描述

开发思路:

  • 创建地图
  • 发送请求将所有图片信息请求回来
  • 创建自己飞机
  • 发送子弹
  • 创建敌机
  • 处理击中和被击中

环境配置:

在这里插入图片描述

这里用的AMD 引入require.js

在这里插入图片描述

源码附注释见末尾 🌈




创建地图: 🌞

background.ts

  1. 背景div盒子
  2. 让背景图动起来,设置中间放两个图的div
  3. 单例的实例对象,地图背景相当于创建一个div,放到网页中间
  4. 设置地图样式

实现代码:

export default class Background{
    public bgWidth:number = 320
    public bgHeight:number = 568
    // 背景div盒子
    public bg:htmlDivElement;
    // 让背景图动起来需要的top值
    public bgImageTop:number = -this.bgHeight;
    // 设置中间放两个图的div
    public imgContainer:HTMLDivElement;
    // 单例的实例对象
    public static _instance:Background;
    private constructor(){
        // 地图背景相当于创建一个div,放到网页中间就好了
        this.bg = document.createElement('div')
        // 设置样式
        Tool.getInstance().setStyle(this.bg,{
            width:this.bgWidth + "px",
            height:this.bgHeight + "px",
            border:"1px solid #000",
            margin:"100px auto",
            position:"relative",
            overflow:"hidden",
        } as CSSStyleDeclaration)
        // 将背景插入到body中
        this.appendTo(this.bg,'body')
        
        // 创建一个大盒子 - 高度是背景盒子的一倍
        this.imgContainer = document.createElement('div')
        // 设置样式
        Tool.getInstance().setStyle(this.imgContainer,{
            width:this.bgWidth + "px",
            height:this.bgHeight * 2 + "px",
            position:"absolute",
            top:-this.bgHeight + "px",
            left:"0",
            fontSize:"0",
            zIndex:"-1"
        } as CSSStyleDeclaration)
        // 放入背景图
        this.setbg()
        this.bgMove()
    }

在这里插入图片描述




发送请求将所有图片信息请求回来:

imageData.ts

  1. 发送请求
  2. 获取响应的内容
  3. 根据数据中的 x y w h 创建div,图片定位
  4. 重新设置div样式

实现代码:

export default class ImageData extends MyTarget{
    private static _instance:ImageData;
    public imgdata:imgData|null = null;
    private constructor(){
        super()
        // 发送请求
        var xhr = new XMLHttpRequest()
        xhr.addEventListener('load',(e:Event)=>this.loadHandler(e))
        xhr.open('get','../../json/arts.json')
        xhr.send()
    }
    static getInstance():ImageData{
        if(!this._instance) this._instance = new ImageData();
        return this._instance;
    }
    // 处理ajax回调
    loadHandler(e:Event):void{
        // 获取ajax对象并获取响应的内容
        // console.log(e.currentTarget.response);
        var data = JSON.parse((e.currentTarget as XMLHttpRequest).response);
        this.imgdata = data;
        var evt = new MyEvent('readEnd')
        this.dispatchEvent(evt)
    }
    // 根据名称创建一个div
    createDiv(imgname:string):HTMLDivElement|null{
        var frame = this.searchData(imgname);
        if(!frame) return null;
        // 根据数据中的 x y w h 创建div
        var div:HTMLDivElement = document.createElement('div')
        this.setImgStyle(div,frame)
        return div;
    }
    // 替换图片定位
    replaceImgPosition(ele:HTMLDivElement,imgname:string):void{
        var frame = this.searchData(imgname)
        if(!frame) return;
        this.setImgStyle(ele,frame)
    }
    // 根据名称找对应数据
    searchData(imgname:string):Frame|undefined{
        // 创建div - 根据名称
        var frames:Array<Frame> = (this.imgdata as imgData).frames // 数组
        // 遍历数组找到 名称 对应的那一个对象
        var frame:Frame|null = null;
        for(var i=0;i<frames.length;i++){
            if(frames[i].filename === imgname){
                frame = frames[i]
            }
        }
        if(!frame) return;
        return frame
    }
    // 给div设置样式
    setImgStyle(ele:HTMLDivElement,frame:Frame):void{
        // 给div重新创建样式
        Tool.getInstance().setStyle(ele,{
            width:frame.frame.w + "px",
            height:frame.frame.h + "px",
            position:"absolute",
            // left:"0",
            // top:"0",
            backgroundImage:"url('../../images/arts.png')",
            backgroundPosition:`-${frame.frame.x}px -${frame.frame.y}px`
        } as CSSStyleDeclaration)
    }
}



创建飞机: 🎯

Mypalne.ts

  1. 创建飞机,设置飞机状态的图片下标切换
  2. 改变飞机的状态
  3. 设置飞机喷火
private static _instance:MyPlane;`在这里插入代码片`
    // 自己飞机
    public myplane:HTMLDivElement;
    // 自己飞机的状态
    public myplaneStatus:FlyOrDie = FlyOrDie.FLY;
    // 存活状态飞机的图片名称集合
    public myplaneLiveImgList:Array<string> = ['hero_fly_1','hero_fly_2'];
    public myplaneDieImgList:Array<string> = ['hero_blowup_1','hero_blowup_2','hero_blowup_3','hero_blowup_4'];
    // 设置切换图片的下标
    public index:number = 0;
    public timer:number = 0
    public speed:number = 0;
    private constructor(){
        // 创建自己飞机
        this.myplane = ImageData.getInstance().createDiv(this.myplaneLiveImgList[0]) as HTMLDivElement;
        // 创建自己飞机
        var myPlane:HTMLDivElement = ImageData.getInstance().createDiv('hero_fly_1') as HTMLDivElement;
        myPlane.style.zIndex = '9999'
    }
    

改变飞机状态:

setStatus(status:string){
        switch(status){
            case "fly":
                this.myplaneStatus = FlyOrDie.FLY
                this.firePen()
                break;
            case "die":
                this.myplaneStatus = FlyOrDie.DIE
                clearInterval(this.timer)
                this.speed = 200
                this.index = -1
                this.firePen()
                break;
        }
    }

飞机喷火:

firePen(){
        clearInterval(this.timer)
        this.timer = setInterval(()=>{
            this.index++;
            // 判断自己飞机状态
            switch(this.myplaneStatus){
                case "fly":
                    if(this.index===this.myplaneLiveImgList.length){
                        this.index = 0
                    }
                    // 调用替换图片名称的方法
                    ImageData.getInstance().replaceImgPosition(this.myplane,this.myplaneLiveImgList[this.index])
                    break;
                case "die":
                    if(this.index===this.myplaneDieImgList.length-1){
                        // 清除定时器
                        clearInterval(this.timer)
                    }
                    ImageData.getInstance().replaceImgPosition(this.myplane,this.myplaneDieImgList[this.index])
                    break;
            }
        },this.speed)
    }



子弹模块:

Bullet:

创建子弹,设置样式

实现代码:

public bullet:HTMLDivElement;
    static bulletList:Array<Bullet> = [];
    public num:number = 0
    public startTop:number = 0
    public speed:number = 2;
    public time:number = 20
    constructor(){
        this.bullet = ImageData.createDiv('bullet1')
        Bullet.bulletList.push(this)
        TimeManager.getInstance().add(this)
        this.setstyle()
    }
    setstyle(){
        Tool.getInstance().setStyle(this.bullet,{
            left:-10 + "px",
            top:-20 + "px"
        } as CSSStyleDeclaration)
    }

子弹移动

实现代码:

move(){
        this.num++;
        if(this.num===1){
            Tool.getInstance().setStyle(this.bullet,{
                left:MyPlane.myplane.offsetLeft + MyPlane.myplane.offsetWidth/2 - this.bullet.offsetWidth/2 + "px",
                top:MyPlane.myplane.offsetTop + "px"
            } as CSSStyleDeclaration)
            this.startTop = MyPlane.myplane.offsetTop;
        }

        // this.time--;
        // if(this.time>0) return;
        // this.time = 20
        this.startTop -= this.speed;
        this.bullet.style.top = this.startTop + "px"
        if(this.startTop<-this.bullet.offsetHeight){
            var index:number = Bullet.bulletList.indexOf(this)
            if(index<0) return;
            Bullet.bulletList.splice(index,1)
            Background.bg.removeChild(this.bullet)
            TimeManager.getInstance().remove(this)
        }
    }

在这里插入图片描述




敌机模块:

Enemy.ts:

创建敌机

  1. 三种敌机,每种敌机都有不同的爆炸状态

创建敌机

public enemy:HTMLDivElement;
    public enemyStatus:EnemyStatus = EnemyStatus.EnemyLive;
    public enemyImg:Array<IEnemy> = [
        {
            fly:['enemy1_fly_1'],
            hit:[],
            die:['enemy1_blowup_1','enemy1_blowup_2','enemy1_blowup_3','enemy1_blowup_4']
        },
        {
            fly:['enemy2_fly_1'],
            hit:['enemy2_hit_1'],
            die:['enemy2_blowup_1','enemy2_blowup_2','enemy2_blowup_3','enemy2_blowup_4','enemy2_blowup_5','enemy2_blowup_6','enemy2_blowup_7']
        },
        {
            fly:['enemy3_fly_1'],
            hit:['enemy3_hit_1','enemy3_hit_2'],
            die:['enemy3_blowup_1','enemy3_blowup_2','enemy3_blowup_3','enemy3_blowup_4']
        },
    ]
    static enemyList:Array<Enemy> = []
    public startTop:number = 0
    public speed = 1
    public type:number = 0
    public index:number = 0
    constructor(){
        var index:number = Math.floor(Math.random() * this.enemyImg.length)
        this.type = index;
        this.enemy = ImageData.createDiv(this.enemyImg[this.type]['fly'][this.index])
        TimeManager.getInstance().add(this)
        Enemy.enemyList.push(this)
    }
    setStatus(status:EnemyStatus){
        this.enemyStatus = status
    }

敌机移动,检测碰撞

 move(){
        this.startTop += this.speed
        this.enemy.style.top = this.startTop + "px"

        // 检测碰撞
        Bullet.bulletList.forEach(item=>{
            if(this.collide(item.bullet,this.enemy)){
                switch(this.enemyStatus){
                    case EnemyStatus.EnemyLive:
                        this.setStatus(EnemyStatus.EnemyHit)
                        var index:number = Bullet.bulletList.indexOf(item)
                        if(index<0) return;
                        Bullet.bulletList.splice(index,1)
                        Background.bg.removeChild(item.bullet)
                        TimeManager.getInstance().remove(item)
                        this.index = 0
                    break;
                    case EnemyStatus.EnemyHit:
                    break;
                    case EnemyStatus.EnemyDie:
                    break;

                }
            }
        })

        this.index++
        switch(this.enemyStatus){
            case EnemyStatus.EnemyLive:
            break;
            case EnemyStatus.EnemyHit:
                if(!this.以上是关于一篇博文:带你用Typescript实现飞机大战,附(详细思路注释),建议收藏!的主要内容,如果未能解决你的问题,请参考以下文章

一篇博文:带你TypeScript入门,两万字肝爆,建议收藏!

一篇博文:带你TypeScript入门,两万字肝爆,建议收藏!

canvas入门,一篇博文带你学会用代码绘画,直击实战案例!

canvas入门,一篇博文带你学会用代码绘画,直击实战案例!

一篇博文带你0基础 Html和css入门

一篇博文带你 jQuery入门,万字肝爆! 建议收藏~