一篇博文:带你用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(){
   
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贪吃ღ大魔王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值