Best way to "move my character"

Blitz3D Forums/Blitz3D Beginners Area/Best way to "move my character"

W(Posted 2006) [#1]
Hey guys I was just wondering what the best\most effective way to move my animated object throughout my level. I have been studying the blitz example and it uses nodes, that were part of an array, but is there a more effective way of doing so without a huge array??


Pineapple(Posted 2006) [#2]
Could you use banks.. They are faster than arrays!


W(Posted 2006) [#3]
Do you have an example of how to use banks??


octothorpe(Posted 2006) [#4]
Linked lists would probably make more sense.

Umm.. banks are faster than arrays? I highly doubt that. Regardless, you should probably be more concerned with clean code and expandability than microoptimizations.


W(Posted 2006) [#5]
Could you show me how to use lists, and link them in such a way that I could use them to move my character?


WolRon(Posted 2006) [#6]
Types ARE linked lists. Just use First, Before, After, and Last.


W(Posted 2006) [#7]
Hey Wolron, I haven't really heard of First,Before,After, and last. I am very farmiliar with types though. Soo, could you kinda demonstrate what you mean buddy??


WolRon(Posted 2006) [#8]
Type variable
Parameters
variable = any legal variable name

Description
If you know C prgramming, a TYPE is basically a STRUCT in Blitz Basic
.
.
.

See also: Field, End Type, New, Before, After, First, Last, Each, Insert, Delete.

Example code usage:
; Define a crafts Type 

Type crafts 
Field x 
Field y 
Field dead 
Field graphic 
End Type 

; Create 100 crafts, with the unique name of alien 
For t = 1 To 100 
alien.crafts = New crafts 
alien\x = Rnd(0,640) 
alien\y = Rnd(0,480) 
alien\dead = 0 
alien\graphic = 1 
Next 

; Move to the first object 
alien.crafts = First crafts 

Print alien\x 
Print alien\y 
Print alien\dead 
Print alien\graphic 

; move to the next alien object 
alien = After alien 

Print alien\x 
Print alien\y 
Print alien\dead 
Print alien\graphic 

; move to the last alien object 
alien.crafts = Last crafts 

Print alien\x 
Print alien\y 
Print alien\dead 
Print alien\graphic 

; move to the second to the last alien object 
alien = Before alien 

Print alien\x 
Print alien\y 
Print alien\dead 
Print alien\graphic  


So, in your case:
Graphics3D 800, 600

Type Node
	Field entity
	Field x#, y#, z#
End Type

For iter = 1 To 10
	thisNode.Node = New Node
	thisNode\entity = CreateCube() ;CreatePivot() ;normally just an invisible pivot
	thisNode\x# = Rnd(-100, 100)
	thisNode\y# = 0
	thisNode\z# = Rnd(-100, 100)
	PositionEntity thisNode\entity, thisNode\x#, thisNode\y#, thisNode\z#
	EntityColor thisNode\entity, iter * 20, 150, 150 ;note:  can't be used with pivots
Next

myGuy = CreateCamera()

grid_tex=CreateTexture( 32,32,8 )
ScaleTexture grid_tex,10,10
SetBuffer TextureBuffer( grid_tex )
Color 0,0,64:Rect 0,0,32,32
Color 0,0,255:Rect 0,0,32,32,False
SetBuffer BackBuffer()
grid_plane=CreatePlane()
EntityTexture grid_plane,grid_tex
MoveEntity grid_plane, 0, -1, 0

thisNode = First Node

While Not KeyHit(1)
	If EntityDistance(myGuy, thisNode\entity) < 10
		turnrate = 5
	Else
		turnrate = 20
	EndIf
	TurnEntity myGuy, 0, DeltaYaw(myGuy, thisNode\entity)/turnrate, 0
	MoveEntity myGuy, 0, 0, .5
	
	If EntityDistance(myGuy, thisNode\entity) < 2
		If thisNode = Last Node Then thisNode = First Node
		thisNode = After thisNode
	EndIf
	
	RenderWorld()
	Flip
Wend

End



octothorpe(Posted 2006) [#9]
Types ARE linked lists. Just use First, Before, After, and Last.


Subtly incorrect. Blitz automatically creates a single, partially-accessible linked list for each defined type. If you implement your own linked lists, you can have the benefits of customizable linked lists, such as multiple lists per type and objects belonging to multiple lists.

thisNode = First Node


See? Only one list per type. If you want your animated objects to follow more than one path, you'll need a different solution.

The conventional approach to "custom" linked lists is to add next (and usually prev) pointer fields to your type so that you can chain objects into lists, setting the pointers at ends of lists to NULL. You need only store a pointer to the first object to be able to access all the elements in its associated list.

Type node
	Field x#, y#, z#
	Field nextNode.node
End Type

Function new_node.node(prevNode.node, x#, y#, z#)
	n.node = New node
	n\x = x : n\y = y : n\z = z
	If prevNode <> Null Then prevNode\nextNode = n ; update the node before us
	Return n
End Function

a1.node = new_node(Null, 1, 1, 1) ; new list
a2.node = new_node(a1,   2, 2, 2) ; chain a1 to this node
a3.node = new_node(a2,   2, 3, 3) ; ...
b1.node = new_node(Null, 3, 2, 3) ; new list
b2.node = new_node(b1,   2, 1, 2) ; chain b1 to this node
b3.node = new_node(b2,   0, 0, 1) ; ...

a.node = a1
b.node = b1

display_node_list(b)

Function display_node_list(firstNode.node)
	currentNode.node = firstNode
	While currentNode <> Null
		Print currentNode\x + ", " + currentNode\y + ", " + currentNode\z
		currentNode = currentNode\nextNode ; advance to the next node
	Wend
End Function


You'll need a function to remove a node without breaking the list. You may end up adding functions to rearrange elements, treat your list as a queue or a stack, and other fun things.

Although this is a fantastic solution, some of us are prone to over-engingeering. The next step is to separate the linked list logic from your type so you can reuse it with other types. Since there's no polymorphism in Blitz Basic, you'll need to copy your linked list functions anytime you need lists of a new type. I got tired of this and devised a different solution.


W(Posted 2006) [#10]
OHHHH...my head is going 2 explode!!, well...maybe not, but this topic is really bewildering me, soo can you break the explanation of how to use linked lists for a beginner programmer??


jhocking(Posted 2006) [#11]
A beginner programmer shan't be using linked lists. Stick to arrays until you get up to learning how to use Type.


Sir Gak(Posted 2006) [#12]
I think there's also a linked list approach using Banks. Since a Bank is a bit o' memory reserved of such-and-such size, you could create a linked lists with Banks. It probably would also need a function or two to manage, but I believe it could be done. (Whether it's a BETTER way of doing, I haven't checked). Start with a new Bank, specifying sufficient memory for the info you need to store in the Bank, and 4 additional bytes (ie an integer) at the end. The last 4 bytes are essentially reserved for storing the handle of the next Bank. Initially, the last 4 bytes will be Null (zero). Then, when you need to add another node in the list, you create a new Bank, and put its handle in that last reserved 4 bytes of the first Bank.

Then, when it's time to go through the list, after getting the initial info from the first Bank, you check the last 4 bytes. If they are other than zero, then those bytes (the second/following Bank's handle) are used to access the info in the following Bank you created. This can be added to indefinitely, as long as you have enough memory.

When you run through the list, if a node is no longer needed, you grab the last 4 bytes of that node's following Bank, and copy them to the last 4 bytes of the previous node, effectively "skipping over" the no-longer-needed node. The Bank thus no longer needed, can be Free'd. Because the handle of the folowing Bank was copied to the previous Bank, the list is maintained. You can always add to the node by adding more Banks.

As an additional sophitication, you could also allocate an initial 4 bytes, to be used to store the Handle of a previous Bank (zero, of course, for the first node). With the handle of the previous Bank in the first 4 bytes of a given Bank, and the handle of a following Bank node (if any) in the last 4 bytes, you can navigate forward and backward through the node list as you please, deleting defunct nodes or inserting new ones.

This is what can be done with Banks. To those who use Types, this procedure using Banks is parallel to what the family of "Type" commands do for you, in taking care of some of the adding/deleting/navigating functions for you, so you don't have to keep track of them.

I think Types are perhaps more versatile than the Banks approach, in that you can have fields that can be any kind of variable, ie floating point, integer, strings, simple arrays, other Types, etc., whereas the Banks are pretty much integer-based (unless you get into using Chr$() functions, which, while possible, would probably be pretty hairy to implement).

But, I just wanted to point out that linked lists CAN be done without using Types.


octothorpe(Posted 2006) [#13]
Now my head's going to explode. Why on earth would someone want to reinvent Types with Banks?

can you break the explanation of how to use linked lists for a beginner programmer?


A (type) object is a collection of variables in memory. A pointer is a variable which describes another position in memory - that is, the location of another variable or object. In a linked list, one of the variables in your object acts as a pointer to another object - specifically the next object in the list.

Type node
	Field nextNode.node
End Type

a1.node = New node
a2.node = New node
a3.node = New node

; chain them together
a1\nextNode = a2
a2\nextNode = a3

; now we only need to know about the first node to find the rest
first_node.node  = a1
second_node.node = a1\nextNode
third_node.node  = a1\nextNode\nextNode


I hope this example is simple enough to showcase the general principle. When you understand it, look up at my previous example. If you still don't understand, let me know what it is you're having trouble with and I'll do my best to explain it.

For reference, here are some explanitory articles on linked lists:

http://en.wikipedia.org/wiki/Linked_list
http://www.codeproject.com/cpp/linkedlist.asp


Sir Gak(Posted 2006) [#14]
Didn't say anyone would *want* to reinvent Types with Banks, just saying it's technically possible (and, with more overhead, to boot)

Might be interesting to tackle the problem, just to see how practical it might be (or not be, as the case may turn out).