Basically im trying to make a game where shapes fall from the sky and the user controls the sprite to avoid them. I have it working but only with 1 block falling at a time. I am using the paint method to draw my shapes. I was wondering how to go about coding it so that it created multiple shapes, but they would be created at 1 second intervals so that there is a gap as the follow on from one another. This game is similar to "falldown" for the Iphone however the shapes come from the top. Any advice is appreciated.

Thanks

Recommended Answers

All 2 Replies

Basically im trying to make a game where shapes fall from the sky and the user controls the sprite to avoid them. I have it working but only with 1 block falling at a time. I am using the paint method to draw my shapes. I was wondering how to go about coding it so that it created multiple shapes, but they would be created at 1 second intervals so that there is a gap as the follow on from one another. This game is similar to "falldown" for the Iphone however the shapes come from the top. Any advice is appreciated.

Thanks

I'm no game designer and I've never played with an iPhone... but if you're interested in reading how a business programmer would attempt solving this problem... read on.

So, the falling shapes are objects... falling objects (lets call them fObj) need a class so that you can create multiple falling objects and you can set and retrieve the the FObj's properties and execute their methods. Something like:

Public Enum ShapeTypes
    FallingSquare = 1
    FallingCircle = 2
    FallingDiamond = 3
    FallingMoon = 4
End Enum

Public Class FallingObj

    Private _angularSpeed As Integer
    Private _shapeColor As Color
    Private _location As Point
    Private _speed As Integer
    Private _shape As ShapeTypes
    Private _rotation As Integer
    Private _size As Integer

    ''' <summary>
    ''' The position of the object
    ''' </summary>
    ''' <value>The new location of the object</value>
    ''' <returns>A Point of the new object</returns>
    ''' <remarks></remarks>
    Public Property Location() As Point
        Get
            Return _location
        End Get
        Set(ByVal value As Point)
            _location = value
        End Set
    End Property

    ''' <summary>
    ''' The X or verticle position of the object
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property X() As Integer
        Get
            Return _location.X
        End Get
    End Property

    ''' <summary>
    ''' The Y or Horizontal position of the object
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property y() As Integer
        Get
            Return _location.Y
        End Get
    End Property

    Public Property Size() As Integer
        Get
            Return _size
        End Get
        Set(ByVal value As Integer)
            If value > 0 Then
                _size = value
            End If
        End Set
    End Property

    Public Property Speed() As Integer
        Get
            Return _speed
        End Get
        Set(ByVal value As Integer)
            _speed = value
        End Set
    End Property

    Public Property Shape() As ShapeTypes
        Get
            Return _shape
        End Get
        Set(ByVal value As ShapeTypes)
            _shape = value
        End Set
    End Property

    Public Property Rotation() As Integer
        Get
            Return _rotation
        End Get
        Set(ByVal value As Integer)
            If value > 359 Then
                value = value Mod 360
            End If
            If value < 0 Then
                value = value Mod 360
            End If
            _rotation = value
        End Set
    End Property

    Public Property ShapeColor() As Color
        Get
            Return _shapeColor
        End Get
        Set(ByVal value As Color)
            _shapeColor = value
        End Set
    End Property

End Class

So while I was building this class I was testing it and the biggest problem I had was generating random numbers easily that were consistantly random. So another class to the rescue.

Public Class rRandonClass

    Public Shared _seed As Integer = My.Computer.Clock.TickCount
    Public Shared _r As New Random(_seed)

    Shared Sub New()

        _r.Next()

    End Sub

    Public Shared Function NextRandom(ByVal min As Integer, ByVal max As Integer) As Integer
        Return _r.Next(min, max)
    End Function

End Class

Maybe not be the best way to do things but it works. Since I'm using SHARED members in my class, I don't need to make a NEW object out of the class. You just call it with its full name. Since my game was called FallingGame, you refer to the rRandomClass like this:

_rotation = FallingGame.rRandonClass.NextRandom(0, 40) - 20

_rotation should be somewhere between -20 and 19

So back to the FObj

In the FallingObj Class one of the more important methods is NEW(). And to make it easier to create objects, you overload the method by creating multiple NEW()'s by changing the number of parameters it needs. Example of the first NEW:

Public Sub New()
        'No parameters, it's all random when you don't care about any of the properties.

        _location.X = FallingGame.rRandonClass.NextRandom(10, 800) 
        _location.Y = FallingGame.rRandonClass.NextRandom(100, 200) * -1
        _speed = FallingGame.rRandonClass.NextRandom(1, 10)
        _rotation = FallingGame.rRandonClass.NextRandom(0, 40) - 20
        _shape = FallingGame.rRandonClass.NextRandom(1, 3)
        _size = FallingGame.rRandonClass.NextRandom(1, 5)
        _shapeColor = Color.FromArgb(255, FallingGame.rRandonClass.NextRandom(128, 255), FallingGame.rRandonClass.NextRandom(128, 255), FallingGame.rRandonClass.NextRandom(128, 255))

    End Sub

The next overloaded New is for when you know what size and speed you want your fObj to be. Something like:

Public Sub New(ByVal objSpeed As Integer, ByVal objSize As Integer)

        If objSize < 1 Then
            objSize = 1
        End If
        _location.X = FallingGame.rRandonClass.NextRandom(10, 800) '
        _location.Y = -1 * FallingGame.rRandonClass.NextRandom(100, 200)
        _speed = objSpeed
        _rotation = FallingGame.rRandonClass.NextRandom(0, 40) - 20
        _shape = FallingGame.rRandonClass.NextRandom(1, 3)
        _size = objSize
        _shapeColor = Color.FromArgb(255, FallingGame.rRandonClass.NextRandom(128, 255) - 50 + _size * 6, FallingGame.rRandonClass.NextRandom(128, 255) - 50 + _size * 6, FallingGame.rRandonClass.NextRandom(128, 255) - 50 + _size * 6)

    End Sub

The last overloaded New() is for when you want much more control over the FObj's properties:

Public Sub New(ByVal ObjColor As Color, ByVal objShape As ShapeTypes, ByVal objSpeed As Integer, ByVal objRotation As Integer, ByVal objSize As Integer)

        If objSize < 1 Then
            objSize = 1
        End If
        _location.X = FallingGame.rRandonClass.NextRandom(10, 800) 
        _location.Y = -100
        _shapeColor = ObjColor
        _shape = objShape
        _speed = objSpeed
        _size = objSize
        _rotation = objRotation


    End Sub

That's it for the fObj.

I'll post this now since the length of this post is getting kinda long and I gotta take the dog for a walk. I'll post the rest in an hour or two.

OK. On to the form which is unimaginatively called Form1 and I added a small picture picture box in the lower right hand corner with a picture that reads "START". Also, I added a timer control to the form called gameTimer. The biggest problem with graphics is the flickering so I draw all the shapes on to a bitmap and then draw the bitmap on to the form.

The timer is set to disabled at the beginning and its interval is set to 100.

So first off... the imports...

above Public Class Form1 place the following statement:

Imports System.Drawing.Drawing2D

Now the fields, place these statements just after Public Class Form1:

Private FallingObjects As New Collection
    Private gameTick As Int32
    Private gameLevel As Integer
    Private m_BufferBitmap As Bitmap
    Private m_BufferGraphics As Graphics
    Private m_Graphics As Graphics
    Private m_Xmax As Integer
    Private m_Ymax As Integer

Now the Form Load. I maximized the window, turn on Double Buffering, create some Graphics and a Bitmap. Also note, I create 20 new FObj:

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ' Save the screen width and height.
        Me.WindowState = FormWindowState.Maximized
        Me.DoubleBuffered = True

        m_Xmax = Me.Width
        m_Ymax = Me.Height

        ' Make a buffer Bitmap and Graphics.
        m_BufferBitmap = New Bitmap(m_Xmax, m_Ymax)
        m_BufferGraphics = Graphics.FromImage(m_BufferBitmap)

        ' Create a Graphics object for the form.
        m_Graphics = CreateGraphics()

        Dim i As Integer


        For i = 1 To 20
            Dim obj As New FallingObj()
            FallingObjects.Add(obj, i.ToString)
        Next
        'Me.DoubleBuffered = True
        Dim l As Integer = -1000 Mod 360

        m_BufferGraphics.Clear(Color.Black)
        Me.KeyPreview = True
End Sub

Then you need a sub to start the game and handle some keystroke and mouse events:

Private Sub StartGame()
        'start the game
        gameTimer.Enabled = True
        PictureBox1.Visible = False
        gameTick = 0
        gameLevel = 1
        Cursor.Hide()

    End Sub
    Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click

        StartGame()

    End Sub

    Private Sub Form1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.DoubleClick
        Dim step2 As New FallingObj(5, FallingGame.rRandonClass.NextRandom(1, 6))
        FallingObjects.Add(step2, FallingObjects.Count + 1)
    End Sub

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        If e.KeyCode = Keys.Enter Then
            'Start the game by pressing ENTER
            If Not gameTimer.Enabled Then
                StartGame()

            End If
        End If
        'Quit the game by pressing ESC
        If e.KeyCode = Keys.Escape Then
            Application.exit
        End If
    End Sub

And lastly the timer event and the form paint event.

Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint

        m_Graphics.DrawImage(m_BufferBitmap, 0, 0)

    End Sub



    Private Sub gameTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles gameTimer.Tick
        m_BufferGraphics.Clear(Color.Black)


        Dim i As Integer
        gameTick += 1

        For Each obj As FallingObj In FallingObjects
            i += 1

            If obj.y + obj.Speed > m_Ymax + 100 Then
                obj.Location = New Point(FallingGame.rRandonClass.NextRandom(50, m_Xmax - 50), -1 * FallingGame.rRandonClass.NextRandom(100, 200))
                obj.Speed += FallingGame.rRandonClass.NextRandom(0, 10)
                If obj.Speed > 15 Then
                    obj.Speed = FallingGame.rRandonClass.NextRandom(1, 5)
                    Dim step2 As New FallingObj()
                    FallingObjects.Add(step2, FallingObjects.Count + 1)

                End If
            Else
                obj.Location = New Point(obj.X, obj.Speed + obj.y)
            End If
            Dim objBrush As New LinearGradientBrush(New PointF(obj.X - 10, obj.y - 10), New Point(obj.X + 50 + obj.Size * 8, obj.y + 50 + obj.Size * 8), Color.Black, obj.ShapeColor)

            Select Case obj.Shape
                Case ShapeTypes.FallingCircle
                    m_BufferGraphics.FillEllipse(objBrush, obj.X, obj.y, 20 + obj.Size * 8, 20 + obj.Size * 8)


                Case ShapeTypes.FallingSquare
                    m_BufferGraphics.FillRectangle(objBrush, obj.X, obj.y, 20 + obj.Size * 8, 20 + obj.Size * 8)




            End Select

        Next
        Dim points As Point() = {New Point(Cursor.Position.X - 10, Cursor.Position.Y - 10), New Point(Cursor.Position.X + 10, Cursor.Position.Y + 10), New Point(Cursor.Position.X - 10, Cursor.Position.Y + 10), New Point(Cursor.Position.X + 10, Cursor.Position.Y - 10), New Point(Cursor.Position.X - 10, Cursor.Position.Y - 10)}


        m_BufferGraphics.FillPolygon(New SolidBrush(Color.Yellow), points)

        m_Graphics.DrawImage(m_BufferBitmap, 0, 0)
        If FallingObjects.Count > 250 Or gameTick Mod 60000 = 0 Then
            FallingObjects.Clear()
            Dim newObj As New FallingObj(5, FallingGame.rRandonClass.NextRandom(1, 6))
            FallingObjects.Add(newObj, "1")

        End If



    End Sub

There are your falling objects. No idea how to handle collisions.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.