Thick outlines for sprite

BlitzMax Forums/BlitzMax Programming/Thick outlines for sprite

FantomKite(Posted 2009) [#1]
Hi to all!
I want to make an outline to some sprite. But it must be something like this: black sprite with alpha channel close to 0.2 ("shadow") and red outline. I want to make it without additional drawing, just using bmax, i know it's possible. Any advices?

Thanks.


ima747(Posted 2009) [#2]
assuming I'm reading you correctly, you want a sprite, with an outline, and a drop shadow effect.

Here's how I would do it.

set alpha to whatever value you want for the shadow (0.2) and set the color you want for the shadow (probably black). then either use SetScale to set the drawing scale up because you want to shadow the border as well (this will make sense in a sec) or use drawimagerect and calculate the size the rect should be for scaling up. draw the sprite as the shadow with it's location offset from where the sprite is (i.e. spritex+10, spritey+10) to give the impression of depth

next, set alpha back to 1, set the color you want for the border. if you drew with setscale you don't need to change it, otherwise use the same scale calculation for drawimagerect and draw the sprite as the border using a negative offset so the border shows on the top and left (i.e. spritex-2, spritey-2)

set the color back to what you want the sprite to be. if you used setscale then set it back to 1x1 now, draw the sprite at it's proper location.


what happens is you draw the shadow in a shifted location to give the impression of depth, and scale it up to take into account the border on the sprite. then draw the border shifted so it sticks out around the sprite on all sides. then draw the sprite where it belongs.

a tip to make life easier: use SetImageHandle or AutoMidHandle to set the draw point of the sprite to the middle. if you're drawing from the middle instead of the top/left corner you won't need to offset the border, and it's easier to offset the shadow because you don't have to take the border into account any more. this will work especially well with setscale instead of drawimagerect.

if you're drawing drop shadows you should optimally draw all your shadows before any sprites since a shadow should (assuming a 2d world) never be on top of a sprite if everything is "floating" at the same height.

if you want to get really anal about perspectives the shadow should be scaled slightly more than the border to give the impression it's blocking the theoretical light source, but if you're going to get that anal you would probably want blurred edges on your shadows and for that you're best off making the shadows as seperate pictures instead of just recycling the sprite itself. more memory, more drawing, not usually worth it imo.

Hope that helps.


MGE(Posted 2009) [#3]
I did the same, but it's a performance hit. If no scaling is needed it's faster to pre-render the shadow and draw it under the sprite.


Nate the Great(Posted 2009) [#4]
just have a sprite and a sprite shadow image that can be slightly bigger and blurred around the edges. then draw all the shadow images first followed by the sprites. This will save time as well as achieving the blurry scaled shadow image effect.

sorry I couldnt quite understand what you were asking though.


GW(Posted 2009) [#5]
The fastest method for me was just set the color to black and draw the image offset by 1 in all directions and then draw your colored image on top.


FantomKite(Posted 2009) [#6]
Thanks guys, but that is not what i wanted. Yes, a bit hard to explain, sorry for it. So, i'll try again. I have a sprite, that represents an item. And i need to show some kind of slot in game area. That slot looks exactly like my sprite, but it is totally black and transparent. So, we have only black transparent shape of an item. That was the easy part. Next, i need a thick red non-transparent outline around this slot.
Hope that it's more understandable this time :)
Sorry for my english.
Thanks!


Bremer(Posted 2009) [#7]
Perhaps post an image showing how the end result is expected to look like, then it might be a lot easier to understand and provide someone with ideas about how to get there.


Retimer(Posted 2009) [#8]
Having it transparent within the border, but a non transparent red border around it...is there actually an efficient way to do that, other then just having a second image for that?


Tommo(Posted 2009) [#9]
Maybe you are asking for something like this?


Function drawOutLine:TPixmap(source:TPixmap, k:Int = 2)
	Local w:Int, h:Int
	w = source.width
	h = source.height
	
	Local target:TPixmap = CreatePixmap(w, h, PF_RGBA8888)
	Local solidred = $ffff0000
	
	
	For Local x:Int = k Until w - k
		For Local y:Int = k Until h - k
			Local a:Byte = source.ReadPixel(x, y) Shr 24 & $ff
			If a < 10 Then Continue
			
			For Local i:Int = -k To k
				For Local j:Int = -k To k
					target.WritePixel(x + i, y + j, solidred)
				Next
			Next
			
		Next
	Next
	Local alpha2:Int = Byte(0.2 * 255) Shl 24
	
	For Local x:Int = 1 Until w - 1
		For Local y:Int = 1 Until h - 1
			
			Local a:Byte = source.ReadPixel(x, y) Shr 24 & $ff
			If a < 10 Then Continue
			target.WritePixel(x, y, alpha2)
			
		Next
	Next
	
	Return target
End Function



FantomKite(Posted 2009) [#10]
Yes, Tommo, thanks a lot!!!