TalkBubble (working!) > How to optimize?

BlitzMax Forums/BlitzMax Programming/TalkBubble (working!) > How to optimize?

Trader3564(Posted 2008) [#1]
Greetings,

I lost myself finding a way to optimize this "TextBubble" function.
It is written for a game im working on where people can chat and have a bubble popup.
As the title says, its a fully functional script, except its kinda slow if you have to render about 100 of these.
I have NO idea what todo.

For the source + bubblemapfont download: http://www.fantasaar.com/bubble.zip

fyi, here is a direct copy of the code:
SetGraphicsDriver GLMax2DDriver()
Graphics 640,480,,,GRAPHICS_BACKBUFFER

Global BubbleMap$="!~q#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~"
Global BubbleCharW=7,BubbleCharH=10
Global BubbleLimitW=48
Global BubbleFont=LoadAnimImage("bubble.png",BubbleCharW,BubbleCharH,0,256)

While Not KeyDown(KEY_ESCAPE)
	DrawBubble("Hey! My name is LeeMing :D. ThislineisbrokenupThislineisbrokenupThislineisbrokenupThislineisbrokenupThislineisbroken\n\nupThislineisbrokenup Some random text goes here: Welcome to the official Fantasaar gameserver!",320,240)
	Flip
Wend
End

Function DrawBubble(text$,x,y)
	'Local destPixmap:TPixmap = CreatePixmap(((BubbleLimitW+1)*BubbleCharW),240,PF_RGBA8888)
	'destPixmap.Paste(BubbleFont.Lock(224,0,0), 32, 32)

	Local line$
	Local l=0
	Local newline
	'Render top
	For p=1 To BubbleLimitW+2
		If p=1 
		DrawImage(BubbleFont,((p-1)*BubbleCharW),(l*BubbleCharH),224)
		Else If p=BubbleLimitW+2
		DrawImage(BubbleFont,((p-1)*BubbleCharW),(l*BubbleCharH),226)
		Else 
		DrawImage(BubbleFont,((p-1)*BubbleCharW),(l*BubbleCharH),225)
		End If
	Next
	l:+1
	While Len(text)>0
		newline=False
		p=0
		'Line start
		DrawImage(BubbleFont,(p*BubbleCharW),(l*BubbleCharH),227)
		For p=1 To BubbleLimitW
			'on: newline?
			If Mid(text,p,2)="\n"
				line=Left(line,p)
				text=Right(text,Len(text)-(Len(line)+2))				
				p=0
				newline=True
				Exit
			Else
				'on: text
				If p < Len(text)+1
					line=line+Mid(text,p,1)
				'Finished?
				Else
					Exit
				End If
			End If
		Next
		'Always except when new line
		If newline=False
			p=line.FindLast(" ")
			If p>-1 
				line=Left(line,p)
				p=0
			End If
			text=Right(text,Len(text)-(Len(line)+1+p))
		End If
		'Render textline
		For p=1 To Len(line)
			DrawImage(BubbleFont,(p*BubbleCharW),(l*BubbleCharH),228)
			DrawImage(BubbleFont,(p*BubbleCharW),(l*BubbleCharH),Instr(BubbleMap,Mid(line,p,1)))
		Next
		'Finish tender textline (spacing)
		For i=p To BubbleLimitW
			DrawImage(BubbleFont,(i*BubbleCharW),(l*BubbleCharH),228)
		Next
		'Line stop
		DrawImage(BubbleFont,(i*BubbleCharW),(l*BubbleCharH),229)
		l:+1
		line=""
	Wend
	'Render bottom
	For p=1 To BubbleLimitW+2
		If p=1 
		DrawImage(BubbleFont,((p-1)*BubbleCharW),(l*BubbleCharH),230)
		Else If p=BubbleLimitW+2
		DrawImage(BubbleFont,((p-1)*BubbleCharW),(l*BubbleCharH),232)
		Else 
		DrawImage(BubbleFont,((p-1)*BubbleCharW),(l*BubbleCharH),231)
		End If
	Next
	'Talk arrow
	DrawImage(BubbleFont,((BubbleLimitW+1)*BubbleCharW)/2,((l+1)*BubbleCharH)-4,236)
End Function



Dreamora(Posted 2008) [#2]
With that attempt it will never become faster ... you render several images for each letter ... that means that you easily render several (ten)tousand objects each frame ... thats a clear no go ...

Implement a "lower level" system or check out the DrawImageArea / DrawImageRect functions that allow you to use 1 texture with all chars in instead of XY different ones and draw subareas of that.


Trader3564(Posted 2008) [#3]
a "lower level" system?

afaik I can only draw images using the draw command. Are you talking about pre-assembling the image before displaying?

How would that work? do i use PixMaps for that?


PantsOn(Posted 2008) [#4]
it would be a lot faster creating a single image with your bubble and text and drawing that every loop.


Dreamora(Posted 2008) [#5]
No I am talking about preassembling an image with all letters on it and use that to do a imagefont and "draw image area" commands that only draw a subarea.

This will not work with Stock Max2D commands, no mather what you do. The amount of texture rebinds is too high, you kill the graphics card by flooding it that way


Trader3564(Posted 2008) [#6]
Ye, going to OOP. Was thinking about that. Altough i must say i did not plan to have it create images every loop. I did this to notice a noticable increase in preformance, that is, when testing and trying to optimize it. I guess i will have to play arround a bit more with pixmaps... it seem that is the way to go.

Ive had some support here with a previous question, also pixmap related.
http://www.blitzbasic.com/Community/posts.php?topic=75531
Isn't there a better referance this subject with BlitzMax?


Dreamora(Posted 2008) [#7]
There is a Render2Texture module by indiepath that a user upgraded to 1.26 ... it can be found on the boards.
Pixmaps aren't fast enough for anything as you must always recreate an image from them if you intend to use blending etc.


Trader3564(Posted 2008) [#8]
i was afraid of that... hmm, il look up that function.


Dreamora(Posted 2008) [#9]
But as mentioned: a bitmap font with a single surface approach (ie 1 texture for all characters) should already speed it up seriously ...


Trader3564(Posted 2008) [#10]
Oh, i ust have not understood that correctly. How exactly do i create a bitmap font? (thanks for the help, its appreciated!)

I know how these things work in Blitz3D, but im new to BlitzMax.


Dreamora(Posted 2008) [#11]
Well in BM they work exactly the same. Just that the DrawImageRect function from B3D does not exist anymore. But users have created their own version of it. They are known as DrawImageArea or DrawImageRect2 and can be found in the code archives.


Trader3564(Posted 2008) [#12]
Neat. Thanks for the tip.


Trader3564(Posted 2008) [#13]
I got the function.... but i dont see how
Function tg_drawimagerect(image:TImage,x:Int,y:Int,xs:Int,ys:Int,width:Int,height:Int)
    DrawImage LoadImage(PixmapWindow(LockImage(image),xs,xy,width,height)),x,y
End Function

is faster than drawing images the way i did?!


Arowx(Posted 2008) [#14]
Just an idea but could you not build up a set of commonly used words and build and store them as images to reduce the number of rectangles drawn?

Or you could even build up a mapping of letter combinations e.g. 2 to 3 letters and then when you write a string containing commonly used combinations it would pick a pre-built one?

With judicious use of Maps could this be faster, over longer conversations heavy duty usage?

You could even go a step further and tokenize the common words combinations and only send those between clients?

As well as potentially being usefull for predictive text?

Wow I like this idea, now how the hell do I write a chat room?


Vlad(Posted 2008) [#15]
@LeeMing
Not
DrawImage LoadImage(PixmapWindow(LockImage(image),xs,xy,width,height)),x,y
is not right variant.

Right functions' names is "DrawImageArea" and "ccDrawImageArea". And they could be just in forum, not only in code archives.


Trader3564(Posted 2008) [#16]
I think i found one: http://www.blitzbasic.com/Community/posts.php?topic=73041#816343
(posting it for reference purpose)

-Edit-
Check this, its a great solution to my problem here: http://www.blitzbasic.com/Community/posts.php?topic=74153#828522