最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 从零开始手把手教你使用javascript+canvas开发一个塔防游戏02敌人自动寻路

    正文概述 掘金(豆约翰)   2020-12-29   519

    项目演示

    从零开始手把手教你使用javascript+canvas开发一个塔防游戏02敌人自动寻路

    项目演示地址:

    体验一下

    项目源码:

    项目源码

    代码结构

    从零开始手把手教你使用javascript+canvas开发一个塔防游戏02敌人自动寻路

    本节做完效果

    从零开始手把手教你使用javascript+canvas开发一个塔防游戏02敌人自动寻路

    Enemy.js

    //敌人类
    
    function Enemy(cxt,img,type,x,y,width,height){
    
        this.cxt = cxt;
        this.img = img;
        this.x = x;//55
        this.y = y;//0
        this.width = width;
        this.height = height;
        //敌人类型
        this.type = type;
    
        this.sp = 2;
        //移动的方向
        this.dir = null;
        //下个移动位置
        this.nextPosition = null;
    
        //记录已经走过的位置
        this.hadWalk = {};
    }
    
    Enemy.prototype = {
        //敌人在图片中对应的位置
        enemyMap : [{x:0,y:0},{x:40,y:0},{x:80,y:0},{x:120,y:0},{x:160,y:0},{x:200,y:0},{x:240,y:0},{x:280,y:0},{x:320,y:0},{x:360,y:0},
            {x:400,y:0},{x:440,y:0},{x:480,y:0},{x:520,y:0},{x:560,y:0},{x:600,y:0},{x:640,y:0},{x:680,y:0},{x:720,y:0},{x:760,y:0}],
        //画出敌人
        draw : function(){
            //冰冻中,画出冰冻图
            if(this.frozenTime > 0){
    
                Canvas.drawImg(this.cxt,this.img,this.enemyMap[this.type].x,this.enemyMap[this.type].y+40,this.width,this.height,this.x,this.y,this.width,this.height);
            }
            //画出正常图
            else Canvas.drawImg(this.cxt,this.img,this.enemyMap[this.type].x,this.enemyMap[this.type].y,this.width,this.height,this.x,this.y,this.width,this.height);
            //计算血量百分比
            var persen = Math.floor(this.life / this.maxLife * 100) / 2;
            //画出血量
            Canvas.fillRect(this.cxt,this.x-5,this.y-5,persen,3,"rgba(38,223,116,0.8)");
        },
    
        //更新敌人信息
        update : function(){
            //超出坐标
            if(this.x >= 500){
                return false;
            }
    
            var xIndex = parseInt(this.x / 50,10),//1
                yIndex = parseInt(this.y / 50,10);//0
            //判断是否有下个移动位置信息,或者下哥移动位置信息是否已经走到了
            if(!this.nextPosition ||
                ((this.x >= this.nextPosition.x - 5 && this.x <= this.nextPosition.x)
                    && (this.y >= this.nextPosition.y - 5 && this.y <= this.nextPosition.y))
            ){
                //走到最右侧
                if(xIndex + 1 >= 10){
                    xIndex = -1;
                }
                else{
                    //判断往下能否走
                    if(MapData[xIndex][yIndex+1] && !this.hadWalk[xIndex+"_"+(yIndex+1)]){
    
                        this.dir = "down";
                        yIndex += 1;
                    }
                    //判断往右能否走
                    else if(MapData[xIndex+1][yIndex]  && !this.hadWalk[(xIndex+1)+"_"+yIndex]){
                        this.dir = "right";
                        xIndex += 1;
                    }
                    else if(MapData[xIndex][yIndex-1] && !this.hadWalk[xIndex+"_"+(yIndex-1)]){
                        this.dir = "up";
                        yIndex -= 1;
                    }
                    else if(MapData[xIndex-1][yIndex] && !this.hadWalk[(xIndex-1)+"_"+yIndex]){
                        this.dir = "left";
                        xIndex -= 1;
                    }
                }
                //是否走到最右侧
                if(xIndex == -1){
                    this.nextPosition = {x:500,y:yIndex*50+5};
                }
                //设置下个移动位置
                else {
                    this.nextPosition = {x:xIndex*50+5,y:yIndex*50+5};
                    //记录已经走过的位置
                    this.hadWalk[xIndex+"_"+yIndex] = true;
                }
    
            }
    
    
            //移动
            switch(this.dir){
    
                case "down":
                    this.y += this.sp;
                    break;
                case "up":
                    this.y -= this.sp;
                    break;
                case "left":
                    this.x -= this.sp;
                    break;
                case "right":
                    this.x += this.sp;
                    break;
                default:
    
                    break;
            }
    
        }
    
    }
    
    //更新所有敌人信息
    function updateEnemy(){
    
        var enemy;
    
        for(var i=0,l=Game.enemyList.length;i<l;i++){
    
            enemy = Game.enemyList[i];
    
            if(!enemy)continue;
    
            enemy.update();
        }
    
    }
    
    //画出所有敌人
    function drawEnemy(){
    
        var enemy;
    
        for(var i=0,l=Game.enemyList.length;i<l;i++){
    
            enemy = Game.enemyList[i];
    
            if(!enemy)continue;
    
            enemy.draw();
        }
    
    }
    

    game.js修改

    从零开始手把手教你使用javascript+canvas开发一个塔防游戏02敌人自动寻路

    每50次循环出一个敌人 从零开始手把手教你使用javascript+canvas开发一个塔防游戏02敌人自动寻路

    从零开始手把手教你使用javascript+canvas开发一个塔防游戏02敌人自动寻路

    tool.js新增

    从零开始手把手教你使用javascript+canvas开发一个塔防游戏02敌人自动寻路

    自动寻路算法解析

    坐标系

    向右为x轴
    向下为y轴

    整个地图为500*500

       // 游戏对象
            var hero = {
                speed: 2, // 每秒移动的像素
                x: 55,
                y: 0,
                srcx:120,
                srcy:40,
               flood:50,
             
            //移动的方向
            dir:null,
            //下个移动位置
            nextPosition: null,
    
            //记录已经走过的位置
            hadWalk:{}
            };
    

    英雄像素转换为网格(10*10)坐标

     var xIndex = parseInt(hero.y / 50, 10),
     yIndex = parseInt(hero.x / 50, 10);
    

    最开始时, xIndex = 1 yIndex = 0

    初始时满足!hero.nextPosition

      if (!hero.nextPosition ||
                     ((hero.x >= hero.nextPosition.x - 5 && hero.x <= hero.nextPosition.x) && (hero.y >= hero.nextPosition.y - 5 && hero.y <= hero.nextPosition.y))
                 ) 
    

    进入后,满足往下走

     else {
                    //判断往下能否走
                    if(MapData[xIndex][yIndex+1] && !this.hadWalk[xIndex+"_"+(yIndex+1)]){
    
                        this.dir = "down";
                        yIndex += 1;
                    }
    

    此时 xIndex = 1 yIndex = 1 然后,

     //设置下个移动位置
                     else {
                         hero.nextPosition = {y: xIndex * 50 + 5, x: yIndex * 50 + 5};
                         //记录已经走过的位置
                         hero.hadWalk[xIndex + "_" + yIndex] = true;
                     }
    

    hero.nextPosition = { x:55,y:55 }

    然后,

     //移动
                switch(hero.dir){
    
                    case "down":
                        hero.y += hero.speed;
                        break;
                    case "up":
                        hero.y -= hero.speed;
                        break;
                    case "left":
                        hero.x -= hero.speed;
                        break;
                    case "right":
                        hero.x += hero.speed;
                        break;
                    default:
    
                        break;
                }
    

    此时,

    hero = {
               speed: 2, // 每秒移动的像素
               x: 2,
               y: 55,
    

    循环回去: 然后在hero.x未满足条件:

      if (!hero.nextPosition ||
                    ((hero.x >= hero.nextPosition.x - 5 && hero.x <= hero.nextPosition.x) && (hero.y >= hero.nextPosition.y - 5 && hero.y <= hero.nextPosition.y))
                ) 
    

    时,有25次(50/2),跳过上面条件里的代码,直接执行以下代码:

     //移动
                switch(hero.dir){
    
                    case "down":
                        hero.y += hero.speed;
                        break;
                    case "up":
                        hero.y -= hero.speed;
                        break;
                    case "left":
                        hero.x -= hero.speed;
                        break;
                    case "right":
                        hero.x += hero.speed;
                        break;
                    default:
    
                        break;
                }
    

    当再次hero.x满足条件:

      if (!hero.nextPosition ||
                    ((hero.x >= hero.nextPosition.x - 5 && hero.x <= hero.nextPosition.x) && (hero.y >= hero.nextPosition.y - 5 && hero.y <= hero.nextPosition.y))
                ) 
    

    时,重复之前的逻辑。
    如此循环。 such that

    项目源码:

    项目源码


    起源地下载网 » 从零开始手把手教你使用javascript+canvas开发一个塔防游戏02敌人自动寻路

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元