0
\$\begingroup\$

I am making a 2d baseball game with JavaScript and HTML5 and am trying to move an image that I have drawn with JavaScript like so:

    //canvas
    var c = document.getElementById("gameCanvas");
    var ctx = c.getContext("2d");
    //baseball
    var baseball = new Image();
    baseball.onload = function() {
        ctx.drawImage(baseball, 400, 425);
    };
    baseball.src = "baseball2.png";

I'm not sure how I would move it though, I have seen many people seem to just type something like ballX and ballY but I don't understand where the actual x and y definition comes from. Here is my code so far:

http://jsfiddle.net/xRfua/

I have a different image source but it is a local source so I didn't include it. Thanks in advance for any help at all!

\$\endgroup\$
2
\$\begingroup\$

One reasonable approach would be to use a requestAnimationFrame loop to update your X and Y, and draw again repeatedly. This would involve computing delta time, and using it to animate your coordinates. Here's an example jsfiddle:

//canvas
var c = document.getElementById("gameCanvas");
var ctx = c.getContext("2d");
//baseball
var baseball = new Image();

var drawFunc = function() {
    //do animation logic
    updateBall();

    //draw new stuff
    ctx.clearRect(0, 0, c.width, c.height);
    ctx.drawImage(baseball, baseballX, baseballY);

    //wait for next frame
    //requestAnimationFrame(drawFunc);

    //because the web is annoying, here's a hack to make it work
    if (window.requestAnimationFrame) {
        requestAnimationFrame(drawFunc);
    } else if (window.webkitRequestAnimationFrame) {
        webkitRequestAnimationFrame(drawFunc);
    } else if (window.mozRequestAnimationFrame) {
        mozRequestAnimationFrame(drawFunc);
    }
};

baseball.onload = function() {
    drawFunc();
};
baseball.src = "http://a3.mzstatic.com/us/r30/Purple6/v4/aa/65/fe/aa65fe9a-9a78-2abb-567c-d439c782d9c8/mzl.xwveiniy.175x175-75.jpg";

//ball movement
var baseballX = 0;
var baseballY = 0;
var lastTime = new Date().getTime();
var speed = 0.25;

var updateBall = function() {
    //calculate time passed
    var rightNow = new Date().getTime();
    var elapsedTime = rightNow - lastTime;
    lastTime = rightNow;

    //animate
    baseballX += speed * elapsedTime;
    if (baseballX>300) baseballX = 0;

    baseballY += speed * elapsedTime;
    if (baseballY>425) baseballY = 0;
}

A less effective, but simpler, approach would be to use a fixed timestep. This can be achieved with a function like setInterval or setTimeout. Be warned there are issues with these routes: setInterval might create a queue of frames to draw faster than they can be pushed. setTimeout might leave you waiting too long for your next frame. With that said, here is another example jsfiddle

// main changes only
...
baseball.onload = function() {
    setInterval(drawFunc, 1000/fps);
};
...
//ball movement
var baseballX = 0;
var baseballY = 0;
var fps = 48;
var speed = 0.25;

var updateBall = function() {
    //calculate time passed
    var elapsedTime = 1000 / fps;
...

EDIT: and just for completeness, an example showing the css 3 transitions method

.loading {
    transition: 1s all;
    -webkit-transition: 1s all;
    -moz-transition: 1s all;
    position: absolute;
    top: 0px;
    left: 0px;
}

.animated {
    top: 250px;
    left: 300px;
}
\$\endgroup\$
  • \$\begingroup\$ I'm not sure this is what I need exactly, is there a way I could do it without using the time? \$\endgroup\$ – Geroy290 May 31 '14 at 23:01
  • \$\begingroup\$ I'm sorry, but in order for your position to vary over time (to move), you need to consider time. There are css 3 transitions, but I did not cover them as they are not really suitable for game development as John Haugeland pointed out. -- There is a simpler, but less effective approach: If the complexity of delta-time is too high, you can use fixed-time with a "constant" frame rate, this can be achieved by a function such as setInterval \$\endgroup\$ – MickLH Jun 1 '14 at 10:31
1
\$\begingroup\$

MickLH's answer was the right one, but your response was "is there a way I could do it without using the time?"

And yes, hilariously, there is. Use CSS to set your locations, and set a transition. This would be a very bad idea for most games; keeping animations in sync this way would be a huge pain in the ass, and since you said baseball, you're very likely in that group. You should do it MickLH's way.

But if you're doing something where sync doesn't matter, like a board or card game, then this is the hella easy way.

Made you something to look at: https://github.com/StoneCypher/chessboard_html

Or, I gather some people prefer codepens: http://codepen.io/StoneCypher/pen/taKsk

Note that we have nice smooth implicit animation, no tracking of time or state of any kind, and in fact essentially no javascript to speak of other than updating the properties.

\$\endgroup\$
  • \$\begingroup\$ Well is there a way to do it instead of using the -webkit-transition: 1s all; -moz-transition: 1s all; things? \$\endgroup\$ – Geroy290 Jun 1 '14 at 18:49
  • \$\begingroup\$ it's much faster to just do it than to keep looking for other ways to do it \$\endgroup\$ – John Haugeland Jun 2 '14 at 3:33
  • \$\begingroup\$ @MickLH I don't understand how it moves though! Like is it down up left right and how do I change/customize it? \$\endgroup\$ – Geroy290 Jun 2 '14 at 3:53
  • \$\begingroup\$ How can I change the animation? @MickLH \$\endgroup\$ – Geroy290 Jun 2 '14 at 19:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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