我正在用画布制作游戏,并且我包括一个库来为我处理碰撞。 碰撞工作正常,但是我不确定如何将玩家“冻结”到位,并且在碰撞后不允许沿该方向移动。有人可以帮我吗?
我尝试过的事情:
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;
}
我尝试跟踪“先前位置”并将其设置为发生碰撞时的位置,但是它的表现确实很奇怪,实际上并不起作用。
理想情况下,我想在玩家类中创建一个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
}
答案 0 :(得分:3)
一种实现方法是将20
作为课程的property
。此属性将是“ speed
”属性。然后,您可以使用“ this.speed
”来访问它。一旦检测到碰撞,将速度设置为0
,您将“冻结”角色。
例如moveRight将变为
moveRight() {
this.pp.x = this.position.x;
this.position.x += this.speed;
}
答案 1 :(得分:1)
一种低成本的方法是循环更新坐标(因此,x+=10
进行10次x++
),并在发生碰撞时“撤消”更改,请参见未命名函数在最后(传递给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>
“游戏”应该响应箭头键,甚至可以同时按下多个键。另外,在开始后使用“整页”,因为它不适合此处的框,并且箭头无论如何都会疯狂滚动所有内容。哦,它需要单击画布一次。
repel()
。