Search code examples
vb.netgraphicscollision-detection

Detect collision between a graphics object and picture object in Visual Basic


I am making a lunar lander game that randomizes the terrain for each new game, so each game is different. For my game, I am creating a graphics object that draws a closed curve for the terrain of the game. I am trying to then detect if a picture object collides with the graphics object. I create the graphics object like so:

    Private Sub generateRandomTerrain()
    Dim terrainBrush As New SolidBrush(Color.Gray)
    Dim terrainDraw As Graphics = Me.CreateGraphics

    'Generate Different Points for Terrain
    Me.xpoint1 = (Rnd() * 10) + (Rnd() * 20) + (Rnd() * 10) - (Rnd() * 20)
    Me.ypoint1 = (Rnd() * 30) + (Rnd() * 10) - (Rnd() * 20) + (Rnd() + 5)

    Me.xpoint2 = (Rnd() * 10) + (Rnd() * 20) + (Rnd() * 10) - (Rnd() * 20)
    Me.ypoint2 = (Rnd() * 30) + (Rnd() * 10) + (Rnd() * 20) + (Rnd() + 5) + (Rnd() * 30) - (Rnd() * 30)

    Me.xpoint3 = (Rnd() * 10) + (Rnd() * 20) + (Rnd() * 10) - (Rnd() * 20)
    Me.ypoint3 = (Rnd() * 30) + (Rnd() * 10) - (Rnd() * 20) + (Rnd() + 5) - (Rnd() * 30) + (Rnd() * 30)

    Me.xpoint4 = (Rnd() * 10) + (Rnd() * 20) + (Rnd() * 10) - (Rnd() * 20)
    Me.ypoint4 = (Rnd() * 30) + (Rnd() * 10) + (Rnd() * 20) + (Rnd() + 5) - (Rnd() * 30) + (Rnd() * 30)

    'Add System to make sure that hills are not too sharp???

    'Generate Points to Draw
    Dim terrain() As Point = {New Point(0, Me.Size.Height), New Point(0, Me.Size.Height - 100), New Point((Me.Size.Width * 0.2) + Me.xpoint1, Me.Size.Height - Me.ypoint1 - 100), New Point((Me.Size.Width * 0.45) + Me.xpoint2, Me.Size.Height - Me.ypoint2 - 100), New Point((Me.Size.Width * 0.75) - Me.xpoint3, Me.Size.Height - 100 - Me.ypoint3), New Point((Me.Size.Width * 0.8) + (Me.Size.Width * 0.05) - Me.xpoint4, Me.Size.Height - Me.ypoint4 - 100), New Point(Me.Size.Width, Me.Size.Height - 100), New Point(Me.Size.Width, Me.Size.Height)}

    'Is Terrain Drawn-Clear
    If Me.isTerrainDrawn = 1 Then
        terrainDraw.Clear(Color.Transparent)
        Me.isTerrainDrawn = 0
    End If

    'Draw Terrain Aspects
    terrainDraw.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
    terrainDraw.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
    terrainDraw.CompositingMode = Drawing2D.CompositingMode.SourceOver

    'Draw Terrain
    terrainDraw.FillClosedCurve(terrainBrush, terrain)

    'Set Terrain to Drawn
    Me.isTerrainDrawn = 1
End Sub

I have tried many ways of doing this, but none of them seem to work.

Thank you.


Solution

  • Create your on path as a spline curve by using the System.Drawing.Drawing2D.GraphicsPath class. You can add the points to the path with the AddClosedCurve method. Then you can test if a point lies within the closed curve with path.IsVisible(point) or path.IsVisible(x, y).

    Finally you can draw the path with terrainDraw.FillPath(brush, path)


    Your code

    Me.xpoint1 = (Rnd() * 10) + (Rnd() * 20) + (Rnd() * 10) - (Rnd() * 20)
    

    could be simplified as

    Me.xpoint1 = 20 * Rnd()
    

    As 10 Rnd + 20 Rnd + 10 Rnd - 20 Rnd == 20 Rnd. You will not get a better random value by adding four random values.


    The Region class is also interesting. It can contain rectangles and graphic paths and has an Intersect method, which returns the intersection of itself and another Region, GraphicsPath or Rectangle. It also has a Complement method that you could use to get the outside of the terrain. If you intersect the outside of the terrain with some graphic object and the result is empty (which you can test with the IsEmpty method), it means that there is no collision.