how to make brush transparent?

Discuss any general programming issues here
Post Reply
Bugala
Posts: 1178
Joined: Sun Feb 14, 2010 7:11 pm

how to make brush transparent?

Post by Bugala »

After trying for a while already i decided it might be easier to ask from hee, especially since im not sure if im even trying to do it at right place on code.

I am simply trying to make a talk box. At game you do something and then the character talks. For this to happen, it opens up a box on top of players head and prints text inside the box.

Otherwise i have done that and its working fine, but i am hoping to get that box transparent, so the background would show behind it a bit.

My current system is that i have first used CreateBrush() to create the box, and then put it on screen as a layer.

After that i have just simply printed text on the box.


I tried while creating that layer or brush, forgot which one, setting its color with that ARGB(64, $777777) but it didint work.

It obviosuly is doing some sort of transparency, since when i keep changing that 64 number to different, also the color of my box changes from lighter to darker gray, but its not working so that it would show background behind it.

Anyone able to help me?
PEB
Posts: 567
Joined: Sun Feb 21, 2010 1:28 am

Re: how to make brush transparent?

Post by PEB »

You can either use a mask or an alpha-channel to do what you want.

Check out the documentation for SetBrushTransparency() and SelectAlphaChannel().
jalih
Posts: 276
Joined: Fri Jun 18, 2010 8:08 pm
Location: Finland

Re: how to make brush transparent?

Post by jalih »

Hi,

Steps are something like:

- Open alpha channel of the brush with: SelectAlphaChannel()
- Make brush fully transparent with: SetAlphaIntensity(0) and Cls
- Then set the desired transparency level with SetAlphaIntensity() (255 is fully opaque)
- Draw to alpha channel
- EndSelect

Simple example with fake light using alpha channel is below, change the png picture of brush 4 to something of your own:

Code: Select all

@VERSION 2,0    /* Hollywood 2.0 strictly required */

/*
** External data
*/

@BRUSH 4, "hertta.png"

@DISPLAY {Borderless = True, DragRegion = {{X = 0, Y = 0, Width = 800, Height = 600}}, Width = 800, Height = 600}

Function p_MainLoop()
	Local mx = MouseX()
	Local my = MouseY()
	
	SelectAlphaChannel(10)
	SetAlphaIntensity(255)
	Cls
	SetAlphaIntensity(0)
	Circle(mx-250, my-250, 250)
	EndSelect

	DisplayBrush(4, #CENTER, #CENTER)
	DisplayBrush(10, #CENTER, #CENTER)	
	
	DisplayBrush(5, mx - 250 , my - 250)
	
	Flip
	
EndFunction



r! = 0.0
rd! = 10.0

s! = 1.0
sd! = 0.1


SetFillStyle(#FILLCOLOR)
CreateBrush(3, 100, 100)
SelectBrush(3)
Circle(0, 0, 50, #WHITE)
EndSelect

SelectAlphaChannel(3)
SetAlphaIntensity(0)
Cls

i = 0

For k = 51 To 1 Step -1
	Circle(#CENTER, #CENTER, k)
	SetAlphaIntensity(i)
	i = i + 5
Next

EndSelect

CopyBrush(3, 5)
ScaleBrush(5, 500, 500, True) 

CreateBrush(10, 800, 600)

/* LeftMouseQuit(True) */
EscapeQuit(True)

SetInterval(1, p_MainLoop, 1000/25) ; 25fps

BeginDoubleBuffer


Repeat
	WaitEvent
Forever
Bugala
Posts: 1178
Joined: Sun Feb 14, 2010 7:11 pm

Re: how to make brush transparent?

Post by Bugala »

Thanks a dozen, that SetBrushTransparency() function fixed my problem real quick with one line only.

And although i didnt use it, since that SetBrushTransparency() already fixed my problem, thanks from such a long piece of example code you made for me Jalih!
jalih
Posts: 276
Joined: Fri Jun 18, 2010 8:08 pm
Location: Finland

Re: how to make brush transparent?

Post by jalih »

Bugala wrote:Thanks a dozen, that SetBrushTransparency() function fixed my problem real quick with one line only.
But sometimes you need more control over brush transparency, and then drawing directly to alpha channel of the brush with different alpha intensity values is the best way to go.

For an example say you have a game, where you control a little rotating space ship and can shoot some baddies. To make it look a little more interesting, you want some gradually fading flames coming out from the back of space ship when thrusting.

Here is the game (replace graphics with your own):

Code: Select all

@APPICON {Ic16x16 = "my16x16icon.png",
	   Ic24x24 = "my24x24icon.png",
	   Ic32x32 = "my32x32icon.png",
	   Ic48x48 = "my48x48icon.png",
	   Ic128x128 = "my128x128icon.png",
	   Ic256x256 = "my256x256icon.png",
	   Ic512x512 = "my512x512icon.png"}


@SCREEN {Mode = "Windowed"}

@VERSION 2,0    /* Hollywood 2.0 strictly required */

/*
** External data
*/

@BRUSH 2, "ship.png", {LoadAlpha =  True}
@BRUSH 4, "flame.png", {LoadAlpha =  True}
@BRUSH 6, "shot.png", {LoadAlpha =  True}
@BRUSH 7, "enemy.png", {LoadAlpha =  True}

@ANIM 1, "explosion.png", {LoadAlpha = True, X = 0, Y = 0, Width = 64, Height = 64, Frames = 6, FPR = 1 }

@DISPLAY {Width = 800, Height = 600, Title = "SpaceMines"}




player = {}
player.x! = (800 - 64)/2
player.y! = (600 - 64)/2
player.angle = 0
player.speed! = 0


Function player:move(xs!, ys!)

	self.x! = self.x! + xs!
	self.y! = self.y! + ys!
	
	Local ix = Int(self.x!)
	Local fx = Frac(self.x!)
	Local iy = Int(self.y!)
	Local fy = Frac(self.y!)
		
	self.x! = (ix + 800) % 800 + fx
	self.y! = (iy + 600) % 600 + fy

EndFunction



Function player:draw()
	
	Local w = GetAttribute(#BRUSH,3,#ATTRWIDTH)
	Local h = GetAttribute(#BRUSH,3,#ATTRHEIGHT)
	
	DisplayBrush(3, self.x! - w/2, self.y! - h/2)

EndFunction



Function player:rotate(angle)

	CopyBrush(2,3)
	RotateBrush(3, angle)	
	
EndFunction




flames = { flames = {} }


Function flames:add(x, y, scale, alpha)
	
	Local flame = { x = x, y = y, scale = scale, alpha = alpha }
	InsertItem(self.flames, flame)
	
EndFunction



Function flames:del(pos)

	RemoveItem(self.flames, pos)
		
EndFunction



Function flames:animate()
	
	Local a, b = NextItem(self.flames)
	While GetType(a) <> #NIL
		b.alpha = b.alpha - 3.75
		If b.alpha < 0
			self:del(a)
		EndIf
		
		b.scale = b.scale + 0.05
		If b.scale > 2
			b.scale = 2
		EndIf
					
		a, b = NextItem(self.flames, a)
	Wend

EndFunction




Function flames:draw()

	Local a, b = NextItem(self.flames)
	While GetType(a) <> #NIL							
		CopyBrush(4, 5)
		SelectAlphaChannel(5)
		SetAlphaIntensity(0)
		Cls
		SetAlphaIntensity(b.alpha)
		DisplayBrush(4, #CENTER, #CENTER)
		EndSelect
		ScaleBrush(5, 64 * b.scale, 64 * b.scale)
		DisplayBrush(5, #CENTER - 400 + b.x, #CENTER - 300 + b.y)
			
		a, b = NextItem(self.flames, a)
	Wend

EndFunction




explosions = { explosions = {} }


Function explosions:add(x, y)
	
	Local explosion = { x = x, y = y, frame = 1 }
	InsertItem(self.explosions, explosion)
	
EndFunction



Function explosions:del(pos)

	RemoveItem(self.explosions, pos)
		
EndFunction



Function explosions:animate()
	
	Local time = GetTimer(2)
	If time > 50
	
		Local a, b = NextItem(self.explosions)
		While GetType(a) <> #NIL
			b.frame = b.frame + 1
			If b.frame >= 7
				self:del(a)
			EndIf
	
					
			a, b = NextItem(self.explosions, a)		
		Wend
	
		ResetTimer(2)
	EndIf

EndFunction




Function explosions:draw()
	
	Local framesy = { 63, 127, 191, 255, 319, 383, 447 }  

	Local a, b = NextItem(self.explosions)
	While GetType(a) <> #NIL
									
		DisplayAnimFrame(1, #CENTER - 400 + b.x, #CENTER - 300 + b.y, b.frame)
			
		a, b = NextItem(self.explosions, a)
	Wend

EndFunction






shots = { shots = {}}

Function shots:add(x, y, xs, ys)
	
	Local shot = { x = x, y = y, xs = xs, ys = ys }
	InsertItem(self.shots, shot)
	
EndFunction



Function shots:del(pos)

	RemoveItem(self.shots, pos)
		
EndFunction



Function shots:move()
	
	Local a, b = NextItem(self.shots)
	While GetType(a) <> #NIL
		b.x = b.x + b.xs
		b.y = b.y + b.ys
		If b.x < 0
			self:del(a)
		ElseIf b.x > 800
			self:del(a)
		EndIf
			
		If b.y < 0
			self:del(a)
		ElseIf b.y > 600
			self:del(a)		
		EndIf
					
		a, b = NextItem(self.shots, a)
	Wend

EndFunction



Function shots:draw()
	
	Local a, b = NextItem(self.shots)
	While GetType(a) <> #NIL
		DisplayBrush(6, #CENTER - 400 + b.x, #CENTER - 300 + b.y )			
		a, b = NextItem(self.shots, a)
	Wend

EndFunction



Function shots:collision()
	
	Local w1 = GetAttribute(#BRUSH,6,#ATTRWIDTH)
	Local h1 = GetAttribute(#BRUSH,6,#ATTRHEIGHT)
	Local w2 = GetAttribute(#BRUSH,7,#ATTRWIDTH)
	Local h2 = GetAttribute(#BRUSH,7,#ATTRHEIGHT)
	Local k, c
	
	Local a, b = NextItem(self.shots)
	While GetType(a) <> #NIL
		c = ListItems(baddies.baddies)
		
		For k = 0 To c-1
			If Collision(#BRUSH, 6, b.x - w1/2, b.y - h1/2, 7, baddies.baddies[k].x - w2/2, baddies.baddies[k].y - h2/2)
				explosions:add(b.x, b.y)
				shots:del(a)
				baddies:del(k)
				points = points + 1
				Break
			EndIf
			
		Next
					
		a, b = NextItem(self.shots, a)
	Wend

EndFunction


starfield = { SP = {}, XS = {}, YS = {}, CL = {} }


Function starfield:init()

	Local k

	For k = 0 To 9
		self.XS[k] = Rnd(800)
		self.YS[k] = Rnd(600)
		self.SP[k] = 0.5
		self.CL[k] = $888888
	Next

	For k = 10 To 20
		self.XS[k] = Rnd(800)
		self.YS[k] = Rnd(600)
		self.SP[k] = 1
		self.CL[k] = $888888
	Next

	For k = 21 To 30
		self.XS[k] = Rnd(800)
		self.YS[k] = Rnd(600)
		self.SP[k] = 1.5
		self.CL[k] = $888888
	Next

	For k = 31 To 40
		self.XS[k] = Rnd(800)
		self.YS[k] = Rnd(600)
		self.SP[k] = 2
		self.CL[k] = $DDDDDD
	Next

	For k = 41 To 50
		self.XS[k] = Rnd(800)
		self.YS[k] = Rnd(600)
		self.SP[k] = 2.5
		self.CL[k] = $DDDDDD
	Next

	For k = 51 To 60
		self.XS[k] = Rnd(800)
		self.YS[k] = Rnd(600)
		self.SP[k] = 3
		self.CL[k] = $DDDDDD
	Next

EndFunction



Function starfield:draw()
	
	For Local k = 0 To 60
		Plot(self.XS[k], self.YS[k], self.CL[k])
		self.XS[k] = self.XS[k] + self.SP[k]
		If self.XS[k] > 800 Then self.XS[k] = 0
	Next

EndFunction




baddies = { baddies = {} }

Function baddies:init()
	
	
	For Local k = 0 To 4
		Local badguy = {}
		badguy.x = Rnd(800)
		badguy.y = 0
		badguy.xs = (Rnd(6) + 1) / 4
		badguy.ys = (Rnd(6) + 1) / 4
		InsertItem(self.baddies, badguy)		 
	Next
	
	For k = 0 To 4
		badguy = {}
		badguy.x = Rnd(800)
		badguy.y = 600
		badguy.xs = -(Rnd(6) + 1) / 4 
		badguy.ys = -(Rnd(6) + 1) / 4
		InsertItem(self.baddies, badguy)		 
	Next


EndFunction


Function baddies:del(pos)

	RemoveItem(self.baddies, pos)
		
EndFunction



Function baddies:move()
	
	Local ix, fx, iy, fy
	
	Local a, b = NextItem(self.baddies)
	While GetType(a) <> #NIL
		b.x = b.x + b.xs
		b.y = b.y + b.ys
		
		ix = Int(b.x)
		fx = Frac(b.x)
		iy = Int(b.y)
		fy = Frac(b.y)
		
		b.x = (ix + 800) % 800 + fx
		b.y = (iy + 600) % 600 + fy		
					
		a, b = NextItem(self.baddies, a)
	Wend

EndFunction



Function baddies:draw()
	
	Local a, b = NextItem(self.baddies)
	While GetType(a) <> #NIL
		DisplayBrush(7, #CENTER - 400 + b.x, #CENTER - 300 + b.y )			
		a, b = NextItem(self.baddies, a)
	Wend

EndFunction



Function baddies:collision()
	
	Local w1 = GetAttribute(#BRUSH,7,#ATTRWIDTH)
	Local h1 = GetAttribute(#BRUSH,7,#ATTRHEIGHT)
	Local w2 = GetAttribute(#BRUSH,3,#ATTRWIDTH)
	Local h2 = GetAttribute(#BRUSH,3,#ATTRHEIGHT)
	Local k, c
	
	Local a, b = NextItem(self.baddies)
	While GetType(a) <> #NIL
			
		If Collision(#BRUSH, 7, b.x - w1/2, b.y - h1/2, 3, player.x! - w2/2, player.y! - h2/2)
			explosions:add(b.x, b.y)
			baddies:del(a)							
			Break
		EndIf
					
		a, b = NextItem(self.baddies, a)
	Wend

EndFunction



Function p_MainLoop()
	
	If IsKeyDown("LEFT")	
		player.angle = (player.angle + 360) % 360 + 4
	ElseIf	IsKeyDown("RIGHT")
		player.angle = (player.angle + 360) % 360 - 4
	EndIf
	
		
	Local xd! = costable[player.angle + 90]
	Local yd! = sintable[player.angle - 90]
	Local xs! = xd! * player.speed!
	Local ys! = yd! * player.speed!
	
	If IsKeyDown("UP")
		player.speed! = player.speed! + 0.35
		If player.speed! > 4
			player.speed! = 4
		EndIf
		
		If Rnd(100) > (100 - player.speed! * 2.5)
			flames:add(player.x! - 40 *xd!, player.y! - 40 * yd!, 0.5, 128) 
		EndIf							
					
	Else
		player.speed! = player.speed! - 0.25
		If player.speed! < 0
			player.speed! = 0
		EndIf
	EndIf
	
	If IsKeyDown("LCONTROL")
		Local time = GetTimer(1)
		If time > 500
			shots:add(player.x! + 32 * xd!, player.y! + 32 * yd!, 20 *xd!, 20 * yd!)
			ResetTimer(1)
		EndIf
		
	EndIf


	DisplayBrush(1, #CENTER, #CENTER)
	
	player:move(xs!, ys!)
	player:rotate(player.angle)
	baddies:move()	
	shots:move()
	shots:collision()

	baddies:collision()
	flames:animate()					
	starfield:draw()	
	player:draw()
	baddies:draw()			 		
	flames:draw()
	explosions:draw()
	explosions:animate()
	shots:draw()
	
	TextOut(#LEFT, #TOP, AddStr(pointinfo$, points))
				
	Flip

EndFunction




sintable = {}
For i = -450 To 450 Do sintable[i] = Sin(Rad(i))

costable = {}
For i = -450 To 450 Do costable[i] = Cos(Rad(i))

points = 0
pointinfo$ = "SCORE: "

starfield:init()
baddies:init()

CreateBrush(1, 800, 600, #BLACK)
ScaleBrush(7, 45, 45, True)


EscapeQuit(True)

BeginDoubleBuffer

StartTimer(1)
StartTimer(2)

SetInterval(1, p_MainLoop, 1000/50) ; 50fps

Repeat
	WaitEvent
Forever
Post Reply