如何防止 2 名玩家在 html5 游戏中互相交叉
How to prevent 2 players to cross each other in html5 game
我想添加我的 2 个玩家之间的碰撞(在服务器端)
My two players
显示我想要的视频(来自名为taming.io的游戏):
https://www.youtube.com/watch?v=tGb6PwjHao8
这是我的实际代码(每次玩家连接时,都会创建一个新玩家 class):
class Player {
static list = new Set()
constructor(id) {
Player.list[id] = this
this.id = id;
this.x = 250;
this.y = 250;
this.pressingUp = false;
this.pressingLeft = false;
this.pressingDown = false;
this.pressingRight = false;
this.moveSpeed = 5;
this.moveAngle = 45;
this.radians = this.moveAngle * Math.PI / 180;
this.vx = Math.cos(this.radians) * this.moveSpeed;
this.vy = Math.sin(this.radians) * this.moveSpeed;
}
//Apply new positions
update() {
//Players collisions
for (const i in Player.list) {
const player = Player.list[i];
const calcDistance = Math.hypot(player.x - this.x, player.y - this.y)
if (calcDistance <= 200 && player != this) {
//What should i put ?
}
}
//Player moves
if (this.pressingUp === true) {
this.y -= this.vy;
}
else if (this.pressingDown === true) {
this.y += this.vy;
}
if (this.pressingRight === true) {
this.x += this.vx;
}
else if (this.pressingLeft === true) {
this.x -= this.vx;
}
}
}
所以我正在计算具有 calcDistance 常量的玩家之间的距离,如果 calcDistance = 200(玩家半径命中框 = 100,所以玩家 1 半径命中框 + 玩家 2 半径命中框 = 200),它应该做一些事情,但我不知道是什么
你能帮帮我吗?
像您一样使用 Math.hypot()
获取圆心之间的距离。查看该距离是否小于两个圆的半径。一旦你有了它,你就可以设置玩家的 x,y 和可选的 vx,vy。
x 将设置为 obj2.x
加上两个半径的总和乘以每个 x 和 y 值的距离除以总距离。更多三角数学...
这是一个例子
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 500;
class Circle {
constructor(x, y, c) {
this.x = x;
this.y = y;
this.color = c;
this.r = 30;
this.vx = 0;
this.vy = 0;
this.speed = 0.5;
}
draw() {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.r, 0, Math.PI*2);
ctx.fill();
}
update() {
if (controller.left) {
this.vx -= this.speed;
}
if (controller.up) {
this.vy -= this.speed;
}
if (controller.right) {
this.vx += this.speed;
}
if (controller.down) {
this.vy += this.speed
}
this.x += this.vx;
this.y += this.vy;
this.vx *= 0.9;
this.vy *= 0.9;
}
}
class Controller {
constructor() {
this.up = false;
this.right = false;
this.down = false;
this.left = false;
let keyEvent = (e) => {
if (e.code == "ArrowUp") {
this.up = e.type == "keydown";
}
if (e.code == "ArrowRight") {
this.right = e.type == "keydown";
}
if (e.code == "ArrowLeft") {
this.left = e.type == "keydown";
}
if (e.code == "ArrowDown") {
this.down = e.type == "keydown";
}
};
addEventListener("keydown", keyEvent);
addEventListener("keyup", keyEvent);
}
}
let player = new Circle(25, 25, 'blue');
let obstacle = new Circle(canvas.width/2, 150, 'red');
let controller = new Controller();
function collisionDetection(obj1, obj2) {
if (Math.hypot(obj1.x - obj2.x, obj1.y - obj2.y) <= obj1.r + obj2.r) {
collisionResponse(obj1, obj2)
}
}
function collisionResponse(obj1, obj2) {
let dx = obj1.x - obj2.x;
let dy = obj1.y - obj2.y;
let dist = (Math.hypot(obj1.x - obj2.x, obj1.y - obj2.y)) || 1;
let radii = obj1.r + obj2.r;
let x = dx / dist;
let y = dy / dist;
obj1.x = obj2.x + radii * x;
obj1.y = obj2.y + radii * y;
obj1.vx = 0; //optional
obj1.vy = 0; //optional
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
collisionDetection(player, obstacle)
player.update();
player.draw();
obstacle.draw();
requestAnimationFrame(animate);
}
animate();
<canvas id="canvas"></canvas>
设置 vx 和 vy 是可选的,可以防止发生任何重叠。你也可以选择不将它们设置为 0,你会有一些重叠,但圆圈看起来会更平滑地滑离彼此。
我想添加我的 2 个玩家之间的碰撞(在服务器端) My two players
显示我想要的视频(来自名为taming.io的游戏): https://www.youtube.com/watch?v=tGb6PwjHao8
这是我的实际代码(每次玩家连接时,都会创建一个新玩家 class):
class Player {
static list = new Set()
constructor(id) {
Player.list[id] = this
this.id = id;
this.x = 250;
this.y = 250;
this.pressingUp = false;
this.pressingLeft = false;
this.pressingDown = false;
this.pressingRight = false;
this.moveSpeed = 5;
this.moveAngle = 45;
this.radians = this.moveAngle * Math.PI / 180;
this.vx = Math.cos(this.radians) * this.moveSpeed;
this.vy = Math.sin(this.radians) * this.moveSpeed;
}
//Apply new positions
update() {
//Players collisions
for (const i in Player.list) {
const player = Player.list[i];
const calcDistance = Math.hypot(player.x - this.x, player.y - this.y)
if (calcDistance <= 200 && player != this) {
//What should i put ?
}
}
//Player moves
if (this.pressingUp === true) {
this.y -= this.vy;
}
else if (this.pressingDown === true) {
this.y += this.vy;
}
if (this.pressingRight === true) {
this.x += this.vx;
}
else if (this.pressingLeft === true) {
this.x -= this.vx;
}
}
}
所以我正在计算具有 calcDistance 常量的玩家之间的距离,如果 calcDistance = 200(玩家半径命中框 = 100,所以玩家 1 半径命中框 + 玩家 2 半径命中框 = 200),它应该做一些事情,但我不知道是什么
你能帮帮我吗?
像您一样使用 Math.hypot()
获取圆心之间的距离。查看该距离是否小于两个圆的半径。一旦你有了它,你就可以设置玩家的 x,y 和可选的 vx,vy。
x 将设置为 obj2.x
加上两个半径的总和乘以每个 x 和 y 值的距离除以总距离。更多三角数学...
这是一个例子
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 500;
class Circle {
constructor(x, y, c) {
this.x = x;
this.y = y;
this.color = c;
this.r = 30;
this.vx = 0;
this.vy = 0;
this.speed = 0.5;
}
draw() {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.r, 0, Math.PI*2);
ctx.fill();
}
update() {
if (controller.left) {
this.vx -= this.speed;
}
if (controller.up) {
this.vy -= this.speed;
}
if (controller.right) {
this.vx += this.speed;
}
if (controller.down) {
this.vy += this.speed
}
this.x += this.vx;
this.y += this.vy;
this.vx *= 0.9;
this.vy *= 0.9;
}
}
class Controller {
constructor() {
this.up = false;
this.right = false;
this.down = false;
this.left = false;
let keyEvent = (e) => {
if (e.code == "ArrowUp") {
this.up = e.type == "keydown";
}
if (e.code == "ArrowRight") {
this.right = e.type == "keydown";
}
if (e.code == "ArrowLeft") {
this.left = e.type == "keydown";
}
if (e.code == "ArrowDown") {
this.down = e.type == "keydown";
}
};
addEventListener("keydown", keyEvent);
addEventListener("keyup", keyEvent);
}
}
let player = new Circle(25, 25, 'blue');
let obstacle = new Circle(canvas.width/2, 150, 'red');
let controller = new Controller();
function collisionDetection(obj1, obj2) {
if (Math.hypot(obj1.x - obj2.x, obj1.y - obj2.y) <= obj1.r + obj2.r) {
collisionResponse(obj1, obj2)
}
}
function collisionResponse(obj1, obj2) {
let dx = obj1.x - obj2.x;
let dy = obj1.y - obj2.y;
let dist = (Math.hypot(obj1.x - obj2.x, obj1.y - obj2.y)) || 1;
let radii = obj1.r + obj2.r;
let x = dx / dist;
let y = dy / dist;
obj1.x = obj2.x + radii * x;
obj1.y = obj2.y + radii * y;
obj1.vx = 0; //optional
obj1.vy = 0; //optional
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
collisionDetection(player, obstacle)
player.update();
player.draw();
obstacle.draw();
requestAnimationFrame(animate);
}
animate();
<canvas id="canvas"></canvas>
设置 vx 和 vy 是可选的,可以防止发生任何重叠。你也可以选择不将它们设置为 0,你会有一些重叠,但圆圈看起来会更平滑地滑离彼此。