一篇博文:带你用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.xpx -$frame.frame.ypx`
         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.enemyImg[this.type一篇博文:带你TypeScript入门,两万字肝爆,建议收藏!

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

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

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

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

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