javascript - P5.js 图像碰撞
问题描述
我最近发现 p5.js 中的图像碰撞与常规的矩形碰撞完全不同。如果您想保持图像的纵横比而不在函数中手动设置高度和宽度参数image()
,则可以使用该scale()
函数缩放图像。然而,这不会改变图像的面积,所以为了检测碰撞,我必须将图像乘以我设置的图像比例。例如,如果在构造函数中设置,获取玩家宽度将为playerImage.width * player.scale
.
所以我已经完成了所有这些,甚至还做了一个函数来显示图像的区域/命中框。然后,当我用我的碰撞功能设置它时,底部和右侧可以很好地检测到碰撞,但顶部和左侧的行为似乎很奇怪。
你可以在这里看到发生了什么: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>
推荐阅读
- java - 在 Java 中输出二维数组
- javascript - Cytoscape.js - 如何为复合节点使用一种布局,为复合节点的子节点使用另一种布局
- google-maps - 通过标记在谷歌地图上设置边界
- javascript - 从桌面浏览器自动移动视图
- ruby-on-rails - 如何在 Rails 中显示当前正在运行的 ActiveJobs(独立于适配器)?
- encryption - RSA-OAEP 和 RSA-PKCS1.5 的区别
- c# - 向事件中心发送消息时 Windows 服务失败给出连接错误
- sql-server - 按特定条件分组
- rest - oracle12 c apex 使休息请求不起作用
- c# - Json.net (9.x) 中的序列化/反序列化类型属性