B3DSDK Sprite Surface V1.0

Blitz3D SDK Forums/Blitz3D SDK Programming/B3DSDK Sprite Surface V1.0

Okay, I've gotten a really cool sprite surface working. Downside? It's possible to load a sprite from an image, but the alpha channel is masked only. If you just use raw textures, alpha works beautifully. Yes, the mechanism is the same one used in the older one I found, but I've basically rewritten the whole thing from scratch to take advantage of OOP methodology, and superior BMax classes. At least, _I_ think BMax classes are better. Anyway, it's pretty cool, so enjoy! :)

Code:
Import Blitz3D.Blitz3DSDK
Import BRL.Math
Import BRL.LinkedList
Import "imagetotex.bmx"

Rem

Sprite Surface BlitzMax Blitz3D SDK Addon
by ninjarat

RCD Software (TM)

Based upon the sprite surface commands by Syntax Error and Barliesque,
but optimized heavily for BlitzMax in these ways:

 - Uses OOP to keep track of sprites in a more stuctured and easy to
   understand manner.

 - Optimized to use textures, not images.  Sorry, but I just don't
   dig the images.  Raw textures are faster, and it's easy to use them
   for variable sized images by just clipping/scaling.

End Rem

Private
	Global currhandle=0
	Function allochandle()
		currhandle:+1
		Return currhandle
	End Function
	
	Type TSprite
		Global sprites:TList
		Global sshow=True
		Global issurfaceinit=False
		Global spritepivot
		Global spritecamera
		
		Field handle
		Field mesh
		Field x#,y#
		Field ax#,ay#,az#
		Field hdlx#,hdly#
		Field sclx#,scly#
		Field angle#
		Field width
		Field height
		Field order
		Field texture
		Field u#[2],v#[2]
		Field isvisible
		Field blend=1
		Field alpha#=1
		
		Function InitSpriteSurface(pivotdist#)
			issurfaceinit=True
			
			sprites=New TList
			bbSetBuffer bbBackBuffer()
			spritecamera=bbCreateCamera()
			
			CreateSpritePivot spritecamera,pivotdist
		End Function
		
		Function CreateSprite:TSprite(width,height,texture,order,u1#,v1#,u2#,v2#)
			sprite:TSprite=New TSprite
			
			sprite.u=[u1,u2]
			sprite.v=[v1,v2]
			sprite.texture=texture
			sprite.order=order
			sprite.width=width
			sprite.height=height
			sprite.x=0
			sprite.y=0
			sprite.hdlx=0
			sprite.hdly=0
			sprite.sclx=1
			sprite.scly=1
			sprite.ax=0
			sprite.ay=0
			sprite.az=0
			sprite.handle=allochandle()
			
			smesh=bbCreateMesh(spritepivot)
			surf=bbCreateSurface(smesh)
			
			bbAddVertex surf,0,0,0,u1,v1
			bbAddVertex surf,2,0,0,u2,v1
			bbAddVertex surf,0,-2,0,u1,v2
			bbAddVertex surf,2,-2,0,u2,v2
			
			bbAddTriangle surf,0,1,2
			bbAddTriangle surf,3,2,1
			
			If texture Then bbEntityTexture smesh,texture
			bbScaleEntity smesh,Float(width)/2,Float(height)/2,1
			bbEntityFX smesh,1+16
			bbEntityOrder smesh,-order
			bbHideEntity smesh
			
			sprite.mesh=smesh
			sprite.isvisible=False
			sprite.MidHandle
			
			sprites.AddLast sprite
			
			Return sprite
		End Function
		
		Method Clone:TSprite()
			s:TSprite=CreateSprite(width,height,texture,order,u[0],v[0],u[1],v[1])
			s.blend=blend
			s.alpha=alpha
			s.SetHandle hdlx,hdly,False
			s.x=x; s.y=y
			Return s
		End Method
		
		Function UpdateSprites()
			For curr:TSprite=EachIn sprites
				curr.Update 
			Next
		End Function
		
		Method Update(frame=-99999,z#=0)
			If sshow Then
				If isvisible Then bbShowEntity(mesh) Else bbHideEntity(mesh)
			Else
				bbHideEntity mesh
			End If
			
			bbEntityBlend mesh,blend
			bbEntityAlpha mesh,alpha
			
			bbEntityOrder mesh,-order
			
			bbPositionEntity mesh,x+.5,.5-y,z
			bbScaleEntity mesh,Float(width*sclx)/2,Float(height*scly)/2,1
			bbRotateEntity mesh,0,0,angle
			
			If frame<>-99999 Then bbEntityTexture mesh,texture,frame
		End Method
		
		'(courtesy of FredBorg)
		Method SetHandle(hx#,hy#,pixpfct)
			MidHandle
			
			If pixpfct Then
				hx=(hx/width)-1
				hy=(hy/height)-1
			End If
			Local surf=bbGetSurface(mesh,1)
			bbVertexCoords surf,0,bbVertexX(surf,0)-hx,bbVertexY(surf,0)+hy,bbVertexZ(surf,0)
			bbVertexCoords surf,1,bbVertexX(surf,1)-hx,bbVertexY(surf,1)+hy,bbVertexZ(surf,1)
			bbVertexCoords surf,2,bbVertexX(surf,2)-hx,bbVertexY(surf,2)+hy,bbVertexZ(surf,2)
			bbVertexCoords surf,3,bbVertexX(surf,3)-hx,bbVertexY(surf,3)+hy,bbVertexZ(surf,3)
			
			hdlx=hx; hdly=hy
		End Method
		
		Method SetScale(sx#,sy#,pixpfct)
			If pixpfct Then
				sclx=sx/width
				scly=sy/height
			Else
				sclx=sx
				scly=sy
			End If
		End Method
		
		Method Rotate(ang#)
			angle=-ang
			If angle>180 Then angle:-360
			If angle<-180 Then angle:+360
		End Method

		Method Turn(ang#)
			angle:-ang
			If angle>180 Then angle:-360
			If angle<-180 Then angle:+360
		End Method
		
		Method GetAngle#()
			Return -angle
		End Method
		
		'(courtesy of bot builder)
		Method MidHandle()
			ux#=-100000; uy#=-100000; uz#=-100000
			lx#=100000; ly#=100000; lz#=100000
			surf=bbGetSurface(mesh,1)
			For vert=0 To 3
				vx#=bbVertexX(surf,vert)
				vy#=bbVertexY(surf,vert)
				vz#=bbVertexZ(surf,vert)
				If vx<lx Then lx=vx
				If vx>ux Then ux=vx
				If vy<ly Then ly=vy
				If vy>uy Then uy=vy
				If vz<lz Then lz=vz
				If vz>uz Then uz=vz
			Next
			ax#=(ux+lx)/2
			ay#=(uy+ly)/2
			az#=(uz+lz)/2
			bbPositionMesh mesh,-ax,-ay,-az
		End Method
		
		Method HandleX#()
			Return hdlx
		End Method

		Method HandleY#()
			Return hdly
		End Method
		
		Method PixelHandleX#()
			abshdlx#=hdlx+1
			Return abshdlx*width
		End Method

		Method PixelHandleY#()
			abshdly#=hdly+1
			Return abshdly*height
		End Method
		
		Function ShowSprites()
			sshow=True
		End Function
		
		Function HideSprites()
			sshow=False
		End Function
		
		Method SetVisible(vis)
			isvisible=vis
		End Method
		
		Method Show()
			isvisible=True
		End Method
		
		Method Hide()
			isvisible=False
		End Method
		
		Function GetCamera()
			Return spritecamera
		End Function
		
		Function CreateSpritePivot(parentcam=0,dist#=1.0)
			spritepivot=bbCreatePivot(parentcam)
			aspect#=Float(bbGraphicsHeight())/Float(bbGraphicsWidth())
			scale#=2#/bbGraphicsWidth()
			
			bbPositionEntity spritepivot,-1,aspect,dist
			bbScaleEntity spritepivot,scale,scale,scale
			bbNameEntity spritepivot,"spritepivot"
		End Function
		
		Method FreeBBObjects()
			bbFreeEntity mesh
		End Method
	End Type
Public


'get whether the sprite suface is initialized
Function IsSpriteSurfaceInit()
	Return TSprite.issurfaceinit
End Function


'initialize the sprite surface
Function InitSpriteSurface(pivotdist#=1)
	TSprite.InitSpriteSurface pivotdist
End Function


'load a sprite from a texture
Function LoadSprite:TSprite(file$,texflags=0,order=1,u1#=0,v1#=0,u2#=1,v2#=1)
	tex=bbLoadTexture(file,texflags)
	Return CreateSpriteFromTex(bbTextureWidth(tex),bbTextureHeight(tex),tex,order,u1,v1,u2,v2)
End Function


'create a new sprite with a texture
Function CreateSpriteFromTex:TSprite(width=1,height=1,texture=Null,order=1,u1#=0,v1#=0,u2#=1,v2#=1)
	Return TSprite.CreateSprite(width,height,texture,order,u1,v1,u2,v2)
End Function


'create a new sprite with an image
'note that the alpha channel can only do
'a mask blend for the time being
Function CreateSpriteFromImg:TSprite(width=1,height=1,image,order=1,u1#=0,v1#=0,u2#=1,v2#=1)
	tex=ImageToTexture(image,0,0)
	Return TSprite.CreateSprite(width,height,texture,order,u1,v1,u2,v2)
End Function


'create a duplicate of a sprite
Function CloneSprite:TSprite(sprite:TSprite)
	Return sprite.Clone()
End Function


'set visibility of sprite
Function SetSpriteVisible(sprite:TSprite,vis)
	sprite.SetVisible vis
End Function


'get visibility of sprite
Function IsSpriteVisible(sprite:TSprite)
	Return sprite.isvisible
End Function


'show the sprite
Function ShowSprite(sprite:TSprite)
	sprite.Show
End Function


'hide the sprite
Function HideSprite(sprite:TSprite)
	sprite.Hide
End Function


'set the sprite's position
Function PositionSprite(sprite:TSprite,x#,y#)
	sprite.x=x
	sprite.y=y
End Function


'rotate the sprite
Function RotateSprite(sprite:TSprite,ang#)
	sprite.Rotate ang
End Function


'turn the sprite
Function TurnSprite(sprite:TSprite,ang#)
	sprite.Turn ang
End Function


'get the sprite's width
Function SpriteWidth#(sprite:TSprite)
	Return sprite.width
End Function


'get the sprite's height
Function SpriteHeight#(sprite:TSprite)
	Return sprite.height
End Function


'get the sprite's x handle
Function SpriteHandleX#(sprite:TSprite,pixpfct=False)
	If pixfct Then
		Return sprite.PixelHandleX()
	Else
		Return sprite.HandleX()
	End If
End Function


'get the sprite's y handle
Function SpriteHandleY#(sprite:TSprite,pixpfct=False)
	If pixfct Then
		Return sprite.PixelHandleY()
	Else
		Return sprite.HandleY()
	End If
End Function


'set the sprite's order
Function SetSpriteOrder(sprite:TSprite,order)
	sprite.order=order
End Function


'set the drawing handle of the sprite
Function SetSpriteHandle(sprite:TSprite,hx#,hy#,pixpfct=False)
	sprite.SetHandle hx,hy,pixpfct
End Function


'set the sprite's scale
Function ScaleSprite(sprite:TSprite,sx#,sy#,pixpfct=False)
	sprite.SetScale sx,sy,pixpfct
End Function


'set sprite blend
Function SetSpriteBlend(sprite:TSprite,blend)
	sprite.blend=blend
End Function


'set sprite alpha
Function SetSpriteAlpha(sprite:TSprite,alpha#)
	sprite.alpha=alpha
End Function


'get sprite blend
Function SpriteBlend(sprite:TSprite)
	Return sprite.blend
End Function


'get sprite alpha
Function SpriteAlpha(sprite:TSprite)
	Return sprite.alpha
End Function


'get sprite angle
Function SpriteAngle#(sprite:TSprite)
	Return sprite.GetAngle()
End Function


'get sprite x scale
Function SpriteScaleX#(sprite:TSprite)
	Return sprite.sclx
End Function


'get sprite y scale
Function SpriteScaleY#(sprite:TSprite)
	Return sprite.scly
End Function


'update all sprites
Function UpdateSprites()
	TSprite.UpdateSprites
End Function


'get the sprite camera
Function GetSpriteCamera()
	Return TSprite.GetCamera()
End Function


'get the sprites integer handle
Function GetSpriteIntHandle(sprite:TSprite)
	Return sprite.handle
End Function


'free a sprite object
Function FreeSprite(sprite:TSprite)
	sprite.FreeBBObjects()
	sprite=Null
End Function


'use a sprite's integer handle to get the sprite
Function GetSpriteFromIntHandle:TSprite(handle)
	For ck:TSprite=EachIn TSprite.sprites
		If ck.handle=handle Then Return ck
	Next
	Return Null
End Function


'get amount of memory used by a sprite
Function SpriteMemory(sprite:TSprite)
	Return SizeOf(sprite)
End Function


'get amount of memory used by all sprites
Function AllSpritesMemory()
	For curr:TSprite=EachIn TSprite.sprites
		acc:+SizeOf(curr)
	Next
	Return acc
End Function


An import you'll need:
Import Blitz3D.Blitz3DSDK
Import BRL.Retro

Function ImageToTexture(img,texflags=0,mask=$FF00FF)
	If par=0 Then par=spritepivot
	imgwid=bbImageWidth(img)
	imghgt=bbImageHeight(img)
	texwid=2 Shl (Bin(imgwid-1).Replace("0"," ").Trim().length-1)
	texhgt=2 Shl (Bin(imghgt-1).Replace("0"," ").Trim().length-1)
	tex=bbCreateTexture(texwid,texhgt,texflags)
	bbLockBuffer bbImageBuffer(img)
	bbLockBuffer bbTextureBuffer(tex)
	
	For x=0 To texwid-1
		For y=0 To texhgt-1
			If x<imgwid><imghgt>
				currpix=bbReadPixelFast(x,y,bbImageBuffer(img))
				If currpix&$FFFFFF=mask Then
					bbWritePixelFast x,y,0,bbTextureBuffer(tex)
				Else
					bbWritePixelFast x,y,currpix,bbTextureBuffer(tex)
				End If
			Else
				bbWritePixelFast x,y,0,bbTextureBuffer(tex)
			End If
		Next
	Next
	
	bbUnlockBuffer bbImageBuffer(img)
	bbUnlockBuffer bbTextureBuffer(tex)
	
Return tex
End Function


And a meager example to download here: http://rattuscanisdev.g0dsoft.com/uploads/dnload/spritesurfacetest.zip Rest assured you can get more out of it than this. I'm just lazy when preparing examples. It should show you how it pretty much works.