问题
Just adding this for the people not looking to read a whole bunch of text, at least read this and look at the picture to understand my question;
I have collision set up between the "player" and "objects", so that when the "player" hits the "Left" of the "object" the "player" is put to the "Left" of the "object". (this is what i want). But I would like the player to be able to hit any side ("top","left","right","bottom") of the object and be placed appropriately.

var canvasWalls1 = document.getElementById('canvasWalls');
var ctxWalls1 = canvasWalls.getContext('2d');
var walls1 = new Walls1();
var imgSprite = new Image();
imgSprite.src = 'sprite.png';
imgSprite.addEventListener('load',init,false);
WallLeft.prototype.draw = function (){
ctxWalls1.drawImage(imgSprite,this.srcX,this.srcY,this.width,this.height,this.drawX,this.drawY,this.width,this.height);
this.checkHitPlayer();
};
WallLeft.prototype.checkHitPlayer = function() {
if (this.drawX > player1.drawX &&
this.drawX <= player1.drawX + player1.width &&
this.drawY >= player1.drawY &&
this.drawY < player1.drawY + player1.height) {
player1.isUpKey = false;
player1.isDownKey = false;
player1.isRightKey = false;
player1.isLeftKey = false;
player1.drawX = this.drawX - player1.width - 0.05;
player1.drawY = this.drawY - 0.05; }
};
I just copied the same code for wall1,2,3,.. etc. I'm sure there is a better way of doing this is if anybody could maybe suggest a better one? I'v tried drawing the same sprite in 2 different places, but can't figure out how to properly achieve this. The main reason I have different "walls" objects is because I need to draw the "player" object In a different position depending on where the "player" collides with the "wall" object.
If the player flys in from the Left, player1.drawX = walls1.drawX - player width
.
But if the player flys in from the top, player1.drawY = walls1.drawY + player1.height
.
The reason I need all collisions to be able to happen on any "wall" object, Is because i re-use all of the "wall" objects whenever the "player" object reaches the "finish".
If i knew of a better system, maybe I could continue using the collision system I have. anyways here is what happens when the "player" hits the "finish" object:
Finish.prototype.checkHitPlayer = function() {
if (this.drawX >= player1.drawX &&
this.drawX <= player1.drawX + player1.width &&
this.drawY >= player1.drawY &&
this.drawY <= player1.drawY + player1.height) {
increaseLevel();
} };
function increaseLevel() {
Level+=1;
if (Level===2) {
drawlevel2(); }
function drawlevel2()
{
player1.drawX = 288;
player1.drawY = 160;
walls1.drawX = 448;
walls1.drawY = 160;
walls2.drawX = 416;
walls2.drawY = 320;
walls3.drawX = 192;
walls3.drawY = 288;
finish1.drawX = 224
finish1.drawY = 96;
}
Again I have accomplished collision between the "player" and the "walls", but only by creating a separate function for every "wall", which doesn't work when I want to draw the "walls" in different places. I apologize if this seems like a lot to read, I tried to only include the relevant code. Any help/suggestions is much appreciated.
回答1:
Detecting rectangular collisions from all 4 sides

Given rectangle objects defined like this:
var player={x:0,y:0, w:20,h:20};
var barrier={x:100,y:100, w:50,h:50};
You can use this function to test if the 2 rectangles are colliding from any side
// return true if the 2 rectangles are colliding
function RectsColliding(r1,r2){
return !(r1.x>r2.x+r2.w || r1.x+r1.w<r2.x || r1.y>r2.y+r2.h || r1.y+r1.h<r2.y);
}
And you would call the function like this:
// test if the player and barrier are colliding
if( RectsColliding(player,barrier){
console.log(‘BANG’);
}else{
console.log(‘Congrats…No collision’);
}
It’s easy to check for collisions even if you have many barrier objects
var CollisionOccured=false;
for(var i=0;i<barriers.length;i++){
if(RectsColliding(desiredPlayer,barriers[i])){
CollisionOccured=true;
}
}
return(CollisionOccured);
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/sJfbd/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var defaultFill="lightgray";
var defaultStroke="skyblue";
ctx.fillStyle=defaultFill;
ctx.strokeStyle=defaultStroke;
var player={x:0,y:0, w:20,h:20, fill:"black",stroke:"black"};
console.log(player.fill);
var barriers=[];
barriers.push({x:50 ,y:100, w:40,h:30});
barriers.push({x:200,y:230, w:20,h:20});
barriers.push({x:150,y:100, w:20,h:20});
barriers.push({x:150,y:200, w:20,h:20});
barriers.push({x:240,y:25, w:10,h:150});
drawAll();
function drawAll(){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<barriers.length;i++){
drawRect(barriers[i]);
}
drawRect(player,player.fill,player.stroke);
}
function drawRect(r,fill,stroke){
ctx.beginPath();
ctx.rect(r.x,r.y,r.w,r.h);
ctx.closePath();
ctx.fillStyle=fill||defaultFill;
ctx.fill();
ctx.strokeStyle=stroke||defaultStroke;
ctx.stroke();
}
function movePlayer(desiredMoveX,desiredMoveY){
// calculate where the player would like to be
var desiredPlayer={
x:player.x+desiredMoveX,
y:player.y+desiredMoveY,
w:player.w,
h:player.h,
fill:"black",
stroke:"black"
}
// to start, set the move to be allowed
var allowMove=true;
// check every barrier for collisions
for(var i=0;i<barriers.length;i++){
// if the desiredPlayer has collided with a barrier
// set the allowMove flag to false
if(RectsColliding(desiredPlayer,barriers[i])){
allowMove=false;
}
}
// if the move is allowed, return the desiredPlayer position
// if the move is not allowed, return the old player position
if(allowMove){
player=desiredPlayer;
player.stroke="black";
}else{
player.stroke="red";
}
// redraw the screen
drawAll();
}
// return true if the 2 rectangles are colliding
function RectsColliding(r1,r2){
return !(r1.x>r2.x+r2.w || r1.x+r1.w<r2.x || r1.y>r2.y+r2.h || r1.y+r1.h<r2.y);
}
$(document).bind("keydown",function(event) {
switch(event.which){
case 37:
movePlayer(-1,0);
break;
case 39:
movePlayer(1,0);
break;
case 38:
movePlayer(0,-1);
break;
case 40:
movePlayer(0,1);
break;
default:
break;
}
});
}); // end $(function(){});
</script>
</head>
<body>
<p>Use arrowkeys to move player (black box)</p>
<p>Player's outline will become red if hitting barrier</p>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
回答2:
You can check the screen x/y coordinates, and the height and width of each collidable object.
if your colliders x/y are within a certain range, then that should trigger a collision.
(but that will only work for blocks)
I have found a fiddle that might help:
http://jsbin.com/imofat/660/edit
回答3:
So I figured out a method that works for what I am trying to do. I can't use something like
(player1.x >= wall1.x && player1.Y===walls1.Y)
Or things similair because when it came down to having 4 objects on differents sides of the player... The player's X value would have to be higher than a wall and lower than another. Same as the Y value. (this also makes it kind of choppy.) Anyways here is what I used:
Player.prototype.checkHitWall = function() {
this.TopY = this.drawY; this.BottomY = this.drawY + this.height; this.LeftX = this.drawX; this.RightX = this.drawX + this.width;
if (this.LeftX===walls1.x + walls1.width - 16 && this.drawY===walls1.y) //If player flys in from the RIGHT of wall1
{
player1.isUpKey = false; player1.isDownKey = false; player1.isRightKey = false; player1.isLeftKey = false;
upkey = false;
rightkey = false;
downkey = false;
leftkey = true;
this.drawX = walls1.x + walls1.width;
this.drawY = walls1.y;
Then I added functions to make the leftkey = false when the player hits a wall, or the game restarts. for anyone wondering about the -16, thats half the wall's width, so the player must hit the center of the wall in order to be placed next to the wall, because of the fps i have (im guessing anyway) You don't ever see the player go inside of the wall object, so it actually looks like the player hits the wall perfectly. The reason for the -16 is so that when the player tries to go left/right with a wall perfectly above the player, the wall doesn't detect a collision.
来源:https://stackoverflow.com/questions/17932679/how-do-i-create-2d-object-collision-from-every-sidetop-left-bottom-right-prope