5
\$\begingroup\$

I have been using this code for a while for a project at work. Actually I got it from a friends who got it from a book. But either way it worked for my demonstration.

But the other night I decided to sit down and see if I could make it into all functions and then to see about moving the variables up to the top of each function. It would be normal for simple programming and everything should work, but when I did this, the code crashed and burned (didn't show anything in the canvas). It should show bouncing balls.

<!doctype html>
<html>
<head>
<title>Bounding Balls</title>
<script src="modernizr.js"></script>
<script type="text/javascript">
window.addEventListener('load', eventWindowLoaded, false);

function eventWindowLoaded() {
    canvasApp();    
}

function canvasSupport () {
    return Modernizr.canvas;
}

function canvasApp() {
  if (!canvasSupport()) {
             return;
  }

  function  drawScreen () {
        context.fillStyle = '#EEEEEE';
        context.fillRect(0, 0, theCanvas.width, theCanvas.height);
        //Box
        context.strokeStyle = '#000000'; 
        context.strokeRect(1,  1, theCanvas.width-2, theCanvas.height-2);
        //Place balls

        context.fillStyle = "#00AA00";
        var ball;//object

        for (var i =0; i <balls.length; i++) {
            ball    = balls[i];
            ball.x += ball.xunits;
            ball.y += ball.yunits;

            context.beginPath();
                context.arc(ball.x,ball.y,ball.radius,0,Math.PI*2,true);
            context.closePath();

            context.fill();

            if (ball.x > theCanvas.width || ball.x < 0 ) {
                ball.angle = 180 - ball.angle;
                updateBall(ball);
            } else if (ball.y > theCanvas.height || ball.y < 0) {
                ball.angle = 360 - ball.angle;
                updateBall(ball); 
            }
        }

    }

    function updateBall(ball) {
        ball.radians = ball.angle * Math.PI/ 180;
        ball.xunits = Math.cos(ball.radians) * ball.speed;
        ball.yunits = Math.sin(ball.radians) * ball.speed;
    }

    var numBalls = 100 ;
    var maxSize = 8;
    var minSize = 5;
    var maxSpeed = maxSize+5;
    var balls = new Array();
    var tempBall;
    var tempX;
    var tempY;
    var tempSpeed;
    var tempAngle;
    var tempRadius;
    var tempRadians;
    var tempXunits;
    var tempYunits;

    theCanvas = document.getElementById('canvasOne'); // <-- Code will not work if this is moved to the top of the method ---
    context = theCanvas.getContext('2d');

    for (var i = 0; i < numBalls; i++) {
        tempRadius = Math.floor(Math.random()*maxSize)+minSize;
        tempX = tempRadius*2 + (Math.floor(Math.random()*theCanvas.width)-tempRadius*2);
        tempY = tempRadius*2 + (Math.floor(Math.random()*theCanvas.height)-tempRadius*2);
        tempSpeed = maxSpeed-tempRadius;
        tempAngle =  Math.floor(Math.random()*360);
        tempRadians = tempAngle * Math.PI/ 180;
        tempXunits = Math.cos(tempRadians) * tempSpeed;
        tempYunits = Math.sin(tempRadians) * tempSpeed;

        tempBall = {x:tempX,y:tempY,radius:tempRadius, speed:tempSpeed, angle:tempAngle, xunits:tempXunits, yunits:tempYunits}
        balls.push(tempBall);
    }

    function gameLoop() {
        window.setTimeout(gameLoop, 20);
        drawScreen()    
    }

    gameLoop();
}
</script>

</head>
<body> 

    <div style="position: absolute; top: 50px; left: 50px;">
    <canvas id="canvasOne" width="500" height="500">
        Your browser does not support the HTML 5 Canvas. 
        </canvas>
    </div>

</body>
</html>

The code is similar to another post which I posted but in this cases I was wondering why these two lines of code could not be moved to the top of the function.

Code here that does not seem to work at the top of the function.

        theCanvas = document.getElementById('canvasOne'); 
        context   = theCanvas.getContext('2d');

My canvas will not see any of the code that is drawn two it if this code is at the top of the function.

How can this become more efficient?

\$\endgroup\$
4
  • \$\begingroup\$ Duplicate of codereview.stackexchange.com/questions/45790/… ? \$\endgroup\$
    – konijn
    Commented Mar 31, 2014 at 23:41
  • \$\begingroup\$ Asking to debug non-working code is off-topic for Code Review. However, after adding // before a stray remark, I got it to work for me. \$\endgroup\$ Commented Apr 1, 2014 at 0:09
  • \$\begingroup\$ It's more of a follow-up question than a duplicate. In the future, please link follow-up questions to their predecessors as a courtesy to other users. \$\endgroup\$ Commented Apr 1, 2014 at 0:13
  • \$\begingroup\$ This code works fine and I was the one that posted a similar example. Both of these are me, and if I need to I can remove this one if everyone wants me to. Just let me know. \$\endgroup\$ Commented Apr 1, 2014 at 0:22

1 Answer 1

2
\$\begingroup\$

I don't see any problem when I move the two lines you mentioned to an earlier position (directly after the check for canvas support).

  • You need to clean up the indention.

  • Use one var statement with the variables separater with commas instead of multiple statements.

  • No need to prefix all those variables with temp.... Also declare them inside the loop. That makes it clear that you only are using them in there.

  • Your code to generate random integers between two limits is wrong. tempRadius will be between 5 and 12, but the maxSize is 8.

  • tempX/tempY calculation adds 2*tempRadius, but then you subtract it again, so it has no effect. This is basiclly the same mistake as with the calculation of the radius (see next point). Also it seems to be the attempt to have the balls bounce when their size touch the walls instead of their center, but you fail to include this when calculating the bouncing.

  • Considering both your attempts to get a random integer between to limits are wrong, you should write a simple function that does that (correctly). Test it.

  • Apropos bouncing: The balls don't bounce off the walls any way. Currently they bounce when they happen to have passed the wall.

  • There is no need to floor tempAngle.

  • You can simplify the calculation of tempRadians to tempRadians = Math.random() * 2 * Math.PI .

  • There is no need to recalculate xunits/yunits of the ball from the angle. When a ball bounces off the left or right walls, then ball.xunits simply becomes -ball.xunits. (Equivalently the top and bottom walls and yunit)

  • You should use a module pattern to wrap your code, so you don't need to use global variables (`context´).

EDIT: Here's my version: http://jsfiddle.net/jjM3V/ (Not quite perfect, as it has some duplicate code in the bounce calculation, that I don't like).

\$\endgroup\$
8
  • \$\begingroup\$ Nice this is so much better. How long have you been working in Javascript. What is the best way in your opinion to declare and object in Javascript. I have seen many different ways. I assume on the fiddle page that the script has to be wrapped in a (function to make it work). \$\endgroup\$
    – Doug Hauf
    Commented Apr 1, 2014 at 13:05
  • \$\begingroup\$ I am reading up on the module pattern part, that was why the code was wrapped in a function declaration on the fiddle page. \$\endgroup\$
    – Doug Hauf
    Commented Apr 1, 2014 at 13:10
  • 1
    \$\begingroup\$ I've been working with JavaScript for far too long :) There is no best way for classes (not objects). I use the method that seems appropriate to the given task. Most of the time I stay away from classes (e.g. the new keyword) anyway. \$\endgroup\$
    – RoToRa
    Commented Apr 1, 2014 at 13:42
  • \$\begingroup\$ The doesn't "have to be" wrapped in a function, however this makes all enclosed functions and variables defined with var local to that function, so there are no global variables. \$\endgroup\$
    – RoToRa
    Commented Apr 1, 2014 at 13:48
  • \$\begingroup\$ From what I read in Javascript there should be no global variables used at all. Or how does this work? What if by changed you had one variable that you needed to use globaly but I guess if you had all of your code in a function wrapper there would be no really need for a global variable. \$\endgroup\$
    – Doug Hauf
    Commented Apr 1, 2014 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.