Javascript HTML5画布-敌人射击

Javascript HTML5画布-敌人射击,javascript,canvas,trigonometry,Javascript,Canvas,Trigonometry,我正在用HTML5画布制作一个游戏。现在我正试图让敌人(地空炮)可以朝玩家(飞机)的方向射击 我的游戏使用2个数组根据其中的值制作地图。因为游戏在通过地图之前不知道要在屏幕上放置多少敌人,所以我让它创建一个带有随机id的新敌人,并让它将其添加到一个对象中,以便在每次遇到地图上的敌人值时跟踪敌人 问题是当敌人向飞机射击时,他们都是以相同的角度射击,而不是以特定情况所需的角度射击 问题是:如何让每个敌人以正确的角度向玩家射击 我意识到这个问题/解释可能有点令人困惑,但请试一试。最好先看看第222-2

我正在用HTML5画布制作一个游戏。现在我正试图让敌人(地空炮)可以朝玩家(飞机)的方向射击

我的游戏使用2个数组根据其中的值制作地图。因为游戏在通过地图之前不知道要在屏幕上放置多少敌人,所以我让它创建一个带有随机id的新敌人,并让它将其添加到一个对象中,以便在每次遇到地图上的敌人值时跟踪敌人

问题是当敌人向飞机射击时,他们都是以相同的角度射击,而不是以特定情况所需的角度射击

问题是:如何让每个敌人以正确的角度向玩家射击

我意识到这个问题/解释可能有点令人困惑,但请试一试。最好先看看第222-257行(updateEntity函数)。(请注意,这是一个与我的真实游戏代码不同的代码示例,它不是最好的。)

谷歌硬盘上的代码:

JS小提琴:

全部代码:

<center><canvas id = "gameCanvas" width = "500" height = "500" style = "border:1px solid navy;"></canvas></center>
var canvas, ctx;
var clip = {};
var arsenal = {};
var enemyClip = {};
var keyDown = {};
var enemy = {};
window.onload = function() {
    canvas = document.getElementById("gameCanvas");
    ctx = canvas.getContext("2d");
    for (var i = 0; i < 3; i++) {
        createEnemy(Math.random(), i * 100 + 140);
    }
    setInterval(function() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        update();
    }, 1000 / 30);
}
var player = {
    x: 240,
    y: 240,
    w: 20,
    h: 20,
    color: "navy",
    alive: true,
    canShoot: true,
    canNuke: true,
    facingRight: true,
    draw: function() {
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.w, this.h);
    },
    shoot: function() {
        if (player.canShoot) {
            player.canShoot = false;
            if (player.facingRight) {
                createPlayerBullet(Math.random(), player.x + player.w, player.y + player.h / 2, true);
            } else {
                createPlayerBullet(Math.random(), player.x, player.y + player.h / 2, false);
            }
            setTimeout(function() {
                player.canShoot = true;
            }, 750);
        }
    },
    nuke: function() {
        if (player.canNuke) {
            player.canNuke = false;
            createNuke(Math.random(), player.x + player.w / 2, player.y + player.h);
            setTimeout(function() {
                player.canNuke = true;
            }, 2000);
        }
    }
}
//var enemy = {
//  x:240,
//  y:480,
//  w:20,
//  h:20,
//  color:"maroon",
//  alive:true,
//  canShoot:true,
//  
//  draw:function(){
//      ctx.fillStyle = this.color;
//      ctx.fillRect(this.x, this.y, this.w, this.h);
//  },
//  
//  shoot:function(){
//      if(enemy.canShoot){
//          enemy.canShoot = false;
//      
//          if(player.x >= enemy.x && player.y <= enemy.y){// Top Right: TF, Bottom Right: TT, Bottom Left: FT, Top Left: FF
//              createEnemyBullet(Math.random(), enemy.x + enemy.w/2, enemy.y, player.x, player.y, true, false); // True equals ___ is greater than
//          }else if(player.x >= enemy.x && player.y >= enemy.y){
//              createEnemyBullet(Math.random(), enemy.x + enemy.w/2, enemy.y, player.x, player.y, true, true);
//          }else if(player.x <= enemy.x && player.y >= enemy.y){
//              createEnemyBullet(Math.random(), enemy.x + enemy.w/2, enemy.y, player.x, player.y, false, true);
//          }else if(player.x <= enemy.x && player.y <= enemy.y){
//              createEnemyBullet(Math.random(), enemy.x + enemy.w/2, enemy.y, player.x, player.y, false, false);
//          }
//          
//          setTimeout(function(){
//              enemy.canShoot = true;
//          }, 750);
//      }
//  }
//}
var createEnemy = function(ID, X) {
    var e = {
        x: X,
        y: 480,
        w: 20,
        h: 20,
        color: "maroon",
        alive: true,
        canShoot: true,
        id: ID,
        draw: function() {
            ctx.fillStyle = this.color;
            ctx.fillRect(this.x, this.y, this.w, this.h);
        },
        shoot: function() {
            if (this.canShoot) {
                this.canShoot = false;
                if (player.x >= this.x && player.y <= this.y) { // Top Right: TF, Bottom Right: TT, Bottom Left: FT, Top Left: FF
                    createEnemyBullet(Math.random(), this.x + this.w / 2, this.y, player.x, player.y, true, false); // True means greater than
                } else if (player.x >= this.x && player.y >= this.y) {
                    createEnemyBullet(Math.random(), this.x + this.w / 2, this.y, player.x, player.y, true, true);
                } else if (player.x <= this.x && player.y >= this.y) {
                    createEnemyBullet(Math.random(), this.x + this.w / 2, this.y, player.x, player.y, false, true);
                } else if (player.x <= this.x && player.y <= this.y) {
                    createEnemyBullet(Math.random(), this.x + this.w / 2, this.y, player.x, player.y, false, false);
                }
                setTimeout(function() {
                    enemy.canShoot = true;
                }, 750);
            }
        }
    };
    enemy[e.id] = e;
}
var createPlayerBullet = function(ID, X, Y, dir) {
    var playerBullet = {
        x: X,
        y: Y,
        w: 5,
        h: 5,
        color: "navy",
        id: ID,
        facingRight: dir,
        draw: function() {
            ctx.fillStyle = this.color;
            ctx.fillRect(this.x, this.y, this.w, this.h);
        }
    }
    clip[playerBullet.id] = playerBullet;
}
var createEnemyBullet = function(ID, X, Y, playerx, playery, dirx, diry) {
    var enemyBullet = {
        x: X,
        y: Y,
        w: 5,
        h: 5,
        color: "maroon",
        id: ID,
        dirX: dirx,
        dirY: diry,
        playerX: playerx,
        playerY: playery,
        draw: function() {
            ctx.fillStyle = this.color;
            ctx.fillRect(this.x, this.y, this.w, this.h);
        }
    }
    enemyClip[enemyBullet.id] = enemyBullet;
}
var createNuke = function(ID, X, Y) {
    var nuke = {
        x: X,
        y: Y,
        w: 5,
        h: 5,
        color: "green",
        id: ID,
        draw: function() {
            ctx.fillStyle = this.color;
            ctx.fillRect(this.x, this.y, this.w, this.h);
        }
    }
    arsenal[nuke.id] = nuke;
}
var updateEntity = function() {
    for (var playerBullet in clip) {
        clip[playerBullet].draw();
        if (clip[playerBullet].facingRight) {
            clip[playerBullet].x += 8;
        } else {
            clip[playerBullet].x -= 8;
        }
        if (clip[playerBullet].x <= 0) {
            delete clip[playerBullet];
        } else if (clip[playerBullet].x >= canvas.width) {
            delete clip[playerBullet];
        }
    }
    for (var nuke in arsenal) {
        arsenal[nuke].draw();
        arsenal[nuke].y += 3;
        if (arsenal[nuke].y >= canvas.height) {
            delete arsenal[nuke];
        }
    }
    for (var enemyBullet in enemyClip) {
        for (var e in enemy) {
            var dx = enemy[e].x - enemyClip[enemyBullet].playerX;
            var dy = enemy[e].y - enemyClip[enemyBullet].playerY;
            var angle = Math.atan2(dy, dx);
        }
        enemyClip[enemyBullet].draw();
        if (enemyClip[enemyBullet].dirX && !enemyClip[enemyBullet].dirY) {
            enemyClip[enemyBullet].x -= 10 * Math.cos(angle);
            enemyClip[enemyBullet].y -= 10 * Math.sin(angle);
        } else if (enemyClip[enemyBullet].dirX && enemyClip[enemyBullet].dirY) {
            enemyClip[enemyBullet].x -= 10 * Math.cos(angle);
            enemyClip[enemyBullet].y -= 10 * Math.sin(angle);
        } else if (!enemyClip[enemyBullet].dirX && enemyClip[enemyBullet].dirY) {
            enemyClip[enemyBullet].x -= 10 * Math.cos(angle);
            enemyClip[enemyBullet].y -= 10 * Math.sin(angle);
        } else if (!enemyClip[enemyBullet].dirX && !enemyClip[enemyBullet].dirY) {
            enemyClip[enemyBullet].x -= 10 * Math.cos(angle);
            enemyClip[enemyBullet].y -= 10 * Math.sin(angle);
        }
        if (enemyClip[enemyBullet].x <= 0) {
            delete enemyClip[enemyBullet];
        } else if (enemyClip[enemyBullet].x >= canvas.width) {
            delete enemyClip[enemyBullet];
        } else if (enemyClip[enemyBullet].y <= 0) {
            delete enemyClip[enemyBullet];
        } else if (enemyClip[enemyBullet].y >= canvas.height) {
            delete enemyClip[enemyBullet];
        } else if (enemyClip[enemyBullet].x >= player.x && enemyClip[enemyBullet].x <= player.x + player.w && enemyClip[enemyBullet].y >= player.y && enemyClip[enemyBullet].y <= player.y + player.h) {
            delete enemyClip[enemyBullet];
        }
    }
}
var update = function() {
    updateEntity();
    if (player.alive) {
        player.draw();
    }
    //if(enemy.alive){
    //  enemy.draw();
    //  enemy.shoot();
    //}
    for (var e in enemy) {
        ctx.fillStyle = enemy[e].color;
        ctx.fillRect(enemy[e].x, enemy[e].y, enemy[e].w, enemy[e].h);
        if (enemy[e].canShoot) {
            enemy[e].canShoot = false;
            if (player.x >= enemy[e].x && player.y <= enemy[e].y) { // Top Right: TF, Bottom Right: TT, Bottom Left: FT, Top Left: FF
                createEnemyBullet(Math.random(), enemy[e].x + enemy[e].w / 2, enemy[e].y, player.x, player.y, true, false); // True equals ___ is greater than
            } else if (player.x >= enemy[e].x && player.y >= enemy[e].y) {
                createEnemyBullet(Math.random(), enemy[e].x + enemy[e].w / 2, enemy[e].y, player.x, player.y, true, true);
            } else if (player.x <= enemy[e].x && player.y >= enemy[e].y) {
                createEnemyBullet(Math.random(), enemy[e].x + enemy[e].w / 2, enemy[e].y, player.x, player.y, false, true);
            } else if (player.x <= enemy[e].x && player.y <= enemy[e].y) {
                createEnemyBullet(Math.random(), enemy[e].x + enemy[e].w / 2, enemy[e].y, player.x, player.y, false, false);
            }
            setTimeout(function() {
                for (var e in enemy) {
                    enemy[e].canShoot = true;
                }
            }, 750);
        }
    }
    if (37 in keyDown) {
        player.facingRight = false;
        player.x -= 5;
    }
    if (38 in keyDown) {
        player.y -= 5;
    }
    if (39 in keyDown) {
        player.facingRight = true;
        player.x += 5;
    }
    if (40 in keyDown) {
        player.y += 5;
    }
    if (32 in keyDown) {
        player.shoot();
    }
    if (90 in keyDown) {
        player.nuke();
    }
}
addEventListener("keydown", function(e) {
    keyDown[e.keyCode] = true;
});
addEventListener("keyup", function(e) {
    delete keyDown[e.keyCode];
});

var画布,ctx;
var clip={};
var={};
var enemyClip={};
var keyDown={};
var敌人={};
window.onload=函数(){
canvas=document.getElementById(“gameCanvas”);
ctx=canvas.getContext(“2d”);
对于(变量i=0;i<3;i++){
create敌军(Math.random(),i*100+140);
}
setInterval(函数(){
clearRect(0,0,canvas.width,canvas.height);
更新();
}, 1000 / 30);
}
变量播放器={
x:240,
y:240,
w:20,
h:20,
颜色:“海军”,
活着:是的,
真的,
坎努克:没错,
facingRight:没错,
绘图:函数(){
ctx.fillStyle=this.color;
ctx.fillRect(this.x,this.y,this.w,this.h);
},
shoot:function(){
if(player.canShoot){
player.canShoot=false;
if(球员右脸){
createPlayerBullet(Math.random(),player.x+player.w,player.y+player.h/2,true);
}否则{
createPlayerBullet(Math.random(),player.x,player.y+player.h/2,false);
}
setTimeout(函数(){
player.canShoot=true;
}, 750);
}
},
nuke:function(){
if(player.canNuke){
player.canNuke=false;
createNuke(Math.random(),player.x+player.w/2,player.y+player.h);
setTimeout(函数(){
player.canNuke=true;
}, 2000);
}
}
}
//var敌人={
//x:240,
//y:480,
//w:20,
//h:20,
//颜色:“栗色”,
//活着:是的,
//真的,
//  
//绘图:函数(){
//ctx.fillStyle=this.color;
//ctx.fillRect(this.x,this.y,this.w,this.h);
//  },
//  
//shoot:function(){
//如果(敌人可以射击){
//敌人。可以射击=错误;
//      
//如果(player.x>=敌方.x&&player.y=敌方.x&&player.y>=敌方.y){
//createneMyBullet(Math.random(),敌方.x+敌方.w/2,敌方.y,玩家.x,玩家.y,真,真);
//}else if(player.x=敌军.y){
//createneMyBullet(Math.random(),敌方.x+敌方.w/2,敌方.y,玩家.x,玩家.y,false,true);
//}else if(player.x=this.y){
createneMyBullet(Math.random(),this.x+this.w/2,this.y,player.x,player.y,true,true);
}else if(player.x=this.y){
createneMyBullet(Math.random(),this.x+this.w/2,this.y,player.x,player.y,false,true);
}否则如果(player.x=player.x&&enemyClip[enemyBullet].x=player.y&&enemyClip[enemyBullet].y=敌军[e]。x&&player.y=敌军[e]。x&&player.y>=敌军[e].y){
createneMyBullet(Math.random(),敌人[e].x+敌人[e].w/2,敌人[e].y,player.x,player.y,true,true);
}else if(player.x=敌人[e].y){
createneMyBullet(Math.random(),敌人[e].x+敌人[e].w/2,敌人[e].y,player.x,player.y,false,true);

}else if(player.x此代码位于
updateEntity

for (var enemyBullet in enemyClip) {
    for (var e in enemy) {
        var dx = enemy[e].x - enemyClip[enemyBullet].playerX;
        var dy = enemy[e].y - enemyClip[enemyBullet].playerY;
        var angle = Math.atan2(dy, dx);
    }
应该在没有for循环的情况下编写。您应该只引用开枪的敌人

for (var enemyBullet in enemyClip) {
    var bullet = enemyClip[enemyBullet]; 
    var dx = bullet.enemyX - bullet.playerX;
    var dy = bullet.enemyY - bullet.playerY;
    var angle = Math.atan2(dy, dx);
但是,不要在子弹被射出时存储所有这些信息,您应该只计算子弹被射出时的角度(子弹没有必要知道玩家的位置,而且“dir”值似乎没有必要)

您的
updateEntity
代码将变成:

for (var enemyBullet in enemyClip) {
  var angle = enemyClip[enemyBullet].angle;

在你进一步之前,我建议你看一下你的代码,看看如何简化它。有很多可以被删除的东西。你在2个地方创建了敌人的子弹,每个地方有4个调用<代码> createEnemyBullet < /代码>,同时也考虑敌人的子弹和玩家的子弹是什么样的。

不是生成唯一id的好方法。每次只需使用递增的数字(尽管此代码中没有id的真正原因)

你的问题是,它涉及许多不同的部分,这不符合本问答环节的形式。如果你问如何以编程方式计算角度,并向我们展示了你的尝试,这是一回事,但你的问题远不止这些。
for (var enemyBullet in enemyClip) {
  var angle = enemyClip[enemyBullet].angle;