The Nature of Motion on the Canvas, Step 4, Hits?

Example F.11. animateh.html

You will have noticed that in last last step the objects moved. Unidirectional and not stopping a the border. If we want them to bounce off the edge of the canvas, and move the opposite way, we need another step.

The code checks the distance between this object, and all other objects in a loop. For each object the distance is calculated using the Pythagorean theorem. If the distance is less than the sum of the two involved radii, there's a hit.

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>Canvas, Motion, Step 3, Optional Bouncing</title>
        <style>
            #canvas { border: 2px solid blue; }
        </style>
        <script src='nQuery.js'></script>   <!-- access to framework -->
        <script>
            'use strict';
            let Canvas = {
                init(canvasId, color) {     // note new syntax
                    this.canvas = $(canvasId);
                    this.context = this.canvas.getContext("2d");
                    this.color = color;
                    this.context.fillStyle = color;
                    this.context.fillRect(0, 0, this.canvas.width, 
                                          this.canvas.height);
                },
                getContext() {
                    return this.context;
                },
                clear() {
                    this.context.clearRect(0, 0, this.canvas.width, 
                                           this.canvas.height);
                },
                prep() {
                    this.context.fillStyle = this.color;
                    this.context.fillRect(0, 0, this.canvas.width, 
                                          this.canvas.height);
                },
                getHeight() {
                    return this.canvas.height;
                },
                getWidth() {
                    return this.canvas.width;
                }
            }

            let UFO = {
                init(canvas, color) {
                    this.canvas = canvas;
                    this.x = Math.random() * this.canvas.getWidth();
                    this.y = Math.random() * this.canvas.getHeight();
                    this.r = Math.random() * 9 + 3;
                    this.dx = Math.random() * 5;
                    this.dy = Math.random() * 5;
                    this.color = color;
                    this.draw();
                },
                draw() {
                    this.canvas.getContext().beginPath();
                    this.canvas.getContext().fillStyle = this.color;
                    this.canvas.getContext().arc(this.x, this.y, this.r,
                                                 0, Math.PI * 2,
                                                 false);
                    this.canvas.getContext().fill();
                    this.canvas.getContext().closePath();
                },
                getX() {
                    return this.x;
                },
                getY() {
                    return this.y;
                },
                getR() {
                    return this.r;
                },
                move() {
                    if (this.x + this.dx > this.canvas.getWidth()
                            || this.x + this.dx < 0)    // at edge?
                          this.dx = -this.dx;           // change direction
                    if (this.y + this.dy > this.canvas.getHeight()
                            || this.y + this.dy < 0)    // at edge
                          this.dy = -this.dy;           // change direction
                    this.x += this.dx;  // move object horizontally
                    this.y += this.dy;  // move vertically
                },
                hits(arr, me) {
                    for (var ob of arr) {               // iterate over balls
                        if (Object.is(ob, me)) {        // myself?
                            continue;                   // uninteresting
                        }
                        if (Math.sqrt(                  // dist < r1 + r2 => hit
                            Math.pow(ob.getX() - me.getX(), 2) +
                            Math.pow(ob.getY() - me.getY(), 2))
                            <= (ob.getR() + me.getR())) {
                                console.log("Ball " + ob.color + " hit ball " + me.color);
                                // this print is for test only
                                // a game would invent an explosion here
                                // or one object swallows another, or ...
                        }
                    }
                }
            }

            let motor = function (cv, obs) {
                setInterval(function() {            // animate
                    cv.clear();
                    cv.prep();
                    for (let obj of obs) {
                        obj.move();                 // iterate over
                        obj.hits(obs, obj);
                        obj.draw();                 // all array values
                    }
                }, 10);
            }
            
            let initialize = function () {
                let canvas = Object.create(Canvas); // create canvas
                canvas.init('canvas', '#ccc');
                let ufos = [];                      // create array
                let ufo0 = Object.create(UFO);      // create ufo
                ufo0.init(canvas, '#f00');
                ufos.push(ufo0);                    // add ufo to array
                ufo0 = Object.create(UFO);          // create ufo          
                ufo0.init(canvas, '#080');
                ufos.push(ufo0);                    // add ufo to array
                ufo0 = Object.create(UFO);          // create ufo
                ufo0.init(canvas, '#00f');
                ufos.push(ufo0);                    // add ufo to array
                ufo0 = Object.create(UFO);          // create ufo          
                ufo0.init(canvas, '#560');
                ufos.push(ufo0);                    // add ufo to array
                ufo0 = Object.create(UFO);          // create ufo
                ufo0.init(canvas, '#056');
                ufos.push(ufo0);                    // add ufo to array
                motor(canvas, ufos);                // start motor 
            }

            window.addEventListener('load', initialize, false);
        </script>
    </head>
    <body>
        <section>
            <canvas id='canvas' width='400' height='400'>
                If you see this text long enough to read it,
                your browser is very old.
            </canvas>
        </section>
    </body>
</html>

Test it!