How to force redraw a frame
krumza

Let's imagine that we have launched a single-player game, if the user switches another browser tab, and then returns to the tab with the game then he will see exactly the same picture as was at the time when he left the tab. because requestAnimationFrame will not refresh the canvas if the tab is closed.

And now if you imagine a multiplayer game-this situation will be terrible!

Even if it is not a PvP game, but simply showing the movement of another player.

Or for example , it is a space simulator and the player's ship flies in space - it must fly, even if the tab is closed, and not immediately draw the jump the entire animation at the time of activating the tab.

I assume that here you can use sockets from the server and for example once a second run on the client wade function.forceRedraw - but the question is-will the frame be redrawn if the tab is not active?

All 12 Comments
Gio

Hi

I know what you mean, and we cannot really force a browser to execute requestAnimationFrame on background tabs - by design, like you said most browsers will try to save power when idle, and will stop requestAnimationFrame from triggering in the background.

However setTimeout and setInterval will work even on background tabs, although with a reduced frequency. I cannot find a reference to it now, but I remember reading that they must be executed at least once per second.

So if you use setTimeout or setInterval, or you have your own events triggered by websocket messages and whatnot, then you can call wade.draw() which will immediately draw your scene, even in a background tab.

Note that this is different to wade.forceRedraw() which simply tells wade to ignore any quad-tree based optimizations and do a full redraw (for a single layer or for the whole scene) the next time the scene is renderered - and that does not happen while the tab is not active.

krumza

How make only force draw with  wade.draw () from server?

I.e. How disable wade update loop and change it to wade.draw () ?

Gio

I'm not sure I understand correctly, but you want to stop the main update loop, and manually call wade.draw once in a while?

If so, you should be able to just call wade.stopSimulation().

krumza

Gio, i use gameloop constructor on server.

and simple send

	this.update = function(delta) {
		var arr = this.entityes;
		arr.forEach(function(item, i, arr) {
			item.entity.update(delta);
		});
		io.emit("frame", arr);
	},

array of all entityes,

than on client-side i use :

wade.app.entityes = {};
...
	    
socket.on('frame',function(data){
	for(let i=0;i<data.length;i++){
	   let obj = wade.app.entityes[data[i].userid];
	   let entity = data[i].entity;
	   if(obj) {
	     obj.setPosition(entity.x,entity.y);
	   }	    		
	}
	wade.draw();
})

but it not so smooth decision.

how add smooth to movements?

Gio

I don't see why you would want to stop the update loop to do that. To me it makes more sense to update the positions when you get a message from the server, and let wade do its normal drawing and update thing. Also wade doesn't draw anything if it doesn't need to... if you have a static scene, with no moving objects (no animations, no time-dependent shaders, etc), then it doesn't draw anything - it just keeps displaying the previous frame. It only draws when something's moved / changed on the screen.

Instead of calling setPosition, I would set the objects on a Path, i.e. create a path from their current position to the next position and use obj.setPath. If you only need linear movement (no tweening), then obj.moveTo would also work and is simpler.

 

krumza

Can you show how use path and moveto in this case?

I calculate on server rotation and position,

then send array of this data to clients 60 times per second

 

krumza
	    socket.on('frame',function(data){
	    	for(let i=0;i<data.length;i++){
	    		let obj = wade.app.entityes[data[i].userid];
	    		let entity = data[i].entity;
	    		if(obj) {
	    			//obj.setPosition(entity.x,entity.y);
	    			obj.moveTo(entity.x,entity.y,entity.speed);
	    		}	    		
	    	}
	    	//wade.draw();
	    })

some like this??

Gio

That's what I was going to write, you beat me to it :)

The main thing is, you can try to send data 60 times per second, but there is no way to know that it will be received 60 times per second. Network lag, slow client machines, and many more factors can affect that. I think it's better to send a target position (where the object is moving to) and let the client do the interpolation, it's going to look smoother.

Of course sometimes you don't know where the object is moving to, but you can try to predict that based on the current velocity, player input, etc. You could still send an estimated target position, and then correct it later if it's wrong.

With a path, you can handle position and rotation at once:

var pos = obj.getPosition();
var rot = obj.getRotation();
obj.setPath(new Path([
    {
        speed: entity.speed,
        position: pos,
        rotation: rot
    },
    {
        position: {entity.x, entity.y},
        rotation: entity.rotation
    }
]));

 

krumza

Gio - method 

obj.setPosition(entity.x,entity.y);

seems better than all

Path twitching. I send from server delta time for position state snapshot

and add to path  -

duration: data.delta/1000, (in my case 20 ms)

But all variants swithing. What the best way for smooth move?

krumza

there is problem that i try make it in 2 instance - in local with ping 1-4ms

and in server - ping - >100ms/

in local better variant with often update, on the server - better moveTo - how find gold between this variants?

and gio? how solve problem with multiple sprites - there is a ships with guns -guns look to the mouse, but if a set object  rotation - guns on the 1ms look forward and then lool on mouse - this look ugly

Gio

Hey krumza

Could you explain what you mean by this "guns look to the mouse, but if a set object  rotation - guns on the 1ms look forward and then lool on mouse".

I'd like to help but I didn't quite understand what the problem is there.

krumza

i mean ship guns rotation follow to  mouse position

here  example 

Post a reply
Add Attachment
Submit Reply
Login to Reply