Jump to content

Sprite movement speed changes depending on device performance


forleafe
 Share

Recommended Posts

Obviously this isn't optimal. Was wondering if maybe I'm doing something wrong? I have a standard game loop that's managed by requestAnimationFrame(gameLoop);

and within my gameloop I have a function that moves each enemy like so: enemy.position.y += 6

 

I don't really know what to do to keep my movement speed from varying so dramatically across different devices. 

Another issue that might be related, over time my sprite movement becomes gradually faster and choppier. This is the part that really really bothers me.

Any help or insight would be deeply appreciated.

Link to comment
Share on other sites

The easier way is to create an Application and use its ticker, like in this Pixi Example. It rotates the sprite but the same concept applies to moving it:

enemy.position.y += delta * 6;

 

Or you can do it like this for example using requestAnimationFrame (enemy.velocity.y is in pixels per millisecond in this example):

var lastTime = 0;
requestAnimationFrame(update);
function update(time) {
    var deltaTime = 0;
    if (lastTime) {
        deltaTime = time - lastTime;
    }
    lastTime = time;

    enemy.position.y += deltaTime * enemy.velocity.y;

    renderer.render(stage);
    requestAnimationFrame(update);
}
Link to comment
Share on other sites

13 minutes ago, Jinz said:

The easier way is to create an Application and use its ticker, like in this Pixi Example. It rotates the sprite but the same concept applies to moving it:


enemy.position.y += delta * 6;

 

Or you can do it like this for example using requestAnimationFrame (enemy.velocity.y is in pixels per millisecond in this example):


var lastTime = 0;
requestAnimationFrame(update);
function update(time) {
    var deltaTime = 0;
    if (lastTime) {
        deltaTime = time - lastTime;
    }
    lastTime = time;

    enemy.position.y += deltaTime * enemy.velocity.y;

    renderer.render(stage);
    requestAnimationFrame(update);
}

Okay, I'm kind of getting this. But what exactly is "time" I don't see it defined anywhere? It's just first just passed into your update function. Another thing I'm not quite understanding is your conditional. if(lastTime)  ... If lastTime what? It's declared as number, 0. How can a number ever evaluate to "true"?

I guess the general concept of this I'm missing a little bit of too.

Thanks so much for your help btw. 

Link to comment
Share on other sites

So, I'd _really_ recommend using the built in pixi stuff for this as Jinz suggested, as it'll give you all the information you need to use :), and again I'll link to the example page; please read the code, it has comments explaining exactly what you want to know: https://pixijs.github.io/examples/#/basics/basic.js

Note how it's added a function to the ticker ... this could be your function to do all your game update stuff.

Also note how it multiplies the rotation speed  by the delta. The delta here is your critical friend in helping you deal with different framerates on different devices. If your game is running at 60fps, and your target frame rate is 60fps, then the delta will be 1. So, in this case, multiplying your position change by 1 does nothing. But imagine the game is only running at half speed, 30fps. Well, the delta sent through now is 2. This is just what you need! You're function is being hit half the amount of times, so it needs to move your sprite double the amount each time.

Link to comment
Share on other sites

23 minutes ago, themoonrat said:

So, I'd _really_ recommend using the built in pixi stuff for this as Jinz suggested, as it'll give you all the information you need to use :), and again I'll link to the example page; please read the code, it has comments explaining exactly what you want to know: https://pixijs.github.io/examples/#/basics/basic.js

Note how it's added a function to the ticker ... this could be your function to do all your game update stuff.

Also note how it multiplies the rotation speed  by the delta. The delta here is your critical friend in helping you deal with different framerates on different devices. If your game is running at 60fps, and your target frame rate is 60fps, then the delta will be 1. So, in this case, multiplying your position change by 1 does nothing. But imagine the game is only running at half speed, 30fps. Well, the delta sent through now is 2. This is just what you need! You're function is being hit half the amount of times, so it needs to move your sprite double the amount each time.

Thanks for that. :)

my only question is the "delta" bit that they passed in. Does pixi automatically know what that variable is and how to keep track of it? I don't see it declared anywhere. I'm also reading this example code under the assumption that everything added to the "ticker" function will be run regularly with every cycle?

Link to comment
Share on other sites

The ticker uses requestAnimationFrame in the background. Internally, it makes a record of the last time requestAnimationFrame fired, and compares it with the latest time the requestAnimationFrame fired. It compares those 2 times, looks at your target frame rate (60fps by default) and therefore knows what the delta is. 

When you add your function to the ticker, when requestAnimationFrame comes through, the ticker does it's calculations, then calls your function, also passing through the delta as it's first parameter.

 

Link to comment
Share on other sites

On 6/2/2017 at 4:06 PM, themoonrat said:

The ticker uses requestAnimationFrame in the background. Internally, it makes a record of the last time requestAnimationFrame fired, and compares it with the latest time the requestAnimationFrame fired. It compares those 2 times, looks at your target frame rate (60fps by default) and therefore knows what the delta is. 

When you add your function to the ticker, when requestAnimationFrame comes through, the ticker does it's calculations, then calls your function, also passing through the delta as it's first parameter.

 

Maybe you could possibly help me change up my code to utilize the ticker. Having a bit of trouble getting my head around it.

so my current code works with a gameloop that loops itself using requestAnimationFrame() like so...

function gameLoop(){
  requestAnimationFrame(gameLoop);
  gameState();
  renderer.render(stage);
};

 

Other parts of my code will call the gameLoop. A few examples include a song loader that changes the gamestate to a loading screen and then calls the gameloop to display said loading screen. Another is my setup function that calls the gameloop when it's finished initializing variables.

I've looked at the pixi documentation... but I guess I don't really understand how to replicate this usage with the ticker. So far what I've done is tried formatting my code like this:

renderer.ticker.add(function(delta){
 state();
 renderer.render(stage);
});

But again, I can't really seem to call anything when I need it. The ticker just appears to run once, render my renderer, and then that's it. It doesn't do anything more.

I've tried using PIXI.ticker.Ticker.start()  but that doesn't seem to do anything either.

 

Link to comment
Share on other sites

25 minutes ago, ivan.popelyshev said:

then you dont have to add "render" method, just 

 


app.ticker.add(function(delta) {
   do_your_physics_here
});

 

I went ahead and did that. The main issue turned out to be how PIXI.Application deals with the "stage". It apparently creates one and you don't have to. So I had to add everything using

renderer.stage.addChild();

where renderer is my variable for PIXI.Application


My only other issue that you might be able to help with... since switching from autoDetectRenderer to Application. renderer.width is coming up undefined. Is there not an easy way I can just grab a number value for the width of the renderer? I have no clue why it's coming up undefined suddenly from just switching to Application like that.

Link to comment
Share on other sites

1 hour ago, forleafe said:

I went ahead and did that. The main issue turned out to be how PIXI.Application deals with the "stage". It apparently creates one and you don't have to. So I had to add everything using


renderer.stage.addChild();

where renderer is my variable for PIXI.Application


My only other issue that you might be able to help with... since switching from autoDetectRenderer to Application. renderer.width is coming up undefined. Is there not an easy way I can just grab a number value for the width of the renderer? I have no clue why it's coming up undefined suddenly from just switching to Application like that.

The renderer is property of Application. The way you have yours named, you would have to do renderer.renderer.width to get the renderer's width. But if you name it application like the examples, then you can use application.renderer.width to get the renderer's width and application.stage.addChild to add to the stage.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...