.: The Particle System
|
|
| |
In the last tutorial we found a way of determining which balls will be dropped and which will explode, in this tutorial we will now implement the particle system that will draw these processes. So, as before, using the source code from the last tutorial, open the project and and go to the Graphics Module.
There are a couple of changes to the code before we start the particle system.
The following declaration has been added to the graphics module:
'A Random Number Generator, Used in GetRandomColour and MoveParticles Subs
Public RandomizePub As Random = New Random
The GetRandomColour Sub becomes:
|
|
'Get Random Colour
Public Function GetRandomColour()
Dim RndNum As Integer = RandomizePub.Next(0, 5)
Dim RndColour As String = ""
Select Case RndNum
Case Is = 0
RndColour = "Blue"
Case Is = 1
RndColour = "Red"
Case Is = 2
RndColour = "Green"
Case Is = 3
RndColour = "Yellow"
Case Is = 4
RndColour = "Black"
End Select
Return RndColour
RndNum = Nothing
RndColour = Nothing
End Function
The above changes ensures that the randomness of the Sub is truly random and that the randomizepub object can be used anywhere in the project. In the Form1 code I have changed the Space Bar section of the Key_Down code to:
Case Is = Windows.Forms.Keys.Space
If ABallHasBeenLaunched = False Then ' If a ball is not already moving
If ABallNeedsPositionedCorrectly = False Then
For Each SingleBall As Ball In BallsArray ' Check every ball in the array
If SingleBall.IsDeleted = False Then
If SingleBall.BallRect = BallLauncherRect7 Then ' If ball is in the launch position
If SingleBall.IsMoving = False Then
GetBallVectorFromArrow() ' Get direction of arrow
End If
BallLauncherRect7IsEmpty = True
ANewBallIsNeeded = True
SingleBall.IsMoving = True
SingleBall.IsInLauncher = False
ABallHasBeenLaunched = True
Exit For ' because only one ball will be in the launch position we can safely exit the
'for loop after we have found it
End If
End If
Next
End If
End If
This new code ensures that a ball is positioned correctly before another one is launched.
The particle system involves a fair bit of new code, starting with declarations in the graphics module:
'A new array list to hold all particles, used in the Particles class
Public ParticlesArray() As Particle = New Particle() {}
Public TheParticelArrayNeedsRedimmed As Boolean = False
The ParticlesArray will hold all particles that will be used in the game, as was the case for the BallsArray, the variable TheParticlesArrayNeedsRedimmed is a switch that tells the game when to remove deleted particles from the particlesArray.
Next, you can completely delete the DropBalls() Sub.
The RemoveBalls() Sub has new code:
'Remove Balls
Public Sub RemoveBalls()
'For each ball in the BallsArray
For Each TempBall As Ball In BallsArray
'If the balls have their deletion marker set then
If TempBall.IsDeleted = False Then
'if the ball is not in the ball launcher
If TempBall.IsInLauncher = False Then
'If the balls deletion maker (Explode) is set - another type of deletion marker will be used in
'in a future tutorial
If TempBall.MarkedForDeletionExplode = True Then
CreateParticles(TempBall) 'Create the particles used in the explosion
'Set the balls deletion marker
TempBall.IsDeleted = True
End If
End If
End If
Next
'Stop the RemoveBalls Sub running again
BallsNeedRemoved = False
End Sub
The new code creates a Particle System using the exploding ball as its template. The ball's position and Colour will be used to create the particles.
The next new sub is the CreateParticle Sub:
'Creates a Single Particle
Public Sub CreateParticle(ByVal BallColour As String, ByVal BallXpos As Integer, ByVal BallYpos As Integer, ByVal ParticleNumber As Integer)
Dim TempParticle As Particle = New Particle
TempParticle.ParticleRect = New Rectangle(BallXpos, BallYpos, 6, 6)
TempParticle.ParticleTex = Texture2D.FromFile(Device, "../../images/Ball" & BallColour & ".png", TempParticle.ParticleTexCreationParams)
TempParticle.ParticleColour = BallColour
TempParticle.ParticleNum = ParticleNumber
ReDim Preserve ParticlesArray(UBound(ParticlesArray) + 1)
ParticlesArray(UBound(ParticlesArray)) = TempParticle
TempParticle = Nothing
End Sub
As you can see a particle is just a small ball, the only other difference between a particle and a ball is that a particle has a number called particlenum, as there are 36 particles per ball, this number is used to distinguish between particles.
The next sub creates all 36 particles using the CreateParticles Sub:
'Create Particles to show Explosion of a Ball
Public Sub CreateParticles(ByVal ExplodingBall As Ball)
'we will now create the 36 balls that will represent the exploding ball
'Basically a square of 6 particles long and 6 particles high
For x As Integer = 0 To 35
Select Case x
Case Is <= 5
CreateParticle(ExplodingBall.BallColour, ((ExplodingBall.BallRect.X + 1) + (x * 6)), ExplodingBall.BallRect.Y + 1, x)
Case 6 To 11
CreateParticle(ExplodingBall.BallColour, ((ExplodingBall.BallRect.X + 1) + ((x - 6) * 6)), ((ExplodingBall.BallRect.Y + 1) + 6), x)
Case 12 To 17
CreateParticle(ExplodingBall.BallColour, ((ExplodingBall.BallRect.X + 1) + ((x - 12) * 6)), ((ExplodingBall.BallRect.Y + 1) + 12), x)
Case 18 To 23
CreateParticle(ExplodingBall.BallColour, ((ExplodingBall.BallRect.X + 1) + ((x - 18) * 6)), ((ExplodingBall.BallRect.Y + 1) + 18), x)
Case 24 To 29
CreateParticle(ExplodingBall.BallColour, ((ExplodingBall.BallRect.X + 1) + ((x - 24) * 6)), ((ExplodingBall.BallRect.Y + 1) + 24), x)
Case Is > 29
CreateParticle(ExplodingBall.BallColour, ((ExplodingBall.BallRect.X + 1) + ((x - 30) * 6)), ((ExplodingBall.BallRect.Y + 1) + 30), x)
End Select
Next
End Sub
Every particle system has 6 rows of 6 balls, each row will obviously have different Y coordinates but equal X coordinates, and every column will have diiferent x coords but equal y coords. This has been written in the above code using x which corresponds to the particles unique particle number. This sub creates a set of particles in a square.
The next sub is used to remove deleted particles from the particlesarray:
'Check Particles Array for Deleted Particles
Public Sub CheckParticlesArray()
'Create a temporary array to hold non-deleted particles
Dim TempParticles() As Particle = New Particle() {}
For Each TempPart As Particle In ParticlesArray
If TempPart.IsDeleted = False Then
ReDim Preserve TempParticles(UBound(TempParticles) + 1)
TempParticles(UBound(TempParticles)) = TempPart
End If
Next
If UBound(TempParticles) > 0 Then
'Resize the Particles Array to the same size as the temporary array
ReDim ParticlesArray(UBound(TempParticles))
'copy the non-deleted particles back to the particles array
TempParticles.CopyTo(ParticlesArray, 0)
End If
'Erase the temp array
Erase TempParticles
'Stop the Sub running again until it is needed
TheParticelArrayNeedsRedimmed = False
End Sub
This sub is called from the Render loop, when the particles array has more than 10 elements and the variable TheParticleArrayNeedsRedimmed is set to True.
The last sub in the graphics module:
'Move the particles
Public Sub MoveParticle(ByVal TempParticle As Particle)
With TempParticle
'Only move those particles that are still in play
If .IsDeleted = False Then
If .OriginalXPos = 0 Then
'Set the original positions of the particles, used as reference points that the particles will travel away from
.OriginalXPos = .ParticleRect.X
.OriginalYPos = .ParticleRect.Y
End If
If .SpeedDecided = False Then
.XSpeed = 3 * RandomizePub.NextDouble 'Speed in the X direction
.ParticleRect.X -= .XSpeed 'move Particle in the X direction
.SpeedDecided = True
If .TempVarInt > 0 Then ' particle will move up while TempVarInt is positive
.ParticleRect.Y -= .YSpeed ' Move particle up
.TempVarInt -= 1 'decrese TempvarInt by 1
.YSpeed = .YSpeed - (.YSpeed / RandomizePub.Next(5, 10)) 'decrease Speed in the Y Direction, giving impression of gravity
Else
'When TempVarInt is negative particle will move down
.ParticleRect.Y += .YSpeed 'move particle down
.YSpeed = .YSpeed + (.YSpeed / RandomizePub.Next(5, 10)) 'increase speed in y direction
End If
ElseIf .SpeedDecided = True Then
.ParticleRect.X -= .XSpeed 'move Particle in the X direction
If .TempVarInt > 0 Then ' particle will move up while TempVarInt is positive
.ParticleRect.Y -= .YSpeed ' Move particle up
.TempVarInt -= 1 'decrese TempvarInt by 1
.YSpeed = .YSpeed - (.YSpeed / RandomizePub.Next(5, 10)) 'decrease Speed in the Y Direction, giving impression of gravity
Else
'When TempVarInt is negative particle will move down
.ParticleRect.Y += .YSpeed 'move particle down
.YSpeed = .YSpeed + (.YSpeed / RandomizePub.Next(5, 10)) 'increase speed in y direction
End If
End If
' If a particle moves outside the playarea then delete it
If .ParticleRect.Y > PlayAreaRect.Bottom Then
.IsDeleted = True
TheParticelArrayNeedsRedimmed = True 'Redim the particles array
End If
If .ParticleRect.X > PlayAreaRect.Right Then
.IsDeleted = True
End If
If .ParticleRect.X < PlayAreaRect.Left - 38 Then
.IsDeleted = True
End If
End If
End With
End Sub
This sub decides randomly how each particle will move and them move the particle in an arc that has the appearance of being affected by gravity. If a particle moves outside the playarea it is deleted. That's it for the graphics module. We will now create the particle class.
Right-click on the project name and select Add Class, name this class particle and add the following code:
Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Graphics
Public Class Particle
#Region "Objects and variables"
Public ParticleTex As Texture2D = Nothing
Public ParticleTexCreationParams As TextureCreationParameters = TextureCreationParameters.Default
Public ParticleRect As Rectangle = Nothing
Public ParticleXVel As Single = 0.02 'speed of the particle in the X direction
Public ParticleYVel As Single = 0.02 ' speed of the particle in the Y direction
Public ParticleColour As String = "Blue" ' The colour of the particle
Public ParticleNum As Integer = 0 ' There will be 36 different particles per ball, each will move in a different direction, giving the explosion effect
Public OriginalXPos As Integer = 0 'Used to Define Movement
Public OriginalYPos As Integer = 0 'Used to Define Movement
Public TempVarInt As Integer = 15 'Used to define change of movement in Y direction
Public XSpeed As Single = 2.0 ' Used to Define particle speed in X direction
Public YSpeed As Single = 2.0 ' Used to Define particle speed in Y direction
Public IsDeleted As Boolean = False ' Used to remove particles once they have moved outside the playArea
Public SpeedDecided As Boolean = False 'If False, then random values will be selected for particle speed
#End Region
End Class
The particle class hold the variables and objects that will define each particle's movement and what actions are performed them, and when.
The last of the new code is in the Render function which becomes:
Private Sub Render()
'Clear the backbuffer to a blue color
Device.Clear(ClearOptions.Target, Microsoft.Xna.Framework.Graphics.Color.Blue, 1.0F, 0)
'Draw all Non Ball Textures
MainSB.Begin(SpriteBlendMode.AlphaBlend)
'Draw Ball
If UBound(BallsArray) > 0 Then
For Each SingleBall As Ball In BallsArray ' Check every ball in array
If SingleBall.IsDeleted = False Then
MainSB.Draw(SingleBall.BallTex, SingleBall.BallRect, Color.White) 'Draw Each Ball
End If
If SingleBall.IsMoving = True Then 'If a ball is set to move
SingleBall.MoveBall() 'Move the ball
End If
If BallLauncherRect7IsEmpty = True Then ' BallLauncherRect7IsEmpty is Set to True when a ball is launched
SingleBall.MoveBallLauncherBalls() ' Move the balls in the ball launcher
End If
If SingleBall.MarkedForDeletionDrop = True Then 'If a Ball is to be dropped
SingleBall.BallRect.Y += SingleBall.BallXVel 'Move the ball down at speed BallXVel
SingleBall.BallXVel += 0.5 'increase BallXVel to give appearance of gravity
SingleBall.IsDropped = True 'Variable to exclude ball fromm Collison
'If it moves below thw playarea then delete it
If SingleBall.BallRect.Y > PlayAreaRect.Bottom Then
SingleBall.IsDeleted = True
End If
End If
Next
If ABallHasBeenLaunched = True Then ' A global variable used to tell the program when to start checking for
If UBound(BallsArray) > 1 Then ' collisions
CheckForCollision() ' Check for a collision
End If
End If
'If a Ball needs to be positioned correctly
If ABallNeedsPositionedCorrectly = True Then
If UBound(BallsArray) > 1 Then
'Correctly Position Ball
PositionBallCorrectly()
End If
End If
'Check for 3 touching Balls
If ShouldWeCheckFor3TouchingBalls = True Then
If CheckFor3TouchingBalls() = True Then
FindTheBallsToRemove()
End If
End If
'If BallsNeedRemoved = True then Run the RemoveBalls Sub
If BallsNeedRemoved = True Then
RemoveBalls() ' Find those balls tha have MarkedForDeletionExplode = False, then set IsDeleted = True
RedimBallArray() ' Remove those Balls that have IsDeleted = True from the Array
FindBallsToDrop() ' Find which Balls should fall out the game, as they are no longer connected to the top of the playarea
End If
'Animate Particles if there are any
If UBound(ParticlesArray) > 0 Then
For Each TempPart As Particle In ParticlesArray
MainSB.Draw(TempPart.ParticleTex, TempPart.ParticleRect, Color.White) 'Draw Each Particle
MoveParticle(TempPart) 'Move each particle
Next
End If
'Remove any Deleted Particles
If TheParticelArrayNeedsRedimmed = True AndAlso UBound(ParticlesArray) > 10 Then
CheckParticlesArray()
End If
End If
MainSB.Draw(BackgroundTex, BackgroundRect, Color.White)
MainSB.Draw(PlayAreaTex, PlayAreaRect, Color.White)
MainSB.Draw(BallLauncherTex, BallLauncherRect, Color.White)
'Draw Arrow - Arrow is drawn after ball so that it appears on top of ball.
'Anything drawn last will appear above anything drawn before
MainSB.Draw(ArrowTex, New Vector2(405, 485), Nothing, Color.White, ArrowSBRotate, _
New Vector2((ArrowTex.Width / 2), (ArrowTex.Height / 2)), 1.0F, SpriteEffects.None, 0.0F)
MainSB.End()
'Display the Scene to the Screen
Device.Present()
End Sub
The first bit of new code will move any ball straight down if it has its MarkedForDeletionDrop marker set to true, the speed of the drop will increase giving the impression of gravity. The next bit of new code will draw and move the particles in the particlesarray if the number of particles in the array is bigger than 0. The last new bit of code will remove deleted particles from the array if the variable TheParticleArrayNeedsRedimmed is set to True and the number of array elements is bigger than 10. This value is set to 10 and not 0 because sometimes for some reason a few particles were left in the array, this would mean that the Sub ran continually.
Now, if you run the game, it should act like this:

And Once the Red balls collide

As you can see the Red balls exploded and the other balls fell, just as they were supposed to. In the next tutorial we will work on the a scoring system and a way to create levels. As usual, once i have completed it I will upload it to the tutorials page. So, until then, enjoy
Web site contents © Copyright Alan Phipps 2006, All rights reserved.
Website templates |