Jump to content


Photo
* * * * * 1 votes

Accelerate Draw_text


  • Please log in to reply
2 replies to this topic

#1 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 18181 posts
  • Version:GM:Studio

Posted 11 March 2008 - 01:52 AM

  • Title: Accelerated Draw Text
  • Description: Fast method for drawing strings that seldom change
  • GM Version: :GM6:
  • Registered: yes
  • File Type: .zip
  • File Size: 50kb
  • File Link: http://host-a.net/ic...42/fastdraw.zip
Summary

You may not realize it but drawing strings can put a lot of strain on the game, especially if you draw a lot of them or draw a long one.

This tutorial/example shows how to make the drawing of strings more efficient for your game…

gm8+ fix line
global._textspr[ident] = sprite_create_from_surface (surf2,0,0,w,h,1,0,xs,ys);



The example also fixes a problem that has been bugging some of us for a while… The dreaded cleartype in windows Vista.

Cleartype blurs the font to make it more readable. A useful feature for laptops and LCD screens, but it works taking into account the background color onto which it is drawn. There is a problem with this in GM though, it does not always use the right background color of the game if the back of the font has multiple colors. The effect is often unreadable text…


OK, first, to accelerate the draw text…

The method is simple

If the text has never been drawn before, create a sprite version of the text by drawing it to a surface and creating a sprite from the surface.
If it has been drawn before, simply draw the sprite.
<Added> If it has failed to create sprite, default to draw text and never try again

The very first call is slower than a regular draw_text because of the overhead but the next calls are very fast.

The sprite index is stored into an array, who’s index is specified by the programmer.

FastDrawText(x,y,”Hello”,1); where 1 is the array index to stuff the sprite into (1 is NOT a sprite index, it is the array index the sprite index is stored into).
NOTE: the actual implementation differs, here, I simplified the parameters and code for introduction purpose…
Actual implementation:
FastDrawText (x, y, string, font (-1 for default), identifierforquickdraw, color,alpha, halign, valign);


The array is initialised using InitFastDrawText(20), where 20 is the number of fast draw text you will create in the game.

So
On Game Start
InitFastDrawText(20);

On a draw
FastDrawText(x,y,”Hello”,1)

On another draw
FastDrawText(x,y,”How are you?”, 2)

When the game end, optionally you free the system
FreeFastDrawText(20)
You may also free the system when you want to update the strings with new values.

The logic for the init array

Repeat(numberofitems)
Set array[n] to -1

The logic to free array
Repeat(numberofitems)
If the sprite of array[n] exist, free it, set array to -1


The logic for the fast draw text

If array[index] has a sprite, draw the sprite, exit
Otherwise, if array indicates to not retry, draw the text, exit
Otherwise
Get the text width and height
Create surface using width and height, clear it.
Draw the text to the surface
Create the sprite from the surface
Free the surface
Set array[index] to new sprite
or set array to failure if fail so not to retry
Draw the sprite.


For cleartype fixing, you create a second surface and draw from the first surface in such a way to neutralize the cleartype effect and create the sprite from that surface.

Note: Before compiling your exe, disable your system's font smoothing (cleartype) and you wont have to do this as long as you use a font you added in the gm project

Other things the script handles is font to use (-1 for default), text color, alpha setting and font alignment which at this point you can figure from the code.

Usually, you set the color for the text to draw… But in this case the actual sprite is created in black and white… The color is added when the sprite is drawn.

Same deal with the alpha, the sprite text has an alpha of 1, the alpha is added when the sprite is drawn.

For the font alignment, depending on what is used (left, right, center, top, bottom, middle), the sprite’s origin is simply set up to emulate the feature when the sprite will be drawn…

Limitations:
You cannot change the text once the sprite is set. (Free the system to make it regenerate the sprites)
You cannot change the alignment once the sprite is set. (Free the system to make it regenerate the sprites)
You cannot change the font once the sprite is set. (Free the system to make it regenerate the sprites)

You should not abuse the free though… Better have 5 copies of similar text than freeing everything up every time a string changes. You can always modify the FastDraw script to receive a update flag where you can use_sprite_replace to update the sprite instead of adding a new one… Again, if your text changes every step though, DO NOT use this method.

Once the text sprite is created, you can change the x, y coordinates and alpha and the color for each draw.

Recommended use:
You may pre-call the function with all your text when the game starts so not to ever slow down the draw event with the sprite creation overhead.

You must pre-call the function if you use it in a redirected draw. (surface_set_target)

I added the "if failed once, don't retry" to make sure not to break the draw event if the PC does not support (or failed) creating surfaces.

If you use "Interpolate color between pixels" option, you should see if turning it OFF in code before creating the sprite and turning it back on after it's done improves the text readability...

//game start
//I'm using interpolation, so turn it off
texture_set_interpolation(false);
//allocate
InitFastDrawText(100)
//pre-create
FastDrawText (x,y,"Hello1",-1,1,c_blue,1,fa_left,fa_top);
FastDrawText (x,y,"Hello2",-1,2,c_blue,1,fa_left,fa_top);
FastDrawText (x,y,"Hello3",-1,3,c_blue,1,fa_left,fa_top);
FastDrawText (x,y,"Hello4",-1,4,c_blue,1,fa_left,fa_top);
FastDrawText (x,y,"Hello5",-1,5,c_blue,1,fa_left,fa_top);
FastDrawText (x,y,"Hello6",-1,6,c_blue,1,fa_left,fa_top);
FastDrawText (x,y,"Hello7",-1,7,c_blue,1,fa_left,fa_top);
FastDrawText (x,y,"Hello8",-1,8,c_blue,1,fa_left,fa_top);
//Turn interpolation back ON
texture_set_interpolation(true);

//on draw
FastDrawText (x,y,"Hello1",-1,1,c_blue,1,fa_left,fa_top);
//or even
FastDrawText (x,y,"",-1,1,c_blue,1,fa_left,fa_top);

As you may get double interpolation... Once when it makes the sprite, and a second time when it actually draws on screen

Enjoy!

Edited by icuurd12b42, 22 September 2011 - 04:57 AM.

  • 0

gmcbanner.pnggmcbanner_tools.png

ICU Live Tutoring Through Slack or Skype | My Tools Page follow.png

I FRANTICALLY MADE MY 18000 POST TOPIC BEFORE MIKE ANNOUNCED A DELAY...
Now I'm squirming not to hit that reply button


#2 jsorgeagames

jsorgeagames

    GMC Member

  • GMC Member
  • 710 posts
  • Version:GM:Studio

Posted 24 February 2009 - 04:01 AM

Another way of solving cleartype, (I believe it is included in Windows XP SP3, because my laptop seems to have it, and I have XP), at least on my computer, is to round the x and y values, because drawing text at 53.5 x and 22.1 y, for example, will cause problems and the text will become unreadable.
  • 0

#3 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 18181 posts
  • Version:GM:Studio

Posted 22 July 2011 - 08:41 PM

Std Msg: Please use the tutorial template header (The Tutorial Clean Up Crew).
  • 0

gmcbanner.pnggmcbanner_tools.png

ICU Live Tutoring Through Slack or Skype | My Tools Page follow.png

I FRANTICALLY MADE MY 18000 POST TOPIC BEFORE MIKE ANNOUNCED A DELAY...
Now I'm squirming not to hit that reply button