恒定不保持恒定?
Constant not staying constant?
我编写了一个代码,目的是在按下鼠标的地方出现一个正方形,尽管鼠标移动但仍留在该位置,并且在松开鼠标时不会消失。
这是 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:对不起,杂项信息,这应该是建立简单的子弹物理学。
const
声明只存在于shoot
的范围内。因此,一旦 shoot
函数执行完毕,startX startY destX destY
即 const
将被删除。
可能的修复:
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
}
听起来似乎对范围界定有些困惑,可能有更好的方法来考虑这个问题。
首先让我们看看哪里出了问题,然后通过一些细节来解释原因。
- 就像变量(
let
、var
)一样,常量总是在特定范围内声明。
- 范围就像常量和变量的容器。作用域是私有的,也就是说它们不能从外部访问。可以创建和销毁范围。
- 当您直接在函数内部声明常量时,作用域就是函数本身(就像
startX
在 shoot
中)。 (请注意,如果您在 if
语句或其他块中声明常量,则作用域就是该块。不过,这里不是这种情况。)
- 函数作用域在每次调用函数时创建,并在函数执行完毕时销毁。
- 每次调用函数并创建其作用域时,所有常量(和变量)都会用新值重新初始化。
- 代码中出现的常量在不同的函数调用期间可能具有不同的值。它仅在其生命周期内保持不变,在您的情况下是函数的一次给定执行。
这就是为什么您的常量不能保持不变的原因。您在鼠标按下时重复调用 shoot()
,因此常量被重复创建并分配新值。
有了这些信息,希望您能看到当前方法存在的问题。至于解决方案,让我们考虑一下到底发生了什么。 shoot()
是当用户发出 "shoot" 命令(例如鼠标单击)时应触发的操作。 draw()
函数是一个连续的事件触发说 "hey, update the screen"。将射门动作放在平局事件中是一种意图不匹配,是这种斗争的根源。
相反,让我们介绍一个 bullet
对象的概念。项目符号具有 x
和 y
值。子弹在用户射击时创建,并在创建时被赋予特定的 x 和 y 值。 None 其中发生在 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
);
}
}
}
我编写了一个代码,目的是在按下鼠标的地方出现一个正方形,尽管鼠标移动但仍留在该位置,并且在松开鼠标时不会消失。
这是 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:对不起,杂项信息,这应该是建立简单的子弹物理学。
const
声明只存在于shoot
的范围内。因此,一旦 shoot
函数执行完毕,startX startY destX destY
即 const
将被删除。
可能的修复:
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
}
听起来似乎对范围界定有些困惑,可能有更好的方法来考虑这个问题。
首先让我们看看哪里出了问题,然后通过一些细节来解释原因。
- 就像变量(
let
、var
)一样,常量总是在特定范围内声明。 - 范围就像常量和变量的容器。作用域是私有的,也就是说它们不能从外部访问。可以创建和销毁范围。
- 当您直接在函数内部声明常量时,作用域就是函数本身(就像
startX
在shoot
中)。 (请注意,如果您在if
语句或其他块中声明常量,则作用域就是该块。不过,这里不是这种情况。) - 函数作用域在每次调用函数时创建,并在函数执行完毕时销毁。
- 每次调用函数并创建其作用域时,所有常量(和变量)都会用新值重新初始化。
- 代码中出现的常量在不同的函数调用期间可能具有不同的值。它仅在其生命周期内保持不变,在您的情况下是函数的一次给定执行。
这就是为什么您的常量不能保持不变的原因。您在鼠标按下时重复调用 shoot()
,因此常量被重复创建并分配新值。
有了这些信息,希望您能看到当前方法存在的问题。至于解决方案,让我们考虑一下到底发生了什么。 shoot()
是当用户发出 "shoot" 命令(例如鼠标单击)时应触发的操作。 draw()
函数是一个连续的事件触发说 "hey, update the screen"。将射门动作放在平局事件中是一种意图不匹配,是这种斗争的根源。
相反,让我们介绍一个 bullet
对象的概念。项目符号具有 x
和 y
值。子弹在用户射击时创建,并在创建时被赋予特定的 x 和 y 值。 None 其中发生在 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
);
}
}
}