ThePentiumGuy
Well-known member
I will be making a set of 5 or 6 tutorials, each of which include source for Visual Basic.NET 2002 and Visual Basic.NET 2003. C# tutorials may or may not follow. These tutorials are to give you guys a jumpstart to some Direct3D. I hope you enjoy these.
This tutorial will teach you how to move stuff around using Matrices and Transformations.
Hey welcome to the next tutorial.. this is the tutorial that will start to confuse the hell out of you.. just know 1 thing: As long as you keep an open mind and a positive attitude youll understand this ;p.
Heh, lets start with a few Q and A to get the ball rolling
The obvious question:
"How do you move stuff??"
The n00b responses (which I expect from some of you at this stage):
"Well, the first thing to do is recreate the vertices - its kinda simple, if you want to move a square right, all you gotta do is this:
vertex(0) = new customvertex.positionTextured(<1 unit to the right>)
and do the same with the other vertices"
Sorry, wrong answer... http://www.computerhelp.forum/x_images/images/smilies/frown.gif Direct3D doesnt allow this... why? Because youre changing data in the vertex buffer. The vertex buffer is loaded and ready to go (there is a way around this but this is not for now), and you cant change it!
n00b response to that:
"Well all you gotta do is recreate the vertex buffer and load in a new set of vertices"
Well... yes that could work... but isnt that a TOTAL waste of memory? Youre creating a TOTALLY new vertex buffer and youre filling it with ANOTHER set of vertices = lag fest & flicker mania http://www.computerhelp.forum/images/smilies/biggrin.gif. So .... youre wrong ;p.
A g33k comes up with a response:
"Well, its rather simple actually, Direct3D has its own built-in functions for doing this, it involves a complex system of matrices. The world gets translated in the direction which you want your objects to move and the result is a mass-movement of all objects in that specified direction."
Uhh... yeah thats the correct answer..... In english please??, here it is:
-Every object is in the WORLD.
These objects cant move on their own (by changing the vertices or recreating the vertex buffer..etc) because it would be too slow.... imagine moving a 3D Character this way...do you realize how many vertices wed have to move in order to move him? Even if this was just 1 pixel to the right.. its a CRAZY way of doing this
So, the ingenious Microsoft came up with a way of doing this:
Move the world to move an object.
;P, scary huh? Again, keep an optimistic outlook and an open mind towards this concept, it might seem weird but everything has its reasons.
If an object wants to move left... what do you do? Make the world move left as well . The same goes for the other directions.. which ever direction the object wants to go in, the world goes in.
So to move that high polygon 3D character model, you move the world rather than move the individual vertices over... you sort of understand what I mean?
How do we move the world? Well... heres where it gets a bit confusing,
Microsoft stores the world in a Matrix which is stored in your Device. The process of moving the world is called Translating... there are other transformations as well, such as Rotation and Scaling, but Translating is just moving it...
Well heres how to translate the world 1 unit to the right.. assuming d3ddev is your device:
d3ddev.Transform.World = Matrix.Translation(1,0,0).
The 3 arguments are X, Y, and Z respecitively. That 1 indicates that the world is being moved 1 unit to the right.
Now that our character has moved 1 unit to the right, how do we move him back to his original position?
d3ddev.Transform.World = Matrix.Translation(0,0,0)
Lets try experimenting with this http://www.computerhelp.forum/x_images/images/smilies/smile.gif.
Open up the previous project (Rendering a Sprite)... Go to GameClass and then go to the RenderScene sub..
Right before Alex.Render, type in
d3ddev.transform.World = Matrix.Translation(30,0,0)
Run it...
edit: before you run it, do 1 thing, it is an error on my part in the previous tutorial, in the Initialize in GameClass, please change
D3Ddev.Transform.View = Matrix.OrthoOffCenterLH(0, DP.Width, DP.Height, 0, 0, 10)
to
D3Ddev.Transform.View = Matrix.OrthoOffCenterLH(0, DP.Width, DP.Height, 0, 1, 10)
Due to some mathematical reason, the zNearPlane argument must be 1 (dont worry if you dont understand this line anyways, i will explain later in the tutorial
The character just shifted 30 units to the right. Be sure to realize one thing, remember that the top left of the character is position (0,0,0), which is the top left of the screen?
Well now, the point (0,0,0) has now shifted 30 units to the right, it is now where 30,0,0 used to be.. the characters top left is still at point 0,0,0... the top left of the screen is now -30,0,0 http://www.computerhelp.forum/images/smilies/biggrin.gif... starting to understand a bit?
Now lets try something different
How do we translate the world 1 unit to the right each frame[each time the object is rendered]?
Well, first of all, we would have d3ddev.transform.world = matrix.translation(1,0,0) right? How would we make it move 1 unit to the right of its previous position, meaning how do we make it keep moving right 1 unit??
Wed simply do this [replace this line with the translation(30,0,0) line:
d3ddev.transform.world = Matrix.Multiply(d3ddev.transform.world, matrix.translation(1,0,0))
Dont worry, the line may seem tricky, but just replace that line with your other translation line and run it... So now the guy moves REALLY quickly across the screen.. for those of you with fast computers,
I suggest that you change the 1 into a 0.1 or a 0.01. Depending on the amount of FPS (Frames Per Second) you get, the faster hell go ....
so Multiply simply translates the world from the PREVIOUS position.. and without Multiply, it would translate the world from position (0,0,0)... got all that? If you dont - play around with it for a while and it might sink in http://www.computerhelp.forum/images/smilies/biggrin.gif.
-------------------------------------------------------------
Now that youve understood that (I dont expect you to understand it completely, but get the general gist of what it does), lets discuss a bit on how to animate.
The first response that people come up with is usually
"Simple, use the Multiply along with Translation to animate the character - except use variables.. for example:
d3ddev.transform.world = Matrix.Multiply(d3ddev.transform.world, matrix.Translation(x,y,0)) since Z doesnt matter in a 2d game set it to 0. When the character presses (for example) right, set x = 1 so he can start animating, when there is no key pressed, set x = 0 so he can STOP animating"
- Ill tell you right now that this is the wrong way, but.. I like to teach people Why we do things as opposed to simply How we do things... lets experiment:
In GameClass:
Public X as Single
Public Y as Single
replace that translation line [you should only have 1 translation line] with:
d3ddev.transform.world = Matrix.Multiply(d3ddev.transform.world, matrix.Translation(x,y,0))
Now go back to form1.. add the following code
[/color]And in form1_keyup:
game.x = 0
game.y = 0
Now test out the code ;D...
You see that it works right? Heres my reasoning behind why we shouldnt do this... the Matrix.Multiply thing is based on time (FPS) becuase it moves the world based on frame count..
you move it .1 in whatever direction, lets say the Frames Per Second is 1, that means that it moves the world by .1 (in whatever direction) every second. Based on the FPS only youll know how much youre actually moving the world by... this leads to confusion..
So theres another technique which does not use multiply and translation, it just uses translation < i bet you guys now know what it is >
<Im Splitting post to overcome limit>
This tutorial will teach you how to move stuff around using Matrices and Transformations.
Hey welcome to the next tutorial.. this is the tutorial that will start to confuse the hell out of you.. just know 1 thing: As long as you keep an open mind and a positive attitude youll understand this ;p.
Heh, lets start with a few Q and A to get the ball rolling
The obvious question:
"How do you move stuff??"
The n00b responses (which I expect from some of you at this stage):
"Well, the first thing to do is recreate the vertices - its kinda simple, if you want to move a square right, all you gotta do is this:
vertex(0) = new customvertex.positionTextured(<1 unit to the right>)
and do the same with the other vertices"
Sorry, wrong answer... http://www.computerhelp.forum/x_images/images/smilies/frown.gif Direct3D doesnt allow this... why? Because youre changing data in the vertex buffer. The vertex buffer is loaded and ready to go (there is a way around this but this is not for now), and you cant change it!
n00b response to that:
"Well all you gotta do is recreate the vertex buffer and load in a new set of vertices"
Well... yes that could work... but isnt that a TOTAL waste of memory? Youre creating a TOTALLY new vertex buffer and youre filling it with ANOTHER set of vertices = lag fest & flicker mania http://www.computerhelp.forum/images/smilies/biggrin.gif. So .... youre wrong ;p.
A g33k comes up with a response:
"Well, its rather simple actually, Direct3D has its own built-in functions for doing this, it involves a complex system of matrices. The world gets translated in the direction which you want your objects to move and the result is a mass-movement of all objects in that specified direction."
Uhh... yeah thats the correct answer..... In english please??, here it is:
-Every object is in the WORLD.
These objects cant move on their own (by changing the vertices or recreating the vertex buffer..etc) because it would be too slow.... imagine moving a 3D Character this way...do you realize how many vertices wed have to move in order to move him? Even if this was just 1 pixel to the right.. its a CRAZY way of doing this
So, the ingenious Microsoft came up with a way of doing this:
Move the world to move an object.
;P, scary huh? Again, keep an optimistic outlook and an open mind towards this concept, it might seem weird but everything has its reasons.
If an object wants to move left... what do you do? Make the world move left as well . The same goes for the other directions.. which ever direction the object wants to go in, the world goes in.
So to move that high polygon 3D character model, you move the world rather than move the individual vertices over... you sort of understand what I mean?
How do we move the world? Well... heres where it gets a bit confusing,
Microsoft stores the world in a Matrix which is stored in your Device. The process of moving the world is called Translating... there are other transformations as well, such as Rotation and Scaling, but Translating is just moving it...
Well heres how to translate the world 1 unit to the right.. assuming d3ddev is your device:
d3ddev.Transform.World = Matrix.Translation(1,0,0).
The 3 arguments are X, Y, and Z respecitively. That 1 indicates that the world is being moved 1 unit to the right.
Now that our character has moved 1 unit to the right, how do we move him back to his original position?
d3ddev.Transform.World = Matrix.Translation(0,0,0)
Lets try experimenting with this http://www.computerhelp.forum/x_images/images/smilies/smile.gif.
Open up the previous project (Rendering a Sprite)... Go to GameClass and then go to the RenderScene sub..
Right before Alex.Render, type in
d3ddev.transform.World = Matrix.Translation(30,0,0)
Run it...
edit: before you run it, do 1 thing, it is an error on my part in the previous tutorial, in the Initialize in GameClass, please change
D3Ddev.Transform.View = Matrix.OrthoOffCenterLH(0, DP.Width, DP.Height, 0, 0, 10)
to
D3Ddev.Transform.View = Matrix.OrthoOffCenterLH(0, DP.Width, DP.Height, 0, 1, 10)
Due to some mathematical reason, the zNearPlane argument must be 1 (dont worry if you dont understand this line anyways, i will explain later in the tutorial
The character just shifted 30 units to the right. Be sure to realize one thing, remember that the top left of the character is position (0,0,0), which is the top left of the screen?
Well now, the point (0,0,0) has now shifted 30 units to the right, it is now where 30,0,0 used to be.. the characters top left is still at point 0,0,0... the top left of the screen is now -30,0,0 http://www.computerhelp.forum/images/smilies/biggrin.gif... starting to understand a bit?
Now lets try something different
How do we translate the world 1 unit to the right each frame[each time the object is rendered]?
Well, first of all, we would have d3ddev.transform.world = matrix.translation(1,0,0) right? How would we make it move 1 unit to the right of its previous position, meaning how do we make it keep moving right 1 unit??
Wed simply do this [replace this line with the translation(30,0,0) line:
d3ddev.transform.world = Matrix.Multiply(d3ddev.transform.world, matrix.translation(1,0,0))
Dont worry, the line may seem tricky, but just replace that line with your other translation line and run it... So now the guy moves REALLY quickly across the screen.. for those of you with fast computers,
I suggest that you change the 1 into a 0.1 or a 0.01. Depending on the amount of FPS (Frames Per Second) you get, the faster hell go ....
so Multiply simply translates the world from the PREVIOUS position.. and without Multiply, it would translate the world from position (0,0,0)... got all that? If you dont - play around with it for a while and it might sink in http://www.computerhelp.forum/images/smilies/biggrin.gif.
-------------------------------------------------------------
Now that youve understood that (I dont expect you to understand it completely, but get the general gist of what it does), lets discuss a bit on how to animate.
The first response that people come up with is usually
"Simple, use the Multiply along with Translation to animate the character - except use variables.. for example:
d3ddev.transform.world = Matrix.Multiply(d3ddev.transform.world, matrix.Translation(x,y,0)) since Z doesnt matter in a 2d game set it to 0. When the character presses (for example) right, set x = 1 so he can start animating, when there is no key pressed, set x = 0 so he can STOP animating"
- Ill tell you right now that this is the wrong way, but.. I like to teach people Why we do things as opposed to simply How we do things... lets experiment:
In GameClass:
Public X as Single
Public Y as Single
replace that translation line [you should only have 1 translation line] with:
d3ddev.transform.world = Matrix.Multiply(d3ddev.transform.world, matrix.Translation(x,y,0))
Now go back to form1.. add the following code
Code:
[color=#0000ff]If[/color] e.KeyCode = Keys.Right [color=#0000ff]Then
[/color]Game.X = 0.1
[color=#0000ff]End[/color][color=#0000ff]If
[/color][color=#0000ff]If[/color] e.KeyCode = Keys.Left [color=#0000ff]Then
[/color]Game.X = -0.1
[color=#0000ff]End[/color][color=#0000ff]If
[/color][color=#0000ff]If[/color] e.KeyCode = Keys.Up [color=#0000ff]Then
[/color]Game.Y = -0.1
[color=#0000ff]End[/color][color=#0000ff]If
[/color][color=#0000ff]If[/color] e.KeyCode = Keys.Down [color=#0000ff]Then
[/color]Game.Y = 0.1
[color=#0000ff]End[/color][color=#0000ff]If[/color]
[color=#0000ff]
[/color][color=#0000ff]
[/color]And in form1_keyup:
game.x = 0
game.y = 0
Now test out the code ;D...
You see that it works right? Heres my reasoning behind why we shouldnt do this... the Matrix.Multiply thing is based on time (FPS) becuase it moves the world based on frame count..
you move it .1 in whatever direction, lets say the Frames Per Second is 1, that means that it moves the world by .1 (in whatever direction) every second. Based on the FPS only youll know how much youre actually moving the world by... this leads to confusion..
So theres another technique which does not use multiply and translation, it just uses translation < i bet you guys now know what it is >
<Im Splitting post to overcome limit>
Last edited by a moderator: