【问题标题】:Enemy detection and turret animation/control in a JavaScript p5.js gameJavaScript p5.js 游戏中的敌人检测和炮塔动画/控制
【发布时间】:2021-01-04 17:32:47
【问题描述】:

我正在使用 JavaScript 和 p5.js 库制作塔防游戏。我的敌人沿着一条路径走,他们的位置总是存储在一个列表中。我有一个基地和一把枪,枪围绕基地旋转(作为 1 个单位)并且应该指向最近的敌人。我有一个功能可以让我将枪指向敌人pointEnemy 但是,我无法获得正确的条件以使其指向其射程内最近的敌人。我需要enemyxenemyy 的正确参数。我目前正在生成 100 个敌人并且他们一直在移动,他们的位置存储在 globalenemy1position 中。任何帮助表示赞赏,谢谢。


所需代码


一些重要的变量

var numberOfEnemy1 = 100
let classenemy1 = new Enemy1(numberOfEnemy1);
var globalenemy1position = [];   
var isFireTowerPressed = false;
var FireTowerPos = [];    // Position of all FireTowers => [x,y]
var FireTowerRange = 300;
var FireTowerAngle = 0;

我的敌人班

class Enemy1
{
    constructor(number_of_enemies)
    {
        this.number_of_enemies = number_of_enemies;
        this.enemy_position = [];
        this.enemy1speed = 4;

    }
    enemy1_spawn()
    {
        let randomx = random(-300, -100);
        for(var i=0; i<this.number_of_enemies; i++)
        {
            var positionx = randomx;
            var positiony = 100;

            this.enemy_position.push([positionx + (-i*50), positiony]);
            globalenemy1position.push([positionx + (-i*50), positiony]);
            image(enemy1, this.enemy_position[i][0], this.enemy_position[i][1]);
        }

    }

    enemy1_move()
    {
        for(var i = 0; i < this.enemy_position.length; i++)
        {
            image(enemy1, this.enemy_position[i][0], this.enemy_position[i][1]);

            if (this.enemy_position[i][0] >= 200 && this.enemy_position[i][1] <= 450 && this.enemy_position[i][0] < 599)
            {
                this.enemy_position[i][1] += this.enemy1speed;
                globalenemy1position[i][1] += this.enemy1speed;
            }   

            else if (this.enemy_position[i][1] >= 100 && this.enemy_position[i][0] >= 600)
            {
                this.enemy_position[i][1] -= this.enemy1speed;
                globalenemy1position[i][1] -= this.enemy1speed;
            }

            else if (this.enemy_position[i][0] >= 750)
            {
                this.enemy_position[i][0] = 750;
                lives --;
                this.enemy_position.shift();
                globalenemy1position.shift();
            }   

            else
            {
                this.enemy_position[i][0] += this.enemy1speed;
                globalenemy1position[i][0] += this.enemy1speed;
            }

        }
    }
}

绘图功能 - 重绘每一帧

function draw() 
{

    background(60, 238, 161);
    [...]
    classenemy1.enemy1_move();
    rect(750, 70, 50, 100);
    ShowLives();
    if (isFireTowerPressed == true) 
    {
        image(firetowerbaseImg, mouseX - 28, mouseY - 28);
        noFill();
        stroke(0,0,0);
        strokeWeight(1);
        circle(mouseX, mouseY, 300);
    }
    for (var i = 0; i < FireTowerPos.length; i++) 
    {
        image(firetowerbaseImg, FireTowerPos[i][0], FireTowerPos[i][1]);

        if (globalenemy1position.length >= 1)
        {
            var gunx = FireTowerPos[i][0] +28;
            var guny = FireTowerPos[i][1]+25;
            var gunrange = FireTowerPos[i][3];

            for (j=0; j<globalenemy1position.length; j++)
            {

                // Need help with this statement here
                pointEnemy(globalenemy1position[j][0], globalenemy1position[j][1], gunx, guny, FireTowerPos[i][2], FireTowerPos[i][3]);
                
            }
        }
        else
        {
            image(firetowerturretImg, FireTowerPos[i][0], FireTowerPos[i][1]-20);
        }
    }
}

使枪口指向敌人的功能 - 我需要为enemyx 和enemyy 设置适当的值

function pointEnemy(enemyx, enemyy, gunx, guny, gunangle, gunrange)
{
    const isWithinRange = dist(enemyx, enemyy, gunx, guny) < gunrange;
    if(isWithinRange)
    {
        gunangle = atan2(enemyy - guny, enemyx - gunx) + radians(90);
    }
        push();
        translate(gunx, guny);
        // rect(-25, -20, 50, 40) // Draw the gun base
        // ellipse(0, 0, gun.range*2) // display the gun range
        rotate(gunangle);
        image(firetowerturretImg, -28, -45); // Set the offset of the gun sprite and draw the gun
        pop();
}

这是一张有助于形象化问题的图片

如您所见,目前我只是遍历所有敌人并给出他们的位置,所以它基本上指向附近的每个敌人。


更新


1

我尝试了@user3386109 给出的方法,但无法实施,如果可能的话,我希望炮塔/枪指向敌人,直到它离开射程而不总是指向最近的敌人。它应该从最近的开始,然后一直指向它,直到它离开或敌人死亡(从列表中删除位置),以先到者为准。然后该函数应再次重新启动并继续该过程。

【问题讨论】:

  • 您需要将目标的选择与绘图代码分开。要选择目标,请使用变量bestDistance(最初设置为gunrange)和变量bestTarget(最初设置为无)。然后,对于每个敌方单位,计算与塔的距离。如果距离小于bestDistance,则更新bestDistancebestTarget。最后,如果bestDistance小于gunrange,那么bestTarget就是要瞄准的敌人。
  • @user3386109 但是我如何使用它并为屏幕上的每个火塔跟踪它?
  • 我会有一个 FireTower 类,它可以跟踪每个 Fire Tower 的位置以及它在做什么。
  • @user3386109 你能帮忙并提供更详细的答案吗,我尝试了几种方法,但到目前为止都没有奏效。

标签: javascript animation rotation p5.js path-finding


【解决方案1】:

这个过程是对塔的完整瞄准。将此添加到绘图中,它会搜索敌人。

for (var i = 0; i < FireTowerPos.length; i++) 
{
    // image(firetowerbaseImg, FireTowerPos[i][0], FireTowerPos[i][1]);
    // pointEnemy(mouseX, mouseY, FireTowerPos[i][0] +28, FireTowerPos[i][1]+25, FireTowerPos[i][2], FireTowerPos[i][3]);
    image(firetowerbaseImg, FireTowerPos[i][0], FireTowerPos[i][1]);

    var enemiesInRange = [];
    let firetowerx = FireTowerPos[i][0];
    let firetowery = FireTowerPos[i][1];
    for (var j = 0; j < globalenemy1position.length; j++) 
    {
        var checkDist = dist(globalenemy1position[j][0], globalenemy1position[j][1], firetowerx, firetowery);
        let thisenemyx = globalenemy1position[j][0];
        let thisenemyy = globalenemy1position[j][1];

        if (checkDist < FireTowerRange) 
        {
            enemiesInRange.push([thisenemyx, thisenemyy]);
            pointEnemy(enemiesInRange[0][0], enemiesInRange[0][1], FireTowerPos[i][0] +28, FireTowerPos[i][1]+25, FireTowerPos[i][2], FireTowerPos[i][3]);

        }
        else
        {
            enemiesInRange.shift();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2017-06-07
    相关资源
    最近更新 更多