碰撞后如何保持玩家位置?
How to keep player position after collision?
我在 canvas 制作游戏,我已经包含了一个库来为我处理碰撞。
碰撞效果很好,但我不太确定如何 "freeze" 玩家在碰撞后不允许朝那个方向移动。谁能帮帮我?
我尝试了什么:
moveRight() {
this.pp.x = this.position.x;
this.position.x += 20;
}
moveLeft() {
this.pp.x = this.position.x;
this.position.x -= 20;
}
moveUp() {
this.pp.y = this.position.y;
this.position.y += 20;
}
moveDown() {
this.pp.y = this.position.y;
this.position.y -= 20;
}
我试着跟踪 "previous position" 并将其设置为碰撞时的那个,但它的行为真的很奇怪,实际上不起作用。
理想情况下,我想在我的播放器 class 中创建一个 stop() 函数,我会在播放器与世界发生碰撞时调用它。
非常感谢,非常感谢任何帮助! ! !
我使用 lib(https://github.com/RonenNess/SSCD.js/)to 为我做碰撞测试,这里是代码:
export function collisionDetection(game) {
let world = new SSCD.World({ grid_size: 1024 });
let player = new SSCD.Rectangle(
new SSCD.Vector(game.player.position.x, game.player.position.y),
new SSCD.Vector(game.player.width, game.player.height)
);
let zombie = new SSCD.Rectangle(
new SSCD.Vector(game.zombie.position.x, game.zombie.position.y),
new SSCD.Vector(game.zombie.width, game.zombie.height)
);
let walls = game.walls;
walls.forEach(wall => {
world.add(
new SSCD.Rectangle(
new SSCD.Vector(wall.position.x, wall.position.y),
new SSCD.Vector(wall.width, wall.height)
)
);
});
if (world.test_collision(player)) {
game.player.speed = 0;
return
}
一种方法是将 20
作为 class 的 property
。此 属性 将是“speed
”属性。然后您可以使用“this.speed
”访问它。一旦你检测到碰撞,将速度设置为 0
,你将 "freeze" 你的角色。
例如 moveRight 会变成
moveRight() {
this.pp.x = this.position.x;
this.position.x += this.speed;
}
一种低预算的方法是循环更新坐标(因此 x+=10
,执行 10 次 x++
),并且 "undo" 发生碰撞时的变化,请参阅最后的未命名函数(传递给 setInterval()
的函数):
function range(l,x,h){
return l<=x && x<h;
}
function rnd(r){
return Math.floor(Math.random()*r);
}
function Rect(x,y,w,h){
this.x=x;
this.y=y;
this.w=w;
this.h=h;
}
Rect.prototype.draw=function(ctx){
ctx.strokeRect(this.x,this.y,this.w,this.h);
};
Rect.prototype.contains=function(x,y){
return range(this.x,x,this.x+this.w) &&
range(this.y,y,this.y+this.h);
}
Rect.prototype.intersects=function(r){
return this.contains(r.x,r.y) ||
this.contains(r.x+r.w,r.y) ||
this.contains(r.x,r.y+r.h) ||
this.contains(r.x+r.w,r.y+r.h);
}
const player=new Rect(1,1,10,10);
const walls=[];
for(let i=0;i<5;i++){
let x=rnd(200);
let y=rnd(200);;
walls.push(new Rect(x+20,y+20,rnd(250-x)+10,rnd(250-y)+10));
}
function collide(){
if(player.x<=0 || player.y<=0 ||
player.x+player.w>=300 || player.y+player.h>=300)
return true;
for(let i=0;i<walls.length;i++)
if(walls[i].intersects(player))
return true;
return false;
}
const ctx=cnv.getContext("2d");
function draw(){
ctx.clearRect(0,0,300,300);
ctx.strokeStyle="#FF0000";
ctx.strokeRect(0,0,300,300);
ctx.strokeStyle="#0000FF";
for(let i=0;i<walls.length;i++)
walls[i].draw(ctx);
ctx.strokeStyle="#00FF00";
player.draw(ctx);
}
draw();
const keymap=[false,false,false,false];
addEventListener("keydown",function(event){
if(range(37,event.keyCode,41))
keymap[event.keyCode-37]=true;
});
addEventListener("keyup",function(event){
if(range(37,event.keyCode,41))
keymap[event.keyCode-37]=false;
});
setInterval(function(){
for(let i=0;i<10;i++){
if(keymap[0]){
player.x--;
if(collide())
player.x++;
}
if(keymap[1]){
player.y--;
if(collide())
player.y++;
}
if(keymap[2]){
player.x++;
if(collide())
player.x--;
}
if(keymap[3]){
player.y++;
if(collide())
player.y--;
}
}
draw();
},100);
<canvas id="cnv" width="300" height="300"></canvas>
"Game" 应该响应方向键,甚至可以同时按下多个方向键。另外,在开始后使用 "Full page",因为它不适合这里的方框,无论如何箭头都会疯狂地滚动所有内容。哦,它需要单击 canvas 一次。
我也看到了编辑,我想你可以检查那个页面的 https://github.com/RonenNess/SSCD.js#resolve-penetration-or-penetration-prevention 部分,然后试验 repel()
.
我在 canvas 制作游戏,我已经包含了一个库来为我处理碰撞。 碰撞效果很好,但我不太确定如何 "freeze" 玩家在碰撞后不允许朝那个方向移动。谁能帮帮我?
我尝试了什么:
moveRight() {
this.pp.x = this.position.x;
this.position.x += 20;
}
moveLeft() {
this.pp.x = this.position.x;
this.position.x -= 20;
}
moveUp() {
this.pp.y = this.position.y;
this.position.y += 20;
}
moveDown() {
this.pp.y = this.position.y;
this.position.y -= 20;
}
我试着跟踪 "previous position" 并将其设置为碰撞时的那个,但它的行为真的很奇怪,实际上不起作用。
理想情况下,我想在我的播放器 class 中创建一个 stop() 函数,我会在播放器与世界发生碰撞时调用它。
非常感谢,非常感谢任何帮助! ! !
我使用 lib(https://github.com/RonenNess/SSCD.js/)to 为我做碰撞测试,这里是代码:
export function collisionDetection(game) {
let world = new SSCD.World({ grid_size: 1024 });
let player = new SSCD.Rectangle(
new SSCD.Vector(game.player.position.x, game.player.position.y),
new SSCD.Vector(game.player.width, game.player.height)
);
let zombie = new SSCD.Rectangle(
new SSCD.Vector(game.zombie.position.x, game.zombie.position.y),
new SSCD.Vector(game.zombie.width, game.zombie.height)
);
let walls = game.walls;
walls.forEach(wall => {
world.add(
new SSCD.Rectangle(
new SSCD.Vector(wall.position.x, wall.position.y),
new SSCD.Vector(wall.width, wall.height)
)
);
});
if (world.test_collision(player)) {
game.player.speed = 0;
return
}
一种方法是将 20
作为 class 的 property
。此 属性 将是“speed
”属性。然后您可以使用“this.speed
”访问它。一旦你检测到碰撞,将速度设置为 0
,你将 "freeze" 你的角色。
例如 moveRight 会变成
moveRight() {
this.pp.x = this.position.x;
this.position.x += this.speed;
}
一种低预算的方法是循环更新坐标(因此 x+=10
,执行 10 次 x++
),并且 "undo" 发生碰撞时的变化,请参阅最后的未命名函数(传递给 setInterval()
的函数):
function range(l,x,h){
return l<=x && x<h;
}
function rnd(r){
return Math.floor(Math.random()*r);
}
function Rect(x,y,w,h){
this.x=x;
this.y=y;
this.w=w;
this.h=h;
}
Rect.prototype.draw=function(ctx){
ctx.strokeRect(this.x,this.y,this.w,this.h);
};
Rect.prototype.contains=function(x,y){
return range(this.x,x,this.x+this.w) &&
range(this.y,y,this.y+this.h);
}
Rect.prototype.intersects=function(r){
return this.contains(r.x,r.y) ||
this.contains(r.x+r.w,r.y) ||
this.contains(r.x,r.y+r.h) ||
this.contains(r.x+r.w,r.y+r.h);
}
const player=new Rect(1,1,10,10);
const walls=[];
for(let i=0;i<5;i++){
let x=rnd(200);
let y=rnd(200);;
walls.push(new Rect(x+20,y+20,rnd(250-x)+10,rnd(250-y)+10));
}
function collide(){
if(player.x<=0 || player.y<=0 ||
player.x+player.w>=300 || player.y+player.h>=300)
return true;
for(let i=0;i<walls.length;i++)
if(walls[i].intersects(player))
return true;
return false;
}
const ctx=cnv.getContext("2d");
function draw(){
ctx.clearRect(0,0,300,300);
ctx.strokeStyle="#FF0000";
ctx.strokeRect(0,0,300,300);
ctx.strokeStyle="#0000FF";
for(let i=0;i<walls.length;i++)
walls[i].draw(ctx);
ctx.strokeStyle="#00FF00";
player.draw(ctx);
}
draw();
const keymap=[false,false,false,false];
addEventListener("keydown",function(event){
if(range(37,event.keyCode,41))
keymap[event.keyCode-37]=true;
});
addEventListener("keyup",function(event){
if(range(37,event.keyCode,41))
keymap[event.keyCode-37]=false;
});
setInterval(function(){
for(let i=0;i<10;i++){
if(keymap[0]){
player.x--;
if(collide())
player.x++;
}
if(keymap[1]){
player.y--;
if(collide())
player.y++;
}
if(keymap[2]){
player.x++;
if(collide())
player.x--;
}
if(keymap[3]){
player.y++;
if(collide())
player.y--;
}
}
draw();
},100);
<canvas id="cnv" width="300" height="300"></canvas>
"Game" 应该响应方向键,甚至可以同时按下多个方向键。另外,在开始后使用 "Full page",因为它不适合这里的方框,无论如何箭头都会疯狂地滚动所有内容。哦,它需要单击 canvas 一次。
我也看到了编辑,我想你可以检查那个页面的 https://github.com/RonenNess/SSCD.js#resolve-penetration-or-penetration-prevention 部分,然后试验
repel()
.