使对象在画布中发生碰撞

时间:2013-12-06 19:07:32

标签: javascript canvas collision-detection

有几天我一直试图在JavaScript中碰撞对象。我有一个家庭作业来制作一个游戏,所以我告诉我为什么不制作一个关于圣诞节的游戏。所以我做了一些雪球产生,圣诞老人被箭头键移动,都在一个画布上。

所以现在我的问题。当这种情况发生时,我怎么能让这个圣诞老人和球碰撞并发出警告?我只知道如何在理论上做到这一点,但无法正确写下代码。

这是我的JavaScript:

window.onload = function () {
    var canvas = document.getElementById("canvas");
    canvas.focus();
    var ctx = canvas.getContext("2d");
    canvas.addEventListener('keydown', doKeyDown, true);
    var scorevalue = document.getElementById('number').value;
    //canvas dimensions
    var W = window.outerWidth - 300;
    var H = window.outerHeight - 200;
    canvas.width = W;
    canvas.height = H;
    var rectx = 400;
    var recty = 690;
    var rectwidth = 200;
    var rectheight = 200;
    var speed = 50;
    var change = 0;
    var thumbImg = document.createElement('img');
    thumbImg.src = "http://www.gettyicons.com/download/?id=3633&t=png&s=256";
    var character = document.createElement('img');
    character.src = "http://clipartist.info/SVG/CLIPARTIST.ORG/SANTA/santa_claus-999px.png";
    var mp = 11; //max particles
    var particles = [];
    for (var i = 0; i < mp; i++) {
        particles.push({
            x: Math.random() * W, //x-coordinate
            y: Math.random() * H - 1400, //y-coordinate
            r: 13, //radius
            d: Math.random() * mp //density
        })
    }
    var maxMoney = 10;
    var money = [];
    for (var i = 0; i < maxMoney; i++) {
        money.push({
            x: Math.random() * W, //x-coordinate
            y: Math.random() * H - 1600, //y-coordinate
        })
    }
    //var directions = {
    //    "left": -1,
    //    "right": +1,
    //    "up": -1,
    //    "down": +1
    //};                    
    function getRandomValue(min, max) {
        return (Math.random() * (max - min) + min) | 0;
    };

    function Img(rectx, recty, width, height, speed) {
        this.x = rectx;
        this.y = recty;
        this.width = width;
        this.height = height;
        this.speed = speed;

        this.draw = function (ctx) {
            ctx.drawImage(character, this.x, this.y, this.width, this.height);

        };
        this.moveRight = function () {
            this.x += speed;
        };
        this.moveLeft = function () {
            this.x -= speed;
        };
        this.returnCurrentX = function () {
            return this.x;
        };
        this.returnCurrentY = function () {
            return this.y;
        };
        this.xAfterMoveLeft = function () {                 
            return (this.x - speed);
        }
        this.xAfterMoveRight = function () {
            return (this.x + speed + this.width);
        }
    };



    //snowflake particles

    //Lets draw the flakes
    function draw() {
        requestAnimationFrame(draw);
        ctx.clearRect(0, 0, W, H);
        ctx.beginPath();
        for (var i = 0; i < mp; i++) {
            var p = particles[i];
            ctx.moveTo(p.x, p.y);
            ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, true);;
        }
        //ctx.beginPath();
        for (var i = 0; i < maxMoney; i++) {
            var m = money[i];
            ctx.moveTo(m.x, m.y);
            ctx.drawImage(thumbImg, m.x, m.y, 90, 90);
        }
        //ctx.moveTo(p.x, p.y);
        //ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, true);
        //}
        ctx.fill();
        update();
    }
    requestAnimationFrame(draw);
    //Function to move the snowflakes
    //angle will be an ongoing incremental flag. Sin and Cos functions will be applied to it to create vertical and horizontal movements of the flakes
    var angle = 0;
    function update() {
        angle += 0.01;
        for (var i = 0; i < mp; i++) {
            //Updating X and Y coordinates
            //We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards       
            var p = particles[i];

            p.y += Math.cos(angle + p.d) + 1 + p.r / 4;
            //Sending flakes back from the top when it exits
            if (p.x > W + 5 || p.x < -5 || p.y > H) {
                if (i % 3 > 0) //66.67% of the flakes
                {
                    particles[i] = { x: Math.random() * W, y: -10, r: p.r, d: p.d };
                }
            }
        }
        for (var i = 0; i < maxMoney; i++) {
            var m = money[i];
            m.y += Math.cos(angle + p.d) + 1 + p.r / 4;
            if (m.x > W + 20 || m.x < -10 || m.y > H) {
                if (i % 3 > 0) //66.67% of the flakes
                {
                    money[i] = { x: Math.random() * W, y: -10 };
                }
            }
        }
    }
    //animation loop
    sq = new Img(rectx, recty, rectwidth, rectheight, speed);

    function doKeyDown(e) {
        sq.draw(ctx);
        if (e.keyCode == 37) {
            var nextX = sq.xAfterMoveLeft();                    
            if (nextX > 0)
                sq.moveLeft();

            //alert(speed + "," + sq.returnCurrentX() + "," + sq.width + "," + canvas.width);
            //alert(speed + sq.returnCurrentX() + sq.width);
        }
        if (e.keyCode == 39) {
            var nextX = sq.xAfterMoveRight();
            if (nextX < canvas.width)
            sq.moveRight();

        }
        sq.draw(ctx);
        requestAnimationFrame(doKeyDown);

    }

    requestAnimationFrame(doKeyDown);
    function changeScore() {
        document.getElementById('number').value = change++;
        if (document.getElementById('number').value >= 101000000010100101010101010) {
            alert("You have made it :)");
        }
    }
    setInterval(changeScore, 40);
}

我的HTML正文:

<canvas style="border:3px solid black; background:red;" ID="canvas" tabindex="1">
    Canvas tag not supported
</canvas>
<input type="number" id="number" value="0" name="score">

我的CSS:

body {
    /*You can use any kind of background here.*/
    background: black;
}
canvas {
    display: block;
}

如果您愿意,还可以在完整的HTML文件中take a look,并设置a JSFiddle进行查看。

我知道我问的有点太多,但我相信有人可以在空闲时间帮助我。

1 个答案:

答案 0 :(得分:0)

您需要设置条件来更改每个元素的位置,就像设置条件来做事情与墙壁碰撞一样。

要做到这一点,有很多方法,但它们都遵循相同的模式:你需要检测碰撞,然后你需要解决它。

要检测碰撞,您可以在元素之间创建一个向量,并查看此向量的模块何时变为0.要获取模块,您可以使用如下函数:

function module (vector) {             
   var result = 0;
   for (var i  in vector){
    result += Math.pow(v[i],2);
        }
   return Math.pow(result,0.5);
        };  

简单地遵循模块的数学定义。

然后你需要得到物体之间的距离,可能是这样的:

  var distance = {

x : thing1.x - thing2.x,

y : thing1.y - thing2.y

        };  

然后情况会是这样的:

if ( module(distance) < thing1.length + thing2.length )

其中thing1和2应该是具有长度的对象。

之后,既然你只是想得到一个警报,解决这个问题要简单得多。