noi_max
07-12-2004, 02:24 PM
I've seen this pop up a few times over in the game programming section so I thought I would take a crack at my first tutorial.
Plus, I just love to move stuff around, so here we go...
Moving a picturebox on a form:
I'll start by creating a new project and adding a picturebox and a timer control to the form. I've kept the default names for sake of simplicity.
The key thing with using these objects is the dimensions and how they work.
The picture box, for example has a Top, Left, Height and Width property that we can utilize. The form has these properties as well. The very Top/Left of the form would be considered 0, 0. To move the picturebox down and
to the right on the form you would need to add to the .Top and .Left dimensions of the picturebox respectively.
To demonstrate, I will set some things up in the Form_Load event to set where the picturebox will appear on the form. Feel free to follow along...
Private Sub Form_Load()
Picture1.Top = 500
Picture1.Left = 500
End Sub
This will offset the picturebox from the top/left corner of the form. This offest is ulimately how we will move the picturebox.
The Timer Control:
Think of the timer control as a loop, that will start and stop when we want it to.
Each time the timer control 'fires' we will move the picturebox using the .Top
property.
When you double click on the Timer control on your form, you'll see that it has
it's own procedure. It's in there that the movement will happen.
We'll set how often the timer fires in the Form_Load. Here is the code in the
project so far...
Private Sub Form_Load()
Picture1.Top = 500
Picture1.Left = 500
'Set the interval. This is measured in milliseconds
Timer1.Interval = 10
'Start the timer
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
'The timer fires once every 10 milliseconds. So in that time, let's move the
'picture box downward by adding to the Picture1.Top property
Picture1.Top = Picture1.Top + 30
End Sub
I put 30 in there for movement. Feel free to change that number to see what
happens.
Basic Wrap:
If you've been following along, you'll notice that the picturebox moves beyond the bottom of the form and then disappears. The timer is still going, in fact the picturebox is still moving, we just can no longer see it!
Since we have the dimensions of the form and picturebox available we can make a simple wrap function to have the picturebox re-appear at the top of the screen after it's reached the bottom. Here's an example:
Private Sub CheckWrap()
'If we kept moving the picturebox, it would disappear. It's still moving, but it's
'coordinates are out of visible range. A simple wrap around function will keep it
'on the screen.
'To do this we need to check if the picture top has gone beyond the
'scaleheight of the form. If it has, set the picturebox's top property to re-'start at the top.
'Here, I used 0 - Picture1.ScaleHeight to make it appear as though the picture is
'coming from beyond the top of the form. Try changing that and see what happens!
If Picture1.Top > Form1.ScaleHeight Then
Picture1.Top = 0 - Picture1.ScaleHeight
End If
End Sub
I then simply added the CheckWrap procedure to the timer procedure:
Private Sub Timer1_Timer()
Picture1.Top = Picture1.Top + 30
CheckWrap
End Sub
Basic Keyboard Handling:
This one gets asked a lot and I feel it's somewhat relative to what I'm doing
so I'll put it here.
There exists for the form a Keydown and KeyUp event that will handle these
keyboard actions for us using a KeyCode constant. Once you learn a few of these constants the rest would be easy enough to guess, but here's the actual list:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbenlr98/html/vamsckeycodeconstants.asp
The events in the sample code will look like this:
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
'If the spacebar is pressed, start the timer.
If KeyCode = vbKeySpace Then
Timer1.Enabled = True
End If
End Sub
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
'If the spacebar is released stop the timer.
If KeyCode = vbKeySpace Then
Timer1.Enabled = False
End If
End Sub
I then modified the Form_Load like this:
Private Sub Form_Load()
Picture1.Top = 500
Picture1.Left = 500
'Set the interval. This is measured in milliseconds
Timer1.Interval = 10
'Let the keyboard start/stop the timer
Timer1.Enabled = False
'This line is needed for the KeyDown/KeyUp events
KeyPreview = True
End Sub
Put together, this will make the picture box move only when the spacebar is
pressed.
More Keyboard and Wrap:
I suppose the next thing would be to change keyboard handling for the arrow keys and make the wrap procedure handle all 4 directions.
To do this I needed to set up a few booleans in the General Declarations section of the form.
Option Explicit
'Boolean data to handle the keypresses
Private k_Up As Boolean
Private k_Down As Boolean
Private k_Left As Boolean
Private k_Right As Boolean
And now to change the KeyDown/KeyUp events to handle the booleans
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
'Using a select case statement, check for the key pressed and
'set a boolean value to be used later in the movement of the picture box
Select Case KeyCode
Case vbKeyUp
k_Up = True
k_Down = False
Case vbKeyDown
k_Down = True
k_Up = False
Case vbKeyLeft
k_Left = True
k_Right = False
Case vbKeyRight
k_Right = True
k_Left = False
End Select
End Sub
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
Select Case KeyCode
Case vbKeyUp
k_Up = False
Case vbKeyDown
k_Down = False
Case vbKeyLeft
k_Left = False
Case vbKeyRight
k_Right = False
End Select
End Sub
Now, change the timer procedure to handle all of the directions. This will
introduce the .Left property of the picture box.
Remember, since we add to the .Top and .Left properties to offset down and right respectively, we will need to subtract to go Left and Up.
Private Sub Timer1_Timer()
If k_Up = True Then
Picture1.Top = Picture1.Top - 30
End If
If k_Down = True Then
Picture1.Top = Picture1.Top + 30
End If
If k_Left = True Then
Picture1.Left = Picture1.Left - 30
End If
If k_Right = True Then
Picture1.Left = Picture1.Left + 30
End If
CheckWrap
End Sub
Finally, it's time to modify the CheckWrap procedure to handle all of the
directions, using a similar formula as before.
Private Sub CheckWrap()
'If the picture goes beyond the bottom of the form, have it
'reappear atthe top.
If Picture1.Top > Form1.ScaleHeight Then
Picture1.Top = (0 - Picture1.Height)
End If
'If the picture goes beyond the top of the form, have it
'reappear at the bottom
If Picture1.Top < (0 - Picture1.Height) Then
Picture1.Top = Form1.ScaleHeight
End If
'If the picture goes beyond the right side of the form, have it
'reappear at the left.
If Picture1.Left > Form1.ScaleWidth Then
Picture1.Left = (0 - Picture1.Width)
End If
'If the picture goes beyond the left side of the form, have it
'reappear at the right.
If Picture1.Left < (0 - Picture1.Width) Then
Picture1.Left = Form1.ScaleWidth
End If
End Sub
And there you have it. Basic movement in a nutshell.
The timer control is a good place to begin, however the accuracy is, well, not
extremely accurate.
I could, in a follow up tutorial, cover the basics of the QueryPerformanceCounter API function that can be used in place of the timer control for more precision movement.
Here is the completed sample project. Of course you can put a picture into the picturebox if you like. That would probably make it more interesting :)
Plus, I just love to move stuff around, so here we go...
Moving a picturebox on a form:
I'll start by creating a new project and adding a picturebox and a timer control to the form. I've kept the default names for sake of simplicity.
The key thing with using these objects is the dimensions and how they work.
The picture box, for example has a Top, Left, Height and Width property that we can utilize. The form has these properties as well. The very Top/Left of the form would be considered 0, 0. To move the picturebox down and
to the right on the form you would need to add to the .Top and .Left dimensions of the picturebox respectively.
To demonstrate, I will set some things up in the Form_Load event to set where the picturebox will appear on the form. Feel free to follow along...
Private Sub Form_Load()
Picture1.Top = 500
Picture1.Left = 500
End Sub
This will offset the picturebox from the top/left corner of the form. This offest is ulimately how we will move the picturebox.
The Timer Control:
Think of the timer control as a loop, that will start and stop when we want it to.
Each time the timer control 'fires' we will move the picturebox using the .Top
property.
When you double click on the Timer control on your form, you'll see that it has
it's own procedure. It's in there that the movement will happen.
We'll set how often the timer fires in the Form_Load. Here is the code in the
project so far...
Private Sub Form_Load()
Picture1.Top = 500
Picture1.Left = 500
'Set the interval. This is measured in milliseconds
Timer1.Interval = 10
'Start the timer
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
'The timer fires once every 10 milliseconds. So in that time, let's move the
'picture box downward by adding to the Picture1.Top property
Picture1.Top = Picture1.Top + 30
End Sub
I put 30 in there for movement. Feel free to change that number to see what
happens.
Basic Wrap:
If you've been following along, you'll notice that the picturebox moves beyond the bottom of the form and then disappears. The timer is still going, in fact the picturebox is still moving, we just can no longer see it!
Since we have the dimensions of the form and picturebox available we can make a simple wrap function to have the picturebox re-appear at the top of the screen after it's reached the bottom. Here's an example:
Private Sub CheckWrap()
'If we kept moving the picturebox, it would disappear. It's still moving, but it's
'coordinates are out of visible range. A simple wrap around function will keep it
'on the screen.
'To do this we need to check if the picture top has gone beyond the
'scaleheight of the form. If it has, set the picturebox's top property to re-'start at the top.
'Here, I used 0 - Picture1.ScaleHeight to make it appear as though the picture is
'coming from beyond the top of the form. Try changing that and see what happens!
If Picture1.Top > Form1.ScaleHeight Then
Picture1.Top = 0 - Picture1.ScaleHeight
End If
End Sub
I then simply added the CheckWrap procedure to the timer procedure:
Private Sub Timer1_Timer()
Picture1.Top = Picture1.Top + 30
CheckWrap
End Sub
Basic Keyboard Handling:
This one gets asked a lot and I feel it's somewhat relative to what I'm doing
so I'll put it here.
There exists for the form a Keydown and KeyUp event that will handle these
keyboard actions for us using a KeyCode constant. Once you learn a few of these constants the rest would be easy enough to guess, but here's the actual list:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbenlr98/html/vamsckeycodeconstants.asp
The events in the sample code will look like this:
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
'If the spacebar is pressed, start the timer.
If KeyCode = vbKeySpace Then
Timer1.Enabled = True
End If
End Sub
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
'If the spacebar is released stop the timer.
If KeyCode = vbKeySpace Then
Timer1.Enabled = False
End If
End Sub
I then modified the Form_Load like this:
Private Sub Form_Load()
Picture1.Top = 500
Picture1.Left = 500
'Set the interval. This is measured in milliseconds
Timer1.Interval = 10
'Let the keyboard start/stop the timer
Timer1.Enabled = False
'This line is needed for the KeyDown/KeyUp events
KeyPreview = True
End Sub
Put together, this will make the picture box move only when the spacebar is
pressed.
More Keyboard and Wrap:
I suppose the next thing would be to change keyboard handling for the arrow keys and make the wrap procedure handle all 4 directions.
To do this I needed to set up a few booleans in the General Declarations section of the form.
Option Explicit
'Boolean data to handle the keypresses
Private k_Up As Boolean
Private k_Down As Boolean
Private k_Left As Boolean
Private k_Right As Boolean
And now to change the KeyDown/KeyUp events to handle the booleans
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
'Using a select case statement, check for the key pressed and
'set a boolean value to be used later in the movement of the picture box
Select Case KeyCode
Case vbKeyUp
k_Up = True
k_Down = False
Case vbKeyDown
k_Down = True
k_Up = False
Case vbKeyLeft
k_Left = True
k_Right = False
Case vbKeyRight
k_Right = True
k_Left = False
End Select
End Sub
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
Select Case KeyCode
Case vbKeyUp
k_Up = False
Case vbKeyDown
k_Down = False
Case vbKeyLeft
k_Left = False
Case vbKeyRight
k_Right = False
End Select
End Sub
Now, change the timer procedure to handle all of the directions. This will
introduce the .Left property of the picture box.
Remember, since we add to the .Top and .Left properties to offset down and right respectively, we will need to subtract to go Left and Up.
Private Sub Timer1_Timer()
If k_Up = True Then
Picture1.Top = Picture1.Top - 30
End If
If k_Down = True Then
Picture1.Top = Picture1.Top + 30
End If
If k_Left = True Then
Picture1.Left = Picture1.Left - 30
End If
If k_Right = True Then
Picture1.Left = Picture1.Left + 30
End If
CheckWrap
End Sub
Finally, it's time to modify the CheckWrap procedure to handle all of the
directions, using a similar formula as before.
Private Sub CheckWrap()
'If the picture goes beyond the bottom of the form, have it
'reappear atthe top.
If Picture1.Top > Form1.ScaleHeight Then
Picture1.Top = (0 - Picture1.Height)
End If
'If the picture goes beyond the top of the form, have it
'reappear at the bottom
If Picture1.Top < (0 - Picture1.Height) Then
Picture1.Top = Form1.ScaleHeight
End If
'If the picture goes beyond the right side of the form, have it
'reappear at the left.
If Picture1.Left > Form1.ScaleWidth Then
Picture1.Left = (0 - Picture1.Width)
End If
'If the picture goes beyond the left side of the form, have it
'reappear at the right.
If Picture1.Left < (0 - Picture1.Width) Then
Picture1.Left = Form1.ScaleWidth
End If
End Sub
And there you have it. Basic movement in a nutshell.
The timer control is a good place to begin, however the accuracy is, well, not
extremely accurate.
I could, in a follow up tutorial, cover the basics of the QueryPerformanceCounter API function that can be used in place of the timer control for more precision movement.
Here is the completed sample project. Of course you can put a picture into the picturebox if you like. That would probably make it more interesting :)