常数不保持不变?

时间:2018-05-02 05:34:20

标签: javascript html processing p5.js

我制作了一个代码,目的是在按下鼠标的地方出现一个正方形,尽管鼠标移动仍然留在那个位置,并且当鼠标释放时不会消失。

这是P5.JS! https://p5js.org/reference/

相反,方块跟随鼠标直到它被释放然后消失!

我相信我的代码会在每次运行shoot()函数时继续声明一个新常量并删除旧常量。

var clocker = 0;// NOT YET USED

var player = {
    x:400,
    y:400,
};

function shoot(x1, y1, x2, y2, speed, range, power, playerDirection){

    var bulletAlive = true;
    var bulletDamage = power;
    const startX = x1;
    const startY = y1;
    const destX = x2;
    const destY = y2;
    var bulletX = startX;
    var bulletY = startY;

    if(bulletAlive){
      fill(0,100,200);
      rect(destX-12.5,destY-12.5,25,25);
    };


};

function setup() {
    createCanvas(1000,650);
}

function draw() {

    background(204,204,204);

    if(mouseIsPressed){
      shoot(player.x,player.y,mouseX,mouseY,2,100,0,"right");
    }

}

也许我使用const错了。如果是这样我应该如何使用它?我怎样才能让destX和destY不会改变? (不要跟随老鼠或消失)

PS:对于杂项信息感到抱歉,这应该是简单的子弹物理。

2 个答案:

答案 0 :(得分:2)

听起来有一些关于范围界定的混淆,并且可能有更好的方法来考虑这个问题。

首先让我们看看出了什么问题,并通过一些细节来解释原因。

  • 就像变量(letvar)一样,常量总是在特定范围内声明。
  • 范围就像常量和变量的容器。范围是私有的,即无法从外部访问。范围可以创建和销毁。
  • 在函数内直接声明常量时,作用域本身就是函数(如startX中的shoot)。 (注意,如果在if语句或其他块中声明一个常量,则范围是块。但这不是这种情况。)
  • 每次调用函数时都会创建函数作用域,并在函数执行完毕后销毁。
  • 每次调用函数并创建其范围时,所有常量(和变量)都将使用新值重新初始化。
  • 在不同的函数调用期间,代码中出现的常量可能具有不同的值。它在它的生命周期中只是常数,在你的情况下是一个给定的函数执行。

这就是为什么你的常数不会保持不变的原因。您在鼠标停止时反复调用shoot(),因此会重复重复常量并为其分配新值。

有了这些信息,希望你能看到当前方法的问题。至于解决方案,让我们考虑到底发生了什么。 shoot()是当用户发出“拍摄”命令(例如鼠标点击)时应触发的操作。 draw()函数是一个连续的事件,触发说“嘿,更新屏幕”。将射击动作放在抽奖活动中是一种意图的不匹配,并且是这样的斗争的根源。

相反,让我们介绍bullet对象的概念。子弹具有xy值。用户拍摄时会创建一个项目符号,并在创建时给出特定的x和y值。这些都不会发生在draw内,它发生在另一个事件监听器中,例如"click"

draw的工作是检查是否有活动的子弹,如果有,则在指定的x和y坐标处绘制它。如果没有子弹,什么也不做。 (当然你也可能需要绘制其他东西,但这与绘制子弹无关。)

保持对象创建和对象绘图分离可以更容易地获得您正在寻找的那种控件。

编辑:添加一些代码示例

以下是使用上面的项目符号概念,代码完全按照您的要求执行操作的样子。内联注释应该解释每一步。

// This is where we'll store an active bullet object.
// The `shoot()` function is responsible for setting this.
// `draw()` is responsible for rendering the bullet.
// Initially we'll set the value to `null` to explicitly
// indicate that there is no bullet.
let activeBullet = null;


// The purpose of `shoot()` is to create a bullet
// and make it available to be rendered.
function shoot(x, y) {
    // Create the bullet object.
    const newBullet = {
        x: x,
        y: y,
        size: 25
    };

    // Set the active bullet to the new bullet. This will
    // cause any previously active bullet to disappear.
    activeBullet = newBullet;
}



// P5 functions
// ------------

function setup() {
    createCanvas(1000, 650);
}


// Shoot when the player clicks.
function mousePressed() {
    shoot(mouseX, mouseY);
}


function draw() {
    // Always start with a blank canvas.
    clear();

    // If there is an active bullet, draw it!
    // (`null` is "falsy", objects are "truthy", so the
    // `if` statement will only run after the `activeBullet`
    // variable is assigned a bullet object.)
    if (activeBullet) {
        fill(0, 100, 200);
        rect(
            activeBullet.x - activeBullet.size / 2,
            activeBullet.y - activeBullet.size / 2,
            activeBullet.size,
            activeBullet.size
        );
    }
}

你还提到你想建立简单的子弹物理。只是为了展示子弹对象的想法是如何工作的,这里是一个演示,你可以点击拍摄多个子弹,它们都独立移动,并与墙壁碰撞,此时它们被移除。 很多更多地参与构建游戏,但希望这是一个鼓舞人心的起点:)

// Store canvas dimensions globally so we have easy access.
const canvasWidth = 1000;
const canvasHeight = 650;

// We'll add a "wall" object so we have something the bullets can
// collide with. This value is the X position of the wall.
const wallX = canvasWidth - 200;


// Instead of a single bullet, using an array can accommodate
// multiple bullets. It's empty to start, which means no bullets.
// We can also use `const` for this, because we won't ever assign
// a new value, we'll only modify the contents of the array.
const activeBullets = [];


function shoot(x, y) {
    // Create the bullet object.
    const newBullet = {
        x: x,
        y: y,
        size: 25,
        speed: 4
    };

    // Instead of overwriting a single bullet variable, we'll push
    // the new bullet onto an array of bullets so multiple can exist.
    activeBullets.push(newBullet);
}



// P5 functions
// ------------

function setup() {
    createCanvas(canvasWidth, canvasHeight);
}


// Shoot when the player clicks.
function mousePressed() {
    shoot(mouseX, mouseY);
}


function draw() {
    // Always start with a blank canvas.
    clear();

    // Draw our "wall".
    fill(50);
    rect(wallX, 0, 60, canvasHeight);

    // Set the fill color once, to use for all bullets. This doesn't
    // need to be set for each bullet.
    fill(0, 100, 200);

    // Loop through the array of bullets and draw each one, while also
    // checking for collisions with the wall so we can remove them. By
    // looping backwards, we can safely remove bullets from the array
    // without changing the index of the next bullet in line.
    for (let i=activeBullets.length-1; i>=0; i--) {
        // Grab the current bullet we're operating on.
        const bullet = activeBullets[i];

        // Move the bullet horizontally.
        bullet.x += bullet.speed;

        // Check if the bullet has visually gone past the wall. This
        // means a collision.
        if (bullet.x + bullet.size / 2 > wallX) {
            // If the bullet has collided, remove it and don't draw it.
            activeBullets.splice(i, 1);
        } else {
            // If the bullet hasn't collided, draw it.
            rect(
                bullet.x - bullet.size / 2,
                bullet.y - bullet.size / 2,
                bullet.size,
                bullet.size
            );
        }
    }
}

答案 1 :(得分:0)

const声明仅存在于shoot范围内。因此,一旦shoot函数执行完毕,startX startY destX destYconst即被删除。

可能的解决方法:

var didShootAlready = false;
var startX, startY, destX, destY;

function shoot(/*params*/){
    if(!didShootAlready){
        didShootAlready = true;
        startX = x1;
        startY = y1;
        destX = x2;
        destY = y2;
    }
    //do the rest
}