P5.js 图像碰撞
P5.js Image Collision
我最近发现 p5.js 中的图像碰撞与常规矩形碰撞有很大不同。如果您想在 image()
函数中不手动设置高度和宽度参数而保持图像的纵横比,则可以使用 scale()
函数缩放图像。但是,这不会改变图像的区域,因此要检测碰撞,我必须将图像乘以我设置的图像比例。例如,如果在构造函数中设置,要获取播放器宽度将是 playerImage.width * player.scale
.
所以我已经完成了所有这些,甚至还制作了一个函数来显示图像的area/hitbox。然后,当我用我的碰撞函数设置它时,底部和右侧检测到碰撞很好,但顶部和左侧似乎表现得很奇怪。
你可以在这里看到发生了什么:https://image-colliding.stcollier.repl.co/
有谁知道为什么左侧和顶部边缘的碰撞关闭?
这是我针对该问题的代码:
let debug = true;
function preload() {
playerImg = loadImage("https://image-colliding.stcollier.repl.co/Player.png")
brickImg = loadImage("https://image-colliding.stcollier.repl.co/brick.jpeg")
}
function setup() {
createCanvas(windowWidth, windowHeight)
player = new Player(windowWidth/2, windowHeight/2, 0.5)
brick = new Brick(windowWidth/10, windowHeight/3, 0.1)
speed = 3;
}
function draw() {
background(200, 200, 200)
push();
brick.display();
pop();
push();
player.display();
pop();
if (debug) {
showRectCollider(player.x, player.y, playerImg.width * player.s, playerImg.height * player.s)
showRectCollider(brick.x, brick.y, brickImg.width * brick.s, brickImg.height * brick.s)
if (player.collidesImg(brick.x, brick.y, brickImg.width, brickImg.height, brick.s)) {
collidingColor = 'green';
} else {
collidingColor = 'red'
}
}
if (keyIsPressed && keyCode === UP_ARROW) {
moveY(player, -speed)
}
if (keyIsPressed && keyCode === DOWN_ARROW) {
moveY(player, speed)
}
if (keyIsPressed && keyCode === LEFT_ARROW) {
moveX(player, -speed)
}
if (keyIsPressed && keyCode === RIGHT_ARROW) {
moveX(player, speed)
}
}
class Player {
constructor(x, y, s) {
this.x = x;
this.y = y;
this.s = s;
}
display() {
translate(this.x, this.y)
scale(this.s)
image(playerImg, 0, 0)
}
collidesFunc1(x, y, w, h) {
if (
this.x - w/2 <= x + w/2 &&
this.x + w/2 >= x - w/2 &&
this.y - h/2 <= y + h/2 &&
this.y + h/2 >= y - h/2) {
return true;
}
else {
return false;
}
}
collidesFunc2(x, y, w, h) {
if (
this.x >= x - w &&
this.x <= x + w &&
this.y >= y - h &&
this.y <= y + h) {
return true;
}
else {
return false;
}
}
collidesImg(x, y, w, h, s) {
if (
this.x >= x - (w * s) &&
this.x <= x + (w * s) &&
this.y >= y - (h * s) &&
this.y <= y + (h * s)) {
return true;
}
else {
return false;
}
}
}
class Brick {
constructor(x, y, s) {
this.x = x;
this.y = y;
this.s = s;
}
display() {
translate(this.x, this.y)
scale(this.s)
image(brickImg, 0, 0)
}
}
//Other functions
var collidingColor = 'red';
function showRectCollider(x, y, w, h) {
noFill();
stroke(collidingColor);
strokeWeight(3);
rect(x, y, w, h)
}
function moveX(object, speed) {
object.x += speed;
}
function moveY(object, speed) {
object.y += speed;
}
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/p5@1.3.1/lib/p5.js"></script>
</head>
<body>
<script src="script.js"></script>
</body>
</html>
我有三个用于检测碰撞的函数,目前我正在使用我制作的 collidesImg()
函数。所有三个函数都可以在第 71-106 行找到。
感谢您的帮助。非常感谢。
你的碰撞逻辑有点不对劲,这里附上解释性注释:
collidesImg(x, y, w, h, s) {
if (
// right edge of player to the right of left edge of brick
this.x + playerImg.width * this.s >= x &&
// left edge of player to the left of right edge of brick
this.x <= x + (w * s) &&
// bottom edge of player below top edge of brick
this.y + playerImg.height * this.s >= y &&
// top edge of player above bottom edge of brick
this.y <= y + (h * s)) {
return true;
} else {
return false;
}
}
let debug = true;
function preload() {
playerImg = loadImage("https://image-colliding.stcollier.repl.co/Player.png")
brickImg = loadImage("https://image-colliding.stcollier.repl.co/brick.jpeg")
}
function setup() {
createCanvas(windowWidth, windowHeight)
player = new Player(windowWidth / 2, windowHeight / 2, 0.5)
brick = new Brick(windowWidth / 10, windowHeight / 3, 0.1)
speed = 3;
}
function draw() {
background(200, 200, 200)
push();
brick.display();
pop();
push();
player.display();
pop();
if (debug) {
if (player.collidesImg(brick.x, brick.y, brickImg.width, brickImg.height, brick.s)) {
collidingColor = 'green';
} else {
collidingColor = 'red'
}
showRectCollider(player.x, player.y, playerImg.width * player.s, playerImg.height * player.s)
showRectCollider(brick.x, brick.y, brickImg.width * brick.s, brickImg.height * brick.s)
}
if (keyIsPressed && keyCode === UP_ARROW) {
moveY(player, -speed)
}
if (keyIsPressed && keyCode === DOWN_ARROW) {
moveY(player, speed)
}
if (keyIsPressed && keyCode === LEFT_ARROW) {
moveX(player, -speed)
}
if (keyIsPressed && keyCode === RIGHT_ARROW) {
moveX(player, speed)
}
}
class Player {
constructor(x, y, s) {
this.x = x;
this.y = y;
this.s = s;
}
display() {
translate(this.x, this.y)
scale(this.s)
image(playerImg, 0, 0)
}
collidesFunc1(x, y, w, h) {
if (
this.x - w / 2 <= x + w / 2 &&
this.x + w / 2 >= x - w / 2 &&
this.y - h / 2 <= y + h / 2 &&
this.y + h / 2 >= y - h / 2) {
return true;
} else {
return false;
}
}
collidesFunc2(x, y, w, h) {
if (
this.x >= x - w &&
this.x <= x + w &&
this.y >= y - h &&
this.y <= y + h) {
return true;
} else {
return false;
}
}
collidesImg(x, y, w, h, s) {
if (
// right edge of player to the right of left edge of brick
this.x + playerImg.width * this.s >= x &&
// left edge of player to the left of right edge of brick
this.x <= x + (w * s) &&
// bottom edge of player below top edge of brick
this.y + playerImg.height * this.s >= y &&
// top edge of player above bottom edge of brick
this.y <= y + (h * s)) {
return true;
} else {
return false;
}
}
}
class Brick {
constructor(x, y, s) {
this.x = x;
this.y = y;
this.s = s;
}
display() {
translate(this.x, this.y)
scale(this.s)
image(brickImg, 0, 0)
}
}
//Other functions
var collidingColor = 'red';
function showRectCollider(x, y, w, h) {
noFill();
stroke(collidingColor);
strokeWeight(3);
rect(x, y, w, h)
}
function moveX(object, speed) {
object.x += speed;
}
function moveY(object, speed) {
object.y += speed;
}
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/p5@1.3.1/lib/p5.js"></script>
</head>
<body>
</body>
</html>
我最近发现 p5.js 中的图像碰撞与常规矩形碰撞有很大不同。如果您想在 image()
函数中不手动设置高度和宽度参数而保持图像的纵横比,则可以使用 scale()
函数缩放图像。但是,这不会改变图像的区域,因此要检测碰撞,我必须将图像乘以我设置的图像比例。例如,如果在构造函数中设置,要获取播放器宽度将是 playerImage.width * player.scale
.
所以我已经完成了所有这些,甚至还制作了一个函数来显示图像的area/hitbox。然后,当我用我的碰撞函数设置它时,底部和右侧检测到碰撞很好,但顶部和左侧似乎表现得很奇怪。
你可以在这里看到发生了什么:https://image-colliding.stcollier.repl.co/
有谁知道为什么左侧和顶部边缘的碰撞关闭?
这是我针对该问题的代码:
let debug = true;
function preload() {
playerImg = loadImage("https://image-colliding.stcollier.repl.co/Player.png")
brickImg = loadImage("https://image-colliding.stcollier.repl.co/brick.jpeg")
}
function setup() {
createCanvas(windowWidth, windowHeight)
player = new Player(windowWidth/2, windowHeight/2, 0.5)
brick = new Brick(windowWidth/10, windowHeight/3, 0.1)
speed = 3;
}
function draw() {
background(200, 200, 200)
push();
brick.display();
pop();
push();
player.display();
pop();
if (debug) {
showRectCollider(player.x, player.y, playerImg.width * player.s, playerImg.height * player.s)
showRectCollider(brick.x, brick.y, brickImg.width * brick.s, brickImg.height * brick.s)
if (player.collidesImg(brick.x, brick.y, brickImg.width, brickImg.height, brick.s)) {
collidingColor = 'green';
} else {
collidingColor = 'red'
}
}
if (keyIsPressed && keyCode === UP_ARROW) {
moveY(player, -speed)
}
if (keyIsPressed && keyCode === DOWN_ARROW) {
moveY(player, speed)
}
if (keyIsPressed && keyCode === LEFT_ARROW) {
moveX(player, -speed)
}
if (keyIsPressed && keyCode === RIGHT_ARROW) {
moveX(player, speed)
}
}
class Player {
constructor(x, y, s) {
this.x = x;
this.y = y;
this.s = s;
}
display() {
translate(this.x, this.y)
scale(this.s)
image(playerImg, 0, 0)
}
collidesFunc1(x, y, w, h) {
if (
this.x - w/2 <= x + w/2 &&
this.x + w/2 >= x - w/2 &&
this.y - h/2 <= y + h/2 &&
this.y + h/2 >= y - h/2) {
return true;
}
else {
return false;
}
}
collidesFunc2(x, y, w, h) {
if (
this.x >= x - w &&
this.x <= x + w &&
this.y >= y - h &&
this.y <= y + h) {
return true;
}
else {
return false;
}
}
collidesImg(x, y, w, h, s) {
if (
this.x >= x - (w * s) &&
this.x <= x + (w * s) &&
this.y >= y - (h * s) &&
this.y <= y + (h * s)) {
return true;
}
else {
return false;
}
}
}
class Brick {
constructor(x, y, s) {
this.x = x;
this.y = y;
this.s = s;
}
display() {
translate(this.x, this.y)
scale(this.s)
image(brickImg, 0, 0)
}
}
//Other functions
var collidingColor = 'red';
function showRectCollider(x, y, w, h) {
noFill();
stroke(collidingColor);
strokeWeight(3);
rect(x, y, w, h)
}
function moveX(object, speed) {
object.x += speed;
}
function moveY(object, speed) {
object.y += speed;
}
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/p5@1.3.1/lib/p5.js"></script>
</head>
<body>
<script src="script.js"></script>
</body>
</html>
我有三个用于检测碰撞的函数,目前我正在使用我制作的 collidesImg()
函数。所有三个函数都可以在第 71-106 行找到。
感谢您的帮助。非常感谢。
你的碰撞逻辑有点不对劲,这里附上解释性注释:
collidesImg(x, y, w, h, s) {
if (
// right edge of player to the right of left edge of brick
this.x + playerImg.width * this.s >= x &&
// left edge of player to the left of right edge of brick
this.x <= x + (w * s) &&
// bottom edge of player below top edge of brick
this.y + playerImg.height * this.s >= y &&
// top edge of player above bottom edge of brick
this.y <= y + (h * s)) {
return true;
} else {
return false;
}
}
let debug = true;
function preload() {
playerImg = loadImage("https://image-colliding.stcollier.repl.co/Player.png")
brickImg = loadImage("https://image-colliding.stcollier.repl.co/brick.jpeg")
}
function setup() {
createCanvas(windowWidth, windowHeight)
player = new Player(windowWidth / 2, windowHeight / 2, 0.5)
brick = new Brick(windowWidth / 10, windowHeight / 3, 0.1)
speed = 3;
}
function draw() {
background(200, 200, 200)
push();
brick.display();
pop();
push();
player.display();
pop();
if (debug) {
if (player.collidesImg(brick.x, brick.y, brickImg.width, brickImg.height, brick.s)) {
collidingColor = 'green';
} else {
collidingColor = 'red'
}
showRectCollider(player.x, player.y, playerImg.width * player.s, playerImg.height * player.s)
showRectCollider(brick.x, brick.y, brickImg.width * brick.s, brickImg.height * brick.s)
}
if (keyIsPressed && keyCode === UP_ARROW) {
moveY(player, -speed)
}
if (keyIsPressed && keyCode === DOWN_ARROW) {
moveY(player, speed)
}
if (keyIsPressed && keyCode === LEFT_ARROW) {
moveX(player, -speed)
}
if (keyIsPressed && keyCode === RIGHT_ARROW) {
moveX(player, speed)
}
}
class Player {
constructor(x, y, s) {
this.x = x;
this.y = y;
this.s = s;
}
display() {
translate(this.x, this.y)
scale(this.s)
image(playerImg, 0, 0)
}
collidesFunc1(x, y, w, h) {
if (
this.x - w / 2 <= x + w / 2 &&
this.x + w / 2 >= x - w / 2 &&
this.y - h / 2 <= y + h / 2 &&
this.y + h / 2 >= y - h / 2) {
return true;
} else {
return false;
}
}
collidesFunc2(x, y, w, h) {
if (
this.x >= x - w &&
this.x <= x + w &&
this.y >= y - h &&
this.y <= y + h) {
return true;
} else {
return false;
}
}
collidesImg(x, y, w, h, s) {
if (
// right edge of player to the right of left edge of brick
this.x + playerImg.width * this.s >= x &&
// left edge of player to the left of right edge of brick
this.x <= x + (w * s) &&
// bottom edge of player below top edge of brick
this.y + playerImg.height * this.s >= y &&
// top edge of player above bottom edge of brick
this.y <= y + (h * s)) {
return true;
} else {
return false;
}
}
}
class Brick {
constructor(x, y, s) {
this.x = x;
this.y = y;
this.s = s;
}
display() {
translate(this.x, this.y)
scale(this.s)
image(brickImg, 0, 0)
}
}
//Other functions
var collidingColor = 'red';
function showRectCollider(x, y, w, h) {
noFill();
stroke(collidingColor);
strokeWeight(3);
rect(x, y, w, h)
}
function moveX(object, speed) {
object.x += speed;
}
function moveY(object, speed) {
object.y += speed;
}
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/p5@1.3.1/lib/p5.js"></script>
</head>
<body>
</body>
</html>