Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

1 decade ago by vidja_games

Anyone have any tips or ideas to reduce the number of draws caused by displaying text on the screen? I was thinking of making a event display/chat box for my game but I fear that the draws from text would pile up over time and slow the game down. I'm thinking of some ways to do it, but I was wondering if anyone here already dealt with/experienced this issue.

1 decade ago by jswart

I would make a MessageQueue. And pair it up with a timer. As messages are generated by the game I would add them to the MessageQueue.

Then I would do a check every 1 second or so, and then draw only then.

// -- main.js --
// pseudo-code

    MessageQueue = new MessageQueue(),
   
// ... 

    update: function() {
        // something happend!
        this.MessageQueue.addEvent(someEventText);
    },

    draw: function() {
        //
        if ( timer.delta == 1) {
            this.MessageQueue.displayQueue();

        }

That was way over simplified. But I would basically follow this order.

1. Add items to MessageQueue as the game generates them.
2. Attach a timer to MessageQueue
3. When the right amount of time has elapsed grab items from the MessageQueue and draw them
4. Remove those items from the MessageQueue
5. Have a timer to denote how long text should display. ( # 5 & 6 could me incorporated into the other steps)
6. When this timer passes remove text from view.
7. Repeat.

That way instead of drawing your text 60 times/second or however often you draw it once every once per second.

1 decade ago by Graphikos

If you want to keep it on the screen just render the text to an off-screen canvas and then draw that. 1 draw vs hundreds/thousands every frame. Redraw your off-screen canvas when there is new text.

1 decade ago by paulh

could you explain how to do that graphikos, its blitting, yea?

1 decade ago by jswart

Quote from paulh
could you explain how to do that graphikos, its blitting, yea?


blitting is a pretty difficult word to narrow in a definition for. Blitting seems to be more like copying parts of one bitmap to another bitmap.

Graphikos is describing something that sounds a lot more like double buffering. We draw to the canvas via the context, then we flip the offscreen canvas and in one step draw it with drawImage.

1 decade ago by Graphikos

Something like this... then when there is new chat you just call updateChat() and redraw the image.

...

updateChat: function() {
	// create a new canvas
	this.chatImage = ig.$new('canvas');
	this.chatImage.width = 500;
	this.chatImage.height = 400;

	// hijack ig.system.context so font.draw() works easily ;)
	var impactCtx = ig.system.context;  
	ig.system.context = this.chatImage.getContext('2d');

	for (var i = 0; i < messagesArray.length; i++) {
		font.draw(messagesArray[i], 20, 15*i, ig.Font.ALIGN.LEFT);
	}

	// restore context
	ig.system.context = impactCtx; 
},

draw: function() {
	this.parent();

	// draw the cached image
	ig.system.context.drawImage(this.chatImage, 50, 50);
}

(untested)

I don't know how jswart's suggestion would work. Drawing every 1 second will give you nothing because its going to get drawn over on the very next frame. Unless you aren't clearing the screen you have to draw it every frame (more about this here).

1 decade ago by tenix

There is a crude way but you could add every single message to one string and then break it apart with line breaks and this would get 1 draw for all chat messages rather than like 8-10 or so. Some people above are basically saying to add all the messages to an array and then loop through and draw each message. I think it was 1.19 or 1.20 but they added a line height so could space out line breaks.

1 decade ago by jswart

Quote from Graphikos
Something like this... then when there is new chat you just call updateChat() and redraw the image.

...

...

(untested)

I don't know how jswart's suggestion would work. Drawing every 1 second will give you nothing because its going to get drawn over on the very next frame. Unless you aren't clearing the screen you have to draw it every frame (more about this here).


Graphikos that was a really cool solution, and I definitely learned something about how ImpactJS internals worked. After reading your original post on the subject I poked around to try and figure out how it would work, and I was definitely looking in the wrong place.

That being said my solution would involve a queue of messages, a timer / switch to limit when messages could be drawn. This would incorporate a duration that the messages would be drawn. This would keep the messages from overwriting one another.

Your solution is much more interesting though, mine stems from a lack of this deeper understanding of ImpactJS. Thanks for sharing!

1 decade ago by Graphikos

My solution is more based on HTML5 rather than Impact... but its the same method Impact does things like pre-rendering a background.

@tenix, true, there are many ways you can render the text but it doesn't change the fact that each character is a draw and draws are expensive. However you do it... arrays... new lines... whatever... caching it is still a good idea.

While on the subject, you could also use quidmonkey's font plugin to do native text rendering which I'd guess to be more efficient than Impact's standard font. You can probably get away with not caching then but it has it's cons also. Mostly being it might not be consistent across platforms.

1 decade ago by jswart

Quote from Graphikos
My solution is more based on HTML5 rather than Impact... but its the same method Impact does things like pre-rendering a background.

...


That is exactly where I was looking when I was trying to come up with my own solution. Good to know I wasnt too far off base!

1 decade ago by tenix

Calling draw once versus multiple times would reduce system lag. But ya you do have to still draw them all.

1 decade ago by Graphikos

Quote from tenix
Calling draw once versus multiple times would reduce system lag. But ya you do have to still draw them all.


Well yea, there is no getting around that. It does bring up a good point though. Redrawing it will cause a spike in performance drop but you have full control when that spike happens. For example redraw it when they stop moving. This should let you optimize and minimize player perception of the performance hit.

Either way it is better than drawing everything every frame.

1 decade ago by vidja_games

Calling draw once versus multiple times would reduce system lag. But ya you do have to still draw them all.


If i have the old draw, I should be able just add the new stuff onto the old stuff without having to redraw all the old stuff.

1 decade ago by Graphikos

Quote from vidja_games
If i have the old draw, I should be able just add the new stuff onto the old stuff without having to redraw all the old stuff.


If you are talking about the cached image, then yes... that would be true because it's not being cleared every frame. But the issue becomes that you can't resize the canvas without it being cleared. So unless you plan on making a huge canvas image to begin with you'll end up clearing it anyway.

1 decade ago by quidmonkey

You could use my Native Canvas Fonts Plugin and reduce each text string to a single draw.

1 decade ago by Graphikos

That's been covered already quidmonkey. ;)

Quote from Graphikos
While on the subject, you could also use quidmonkey's font plugin to do native text rendering which I'd guess to be more efficient than Impact's standard font. You can probably get away with not caching then but it has it's cons also. Mostly being it might not be consistent across platforms.

1 decade ago by quidmonkey

trout slaps self
Page 1 of 1
« first « previous next › last »