碰撞检测问题;对某些条件的奇怪反应

时间:2014-11-15 20:00:41

标签: javascript canvas 2d collision-detection rectangles

如果有人认为此问题过于具体,请随意将其删除。

我的碰撞检测有问题,我看过一些基本的碰撞检测技术,然后尝试调整它来判断哪一侧正在碰撞,但是当角落碰撞或角色有垂直时,检测似乎失败了碰撞时的水平速度。

继承我的碰撞检测功能:

this.checkCollision = function() {
        var isGround = false;
        var i;

        /*Combines Platforms and Chars so Character Collide with Eachother*/
        var x = platforms[level];
        var y = chars[level];
        var p = x.concat(y);

        /* For Readability */
        var top = this.y;
        var bottom = this.y + this.h;
        var left = this.x;
        var right = this.x + this.w;

        for (i = 0; i < p.length; i++) {
            /* For Readability */
            var pTop = p[i].y;
            var pBottom = p[i].y + p[i].h;
            var pLeft = p[i].x;
            var pRight = p[i].x + p[i].w;

            if (p[i] !== this) {
                if (this.inverted) {

                        /*Vertical-Top*/
                    if ((bottom === pTop) && (right > pLeft && left < pRight)) {

                        this.vy = -gravity;


                        /*Vertical-Near-Top*/
                    } else if ((bottom + this.vy >= pTop && bottom <= pTop) && (right > pLeft && left < pRight)) {

                        this.vy = pTop - bottom;

                        /*Vertical-Bottom*/
                    } else if ((top === pBottom) && (right > pLeft && left < pRight) && (this.vy <= 0)) {

                        isGround = true;
                        this.onGround = true;

                        /*Vertical-Near-Bottom*/
                    } else if ((top + this.vy <= pBottom && top >= pTop) && (right > pLeft && left < pRight)) {

                        this.vy = pBottom - top + gravity;

                    }
                } else {

                        /*Vertical-Top*/
                    if ((bottom === pTop) && (right > pLeft && left < pRight)) {

                        if (p[i].bouncy) {
                            this.vy = -(this.jumpVelocity * 1.2);
                        } else if (p[i] instanceof Char && !p[i].inverted) {
                            this.vx = this.current ? this.vx : p[i].vx;
                            if (p[i].onGround) {
                                isGround = true;
                                this.onGround = true;
                            } else {
                                this.vy = p[i].vy;
                            }
                        } else {
                            this.vx = this.current ? this.vx : 0;
                            isGround = true;
                            this.onGround = true;
                        }

                        /*Vertical-Near-Top*/
                    } else if ((bottom + this.vy >= pTop && bottom <= pTop) && (right > pLeft && left < pRight)) {

                        this.vy = pTop - bottom - gravity;

                        /*Vertical-Bottom*/
                    } else if ((top === pBottom) && (right > pLeft && left < pRight)) {

                        this.vy = gravity;

                        /*Vertical-Near-Bottom*/
                    } else if ((top + this.vy <= pBottom && top >= pTop) && (right > pLeft && left < pRight)) {

                        this.vy = top - pBottom;

                    }
                }
                /*Horizontal-Left*/
                if ((right === pLeft) && ((top < pTop && bottom > pTop) || (top < pBottom && bottom >= pBottom) || (top >= pTop && bottom <= pBottom)) && (this.vx > 0)) {

                    this.vx = 0;

                    /*Horizontal-Left-Near*/
                } else if ((right + this.vx >= pLeft && right <= pRight) && ((top < pTop && bottom > pTop) || (top < pBottom && bottom >= pBottom) || (top >= pTop && bottom <= pBottom)) && (this.vx > 0)) {

                    this.vx = pLeft - right;

                    /*Horizontal-Right*/
                } else if ((left === pRight) && ((top < pTop && bottom > pTop) || (top < pBottom && bottom >= pBottom) || (top >= pTop && bottom <= pBottom)) && (this.vx < 0)) {

                    this.vx = 0;

                    /*Horizontal-Right-Near*/
                } else if ((left + this.vx <= pRight && left >= pLeft) && ((top < pTop && bottom > pTop) || (top < pBottom && bottom >= pBottom) || (top >= pTop && bottom <= pBottom)) && (this.vx < 0)) {

                    this.vx = pRight - left;

                }
            }
        }
        if (!isGround) {
            this.onGround = false;
        }
    };

其余代码是JSFiddle(按T键进入测试级别,其中包含所有字符):http://jsfiddle.net/v5hhpt57/1/

另外我建议使用全屏结果,因为画布似乎不适合JSFiddle页面:http://tinyurl.com/twa-js(不是JSFiddle,由于JSFiddle的困难而导致的Google Site Hosting)

对于一个特定问题,在测试级别从蓝色顶部移除红色,将粉红色向右移动一点点,然后尝试在蓝色顶部反弹紫色。

最后不要介意在地面漂浮和下沉,这是在碰撞处理结束。

并再次: 如果有人认为此问题过于具体,请随意将其删除。

2 个答案:

答案 0 :(得分:0)

我正在用帆布制作游戏。我还是初学者,但为我的在线网络游戏做了一些基础知识。 我觉得这里碰撞几乎就像我的游戏鼠标。

Xerror = 2
Yerror = 3
monster_width = 20
monster_height = 20
mouseX  = evt.clientX-Xerror  //My mouse X position in canvas map
mouseY  = evt.clientY-Yerror  //My mouse Y position in canvas map   

for monster in all_monsters  //looping trough all monsters
if mouseX > monster.x_position[monster.id]-monster_width/2+Xerror*4  and mouseX< 
            monster.x_position[monster.id]+monster_width/2+Xerror*4  and mouseY>
            monster.y_position[monster.id]-monster_height/2+Yerror*2 and mouseY<
            monster.y_position[monster.id]+monster_height/2+Yerror*4    
// then my mouse is over one of the monsters

这些X错误可能是由于画布的边界很小,不知道,但没有这些错误输出。但我也从2减去我的怪物宽度/高度,以获得中心。 (我的怪物只是立方体)。

我自己的游戏是在gamegame.herokuapp.com,ID testeris,PWD testeris。如果你想和我联系,请发送电子邮件至magimantas@yahoo.com。我热衷于使用canvas,Ruby on rails,Backbone.js,coffeescript制作我的在线游戏。和其他喜欢用帆布创建游戏的人说话会很有趣:)

答案 1 :(得分:-1)

对于Tomb-Raider,我们有一个连接到面或顶点的球体列表。球体和三角形之间的检测很简单,因此许多小球体可以产生几乎完美的碰撞。在移动物体(所有球)和刚刚有旗帜的背景(可攀爬等)之间。 虽然我喜欢它,但是从C64开始就是一个技巧 - 使用带有2D Quad的房间。那么你只需要考虑在相邻房间中渲染物体,如果它们在通过将四边形扩展为方形/矩形(简单的4x4矩阵)而形成的矩形内部