1

只是为那些不想阅读一大堆文字的人添加这个,至少阅读这个并查看图片以理解我的问题;
我在“玩家”和“对象”之间设置了碰撞,因此当“玩家”击中“对象”的“左侧”时,“玩家”被放在“对象”的“左侧”。(这就是我要的)。但我希望玩家能够击中对象的任何一侧(“顶部”、“左侧”、“右侧”、“底部”)并适当放置。 块碰撞示例图像 所以看上面的图片,基本上我试图在黑色方块和其他物体之间产生碰撞。黑色方块是“玩家”对象,灰色方块是编号的“墙壁”对象,红色方块是“下一级”对象。我已经完成了这个,但它有点混乱,当涉及到移动墙壁对象时,玩家碰撞不再像我想要的那样工作。所以无论如何这里是我的“墙”代码:

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;      }
}; 

我刚刚为 wall1,2,3,.. 等复制了相同的代码。我确信有更好的方法是如果有人可以提出更好的方法吗?我尝试在 2 个不同的地方绘制相同的精灵,但不知道如何正确实现这一点。我有不同的“墙”对象的主要原因是因为我需要根据“玩家”与“墙”对象碰撞的位置将“玩家”对象绘制在不同的位置。如果玩家从左侧飞入,player1.drawX = walls1.drawX - player width。但是如果玩家从顶部飞进来,player1.drawY = walls1.drawY + player1.height. 我需要所有碰撞都能够发生在任何“墙”对象上的原因是因为每当“玩家”对象到达“完成”时,我都会重新使用所有“墙”对象。如果我知道更好的系统,也许我可以继续使用我拥有的碰撞系统。无论如何,当“玩家”击中“完成”对象时会发生什么:

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;
}

我再次完成了“玩家”和“墙”之间的碰撞,但只是通过为每个“墙”创建一个单独的函数,当我想在不同的地方绘制“墙”时,这不起作用。如果这似乎需要阅读很多内容,我深表歉意,我试图只包含相关代码。非常感谢任何帮助/建议。

4

3 回答 3

2

从所有 4 个侧面检测矩形碰撞

在此处输入图像描述

给定这样定义的矩形对象:

var player={x:0,y:0, w:20,h:20};

var barrier={x:100,y:100, w:50,h:50};

您可以使用此功能测试 2 个矩形是否从任何一侧碰撞

// 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);
}

你会这样调用函数:

// test if the player and barrier are colliding

if( RectsColliding(player,barrier){
       console.log(‘BANG’);
}else{
       console.log(‘Congrats…No collision’);
}

即使您有许多障碍物,也很容易检查碰撞

var CollisionOccured=false;

for(var i=0;i<barriers.length;i++){
    if(RectsColliding(desiredPlayer,barriers[i])){
        CollisionOccured=true;
    }
} 

return(CollisionOccured);

这是代码和小提琴: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>
于 2013-07-30T06:27:20.120 回答
0

您可以检查屏幕 x/y 坐标,以及每个可碰撞对象的高度和宽度。

如果您的对撞机 x/y 在某个范围内,则应该触发碰撞。

(但这仅适用于块)

我找到了一个可能有帮助的小提琴:

http://jsbin.com/imofat/660/edit

于 2013-07-29T20:24:25.090 回答
0

所以我想出了一种适用于我正在尝试做的事情的方法。我不能使用类似 (player1.x >= wall1.x && player1.Y===walls1.Y)Or things similair 之类的东西,因为当它归结为在玩家的不同侧面有 4 个对象时……玩家的 X 值必须高于一堵墙并低于另一堵墙。与 Y 值相同。(这也使它有点波涛汹涌。)无论如何,这是我使用的:

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;

然后我添加了函数来让 leftkey = false 当玩家撞墙或游戏重新开始时。对于任何想知道 -16 的人,那是墙的一半宽度,所以玩家必须击中墙的中心才能被放置在墙旁边,因为我有 fps(无论如何我都在猜测)你永远不会看到玩家进入墙壁对象内部,因此看起来玩家完美地撞到了墙壁。-16 的原因是,当玩家尝试向左/向右移动时,墙壁完全位于玩家上方,墙壁不会检测到碰撞。

于 2013-07-31T05:48:25.883 回答