Tag: object factory

Macro Templates, by example.

Posted by on July 13, 2009

Heres an example of what I call “macro templates” in PureBasic. A template encapsulates certain functionality, allowing you to dynamically generate the code in a flexible manner.

This example implements a bare-bones n-vector library using a structure and a static array:

Macro Vector_Register( _n, _type )
	
	Structure VECTOR#_n#_type
		vector._type[_n]
	EndStructure
	
	Procedure._type Vector#_n#_type#_Add( *r.VECTOR#_n#_type, *a.VECTOR#_n#_type, *b.VECTOR#_n#_type )
		Define.i i
		For i=0 To _n - 1
			*r\vector[i] = *a\vector[i] + *b\vector[i]
		Next
	EndProcedure
	
	Procedure._type Vector#_n#_type#_Subtract( *r.VECTOR#_n#_type, *a.VECTOR#_n#_type, *b.VECTOR#_n#_type )
		Define.i i
		For i=0 To _n - 1
			*r\vector[i] = *a\vector[i] - *b\vector[i]
		Next
	EndProcedure
	
	Procedure._type Vector#_n#_type#_Divide( *r.VECTOR#_n#_type, *a.VECTOR#_n#_type, *b.VECTOR#_n#_type )
		Define.i i
		For i=0 To _n - 1
			If *b\vector[i] <> 0.0 And *a\vector[i] <> 0.0
				*r\vector[i] = *a\vector[i] / *b\vector[i]
			EndIf
		Next
	EndProcedure
	
	Procedure._type Vector#_n#_type#_Multiply( *r.VECTOR#_n#_type, *a.VECTOR#_n#_type, *b.VECTOR#_n#_type )
		Define.i i
		For i=0 To _n - 1
			*r\vector[i] = *a\vector[i] * *b\vector[i]
		Next
	EndProcedure
	
	Procedure._type Vector#_n#_type#_DotProduct( *a.VECTOR#_n#_type, *b.VECTOR#_n#_type )
		Define.i i
		Define._type result
		For i=0 To _n - 1
			result + ( *a\vector[i] * *b\vector[i] )
		Next
		ProcedureReturn result
	EndProcedure
	
	Procedure._type Vector#_n#_type#_Length( *v.VECTOR#_n#_type )
		ProcedureReturn Sqr( Vector#_n#_type#_DotProduct( *v, *v ) )
	EndProcedure
	
	Procedure._type Vector#_n#_type#_Distance( *a.VECTOR#_n#_type, *b.VECTOR#_n#_type )
		Define.VECTOR#_n#_type temp
		Vector#_n#_type#_Subtract( temp, *a, *b )
		ProcedureReturn Vector#_n#_type#_Length( temp )
	EndProcedure
	
	Procedure.s Vector#_n#_type#_Debug( *v.VECTOR#_n#_type, Decimals.i=#PB_Default )
		Define.i i
		Define.s tmp = "["
		For i=0 To _n-1
			tmp + StrF( *v\vector[i], Decimals.i )
			If i <> _n-1
				tmp + ", "
			EndIf
		Next
		tmp + "]"
		Debug tmp
		ProcedureReturn tmp
	EndProcedure
	
EndMacro

It might look strange/complicated at first, but once you read it you’ll realize it’s fairly simple.

Let’s see the usage of this particular template:

Vector_Register(3, f )	; Register a float "vec3".
Define.VECTOR3f a,b,c	; Define a few vectors with the new structure.

a\vector[0] = 10.0
a\vector[1] = 20.0
a\vector[2] = 30.0

b\vector[0] = 100.0
b\vector[1] = 200.0
b\vector[2] = 300.0

Vector3f_Add(c, a, b)	; c = a + b
Vector3f_Debug(c)	; show each element using the debug output.

Debug Vector3f_DotProduct( a, b )
Debug Vector3f_Length( a )
Debug Vector3f_Distance( a, b )

Cool, huh?. And you can define any amount of elements with any basic type.

Of course we sacrificed speed for flexibility. In those cases where we have to define n-vectors, this would be an ideal solution. For everything else, I suggest a specific library, such as my vec3 macro lib.

Using this principle you can abstract almost anything, within reason. One good example is my object factory template.  Ideally one would have arrays, lists, etc. Implemented in this very same way, in such case the possibilities would be endless and you’d be able to define dynamic lists/arrays inside structures, etc.

I strongly advice you to implement at least one of those templates, even if it’s just for an exercise.

Having the extra tools can’t hurt!

Cheers.

VEC3 and EasyObject Libraries updated.

Posted by on May 10, 2009

Today I updated both VEC3 and EasyObject, the download links remain the same.

http://gushh.net/blog/2009/01/09/a-fast-vector-library-for-purebasic/

VEC3 got angle helpers (now you can easily find the angle between two vec3, etc) as well as a curve function to smoothly interpolate variables (you can see it in action in one of the new examples where an enemy turret slowly aims toward the player).

http://gushh.net/blog/2009/05/03/object-factory-for-purebasic/

EasyObject now allows you to send a user variable on all iterators. New example provided (particles)

Cheers!