Холст Для Рисования/Анимации


Я пытаюсь научиться писать хороший, чистый, и эффективный код JavaScript. Я считаю себя новичком, в лучшем случае, в JavaScript. Любые комментарии приветствуются.

В стремлении стать лучше JavaScript программист, я пытаюсь написать простой JavaScript анимации используя новый элемент canvas в HTML5. Функционально говоря, при щелчке мышью, новый круг (или шар) добавляется на холст и начинает двигать в правый нижний угол холста. Когда мяч попадает в стену, или сталкивается с другим шаром, скорость, с которой координаты X и y движутся инвертируется.

Это хорошая идея, чтобы изменить этот объект? Например, делает следующий шаблон имеет смысла?

function Point(I) {
    this.x = I.x;
    this.y = I.y;
    this.z = I.z;
    return this;
}

Есть ли причина, почему я не должен отправить объект и потянуть переменные из объекта ввода? Мне нравится синтаксис для создания, но есть какие-то проблемы с этим шаблоном?

new Point({
    x: 10,
    y: 30
});
new Point({
    x: 50,
    y: 25
    z: 3
});

Полный Код

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Ball Collision</title>
<script src="js/modernizr-1.7.js"></script>
<script>
    window.onload = function () {
        //"use strict";

        // Source: http://www.html5rocks.com/tutorials/canvas/notearsgame/
        Number.prototype.clamp = function(min, max) {
            return Math.min(Math.max(this, min), max);
        };


        if (Modernizr.canvas) {
            var canvas = document.createElement('canvas'),
                ctx = canvas.getContext('2d');


            canvas.width = 500;
            canvas.height = 375;
            canvas.style.border = "3px solid red";

            function Point(I) {
                console.log("Point created");
                this.x = I.x;
                this.y = I.y;
                this.z = I.z;
                return this;
            }

            function Ball(I) {
                console.log("Ball created");

                var SPEED_LIMIT = 10;

                this.point = new Point(I.point);
                this.radius = (I.radius > 10 ? I.radius : 10);
                this.color = I.color;
                this.speed = new Point(I.speed);
                this.collision = false;
                this.mass = I.mass || 1;

                this.draw = function() {
                    this.point.x = this.point.x.clamp(0 + this.radius, canvas.width - this.radius);
                    this.point.y = this.point.y.clamp(0 + this.radius, canvas.height - this.radius);
                    ctx.beginPath();
                    ctx.arc(this.point.x, this.point.y, this.radius, 0, Math.PI*2, false);
                    ctx.closePath();
                    ctx.fillStyle = this.color;
                    ctx.fill();
                };

                this.update = function() {
                    this.clear();

                    if ( this.point.x <= this.radius || this.point.x >= (canvas.width - this.radius)) {
                        this.speed.x *= -1;
                    }

                    if ( this.point.y <= this.radius || this.point.y >= (canvas.height - this.radius)) {
                        this.speed.y *= -1;
                    }

                    if ( this.speed.x > SPEED_LIMIT ) {
                        this.speed.x = SPEED_LIMIT;
                    }
                    if ( this.speed.x < SPEED_LIMIT * -1 ) {
                        this.speed.x = SPEED_LIMIT * -1;
                    }
                    if ( this.speed.y > SPEED_LIMIT ) {
                        this.speed.y = SPEED_LIMIT;
                    }
                    if ( this.speed.y < SPEED_LIMIT * -1 ) {
                        this.speed.y = SPEED_LIMIT * -1;
                    }

                    this.point.x += this.speed.x;
                    this.point.y += this.speed.y;
                };

                this.clear = function() {
                    ctx.beginPath();
                    ctx.arc(this.point.x - 1, this.point.y - 1, this.radius + 2, 0, Math.PI*2, false);
                    ctx.closePath();
                    ctx.fillStyle = "#fff";
                    ctx.fill();
                };

                return this;
            }

            var balls = [];

            function handleCollisions() {
                function collide(ball1, ball2) {
                    ball1.speed.x *= -1;
                    ball2.speed.x *= -1;
                    ball1.speed.y *= -1;
                    ball2.speed.y *= -1;
                }


                function checkCollisions() {
                    var i, j, a, b;

                    for ( i = 0; i < balls.length; i++ ) {
                        for ( j = i+1; j < balls.length; j++ ) {
                            a = balls[i];
                            b = balls[j];

                            var dx = Math.abs(a.point.x - b.point.x);
                            var dy = Math.abs(a.point.y - b.point.y);
                            var d = (dx*dx)+(dy*dy);
                            var r = (a.radius + b.radius) * (a.radius + b.radius);

                            if ( d < r && ( !a.collision || !b.collision ) ) {
                                a.collision = true;
                                b.collision = true;
                                collide(a, b);
                            } else if ( d > r ) {
                                a.collision = false;
                                b.collision = false;
                            }                           
                        }
                    }
                }

                checkCollisions();
            }

            function update() {
                balls.forEach(function(ball) {
                    ball.update();
                });

                handleCollisions();
            }

            function draw() {
                balls.forEach(function(ball) {
                    ball.draw();
                });
            }

            var FPS = 30;
            var loop = setInterval( function() {
                update();
                draw();
            }, 1000/FPS);

            canvas.onclick = function(e) {              
                var radiusAndMass = Math.floor(Math.random() * 50) + 1;
                var speed = Math.floor(Math.random() * 10) + 1;

                balls.push(new Ball({
                    point: {
                        //x: Math.floor(Math.random() * canvas.width),
                        //y: Math.floor(Math.random() * canvas.height),
                        x: e.offsetX,
                        y: e.offsetY
                    },
                    color: "#"+((1<<24)*Math.random()|0).toString(16),
                    radius: radiusAndMass,
                    mass: radiusAndMass,
                    speed: {
                        x: speed,
                        y: speed
                    }
                }));
            };


            document.getElementById('canvas-container').appendChild(canvas);
        }
    };
</script>   
</head>
<body>
<div id="wrap">
    <div id="canvas-container">

    </div>
</div>
</body>
</html>


1029
8
задан 18 апреля 2011 в 04:04 Источник Поделиться
Комментарии
1 ответ

Я думаю, что шаблон-это хорошо. Это имеет то преимущество, что у вас есть "именованные аргументы", которые очень легко читаются и могут быть полезными, если вы вызываете какую-то функцию/конструктор с различными наборами аргументов.

Единственное, что я хотел бы предложить, чтобы использовать другое имя для параметра, потому что заглавные буквы обычно используются для функции конструктора:

function Point(p) {
this.x = p.x;
this.y = p.y;
this.z = p.z;
return this;
}

2
ответ дан 19 апреля 2011 в 02:04 Источник Поделиться