How do I create a perfect collision system?

Nomestack 61 Reputation points
2021-03-10T21:33:01.213+00:00

I'm making a "game engine" and I need to make a perfect collision system, I tried to make some but it was bad the player kept stopping at the edges and I couldn't move, so I wanted someone to send me a code for the perfect collision it could be with the extensions: litdev or the fremy extension thanks for reading :)

(also, i'm using google translate this is why my english is bad)

Small BASIC
Small BASIC
A programming language created by Microsoft that serves a stepping stone for beginners from block-based coding languages to more complex text-based languages.
277 questions
0 comments No comments
{count} votes

Accepted answer
  1. Scout 541 Reputation points
    2021-03-12T08:18:33.847+00:00

    The Brickwall game is a good example.
    The bricks could be placed in any position and must not be removed if hit.

    'BrickWall
    'A development of the paddle game sample.
    'Revove all the bricks to complete the game.
    ' Game over if you miss the ball.
    'You are penalised -1 each time no bricks are hit.
    'The movement of the ball is influenced by where it hits the paddle.
    'Do not let the bricks reach the bottom of the screen.
    
    GameStart:
    
    'paddle = GraphicsWindow.AddRectangle(120, 12) 'v0.2
    paddle = Shapes.AddRectangle(120, 12) 'v0.3.1
    'ball = GraphicsWindow.AddEllipse(16, 16) 'v0.2
    ball = Shapes.AddEllipse(16,16) 'v0.3.1
    bricksLeft = 48
    brickStartY = 35
    hitCount = 0
    GraphicsWindow.FontSize = 14
    GraphicsWindow.MouseMove = OnMouseMove
    GraphicsWindow.Title = "Brick Wall"
    
    For idx = 0 To 15
      Array.SetValue("GreenBricks", idx, 1)
      Array.SetValue("YellowBricks", idx, 1)
      Array.SetValue("RedBricks", idx, 1)
    Endfor
    DrawBricks()
    score = 0
    PrintScore()
    
    gw = GraphicsWindow.Width
    gh = GraphicsWindow.Height
    y = gh - 28
    'GraphicsWindow.MoveShape(ball, x, y) 'v0.2
    Shapes.Move(ball,x,y) 'v0.3.1
    deltaX = 1
    deltaY = -2
    Sound.PlayBellRingAndWait()
    
    RunLoop:
      x = x + deltaX
      y = y + deltaY
    
      gw = GraphicsWindow.Width
      gh = GraphicsWindow.Height
      If (x >= gw - 16 Or x <= 0) Then
        deltaX = -deltaX
      EndIf
      If (y <= 0) Then
        deltaY = -deltaY
      EndIf
    
     'padX = GraphicsWindow.GetLeftOfShape(paddle) 'v0.2
     padX = Shapes.GetLeft(paddle) 'v0.3.1
      If ((y >= gh - 28 + 2) And x >= padX And x <= padX + 120) Then
        y = gh - 28 + 2
        'Sound.PlayClick()
        hitCount = hitCount + 1
        If Math.Remainder(hitCount, 3) = 0 Then 'Move bricks downwards
          For idx = 0 To 15
            RemoveGreenBrick()
            RemoveYellowBrick()
            RemoveRedBrick()
          Endfor
          brickStartY = brickStartY + 20
          DrawBricks()
        EndIf
        TestRed:
        For idx = 0 To 15
          If Array.GetValue("RedBricks", idx) = 1 Then
            If brickStartY > gh - 160 Then
              Goto EndGame
            EndIf
          EndIf
        EndFor
        TestYellow:
        For idx = 0 To 15
          If Array.GetValue("YellowBricks", idx) = 1 Then
            If brickStartY > gh - 100 Then
              Goto EndGame
            EndIf
          EndIf
        EndFor
        TestGreen:
        For idx = 0 To 15
          If Array.GetValue("GreenBricks", idx) = 1 Then
            If brickStartY > gh - 40 Then
              Goto EndGame
            EndIf
          EndIf
        EndFor
        EndTest:
    
        deltaX = deltaX - 2 + (x - padX) / 30  ' Add some skill
    
        If score = oldScore Then  'No bricks hit
          score = score - 1
        EndIf
        oldScore = score
        PrintScore()
        deltaY = -deltaY  'Change the ball direction
      EndIf
      ' GraphicsWindow.MoveShape(ball, x, y) 'v0.2
      Shapes.Move(ball,x,y) 'v0.3.1
      Program.Delay(15)
    
      ' Green Bricks
      If y > brickStartY - 16 And y < brickStartY + 20 Then  ' y position of brick - diameter of ball
        idx = (x+8) / 40  ' Radius of ball / length of brick
        idx = Math.Floor(idx) ' take integer part
        If Array.GetValue("GreenBricks", idx) = 1 Then
          Array.SetValue("GreenBricks", idx, 0)
          RemoveGreenBrick()
          Sound.PlayChime()
          bricksLeft = bricksLeft - 1
          deltaY = -deltaY  'Change ball direction
          score = score + 15
          PrintScore()
          CheckEnd()
        EndIf
      EndIf
    
      ' Yellow Bricks
      If y > brickStartY + 44 And y < brickStartY + 80 Then  ' y position of brick - diameter of ball = 19
        idx = (x+8) / 40  ' Radius of ball / length of brick
        idx = Math.Floor(idx) ' take integer part
        If Array.GetValue("YellowBricks", idx) = 1 Then
          Array.SetValue("YellowBricks", idx, 0)
          RemoveYellowBrick()
          Sound.PlayChime()
          bricksLeft = bricksLeft - 1
          deltaY = -deltaY  'Change ball direction
          score = score + 10
          PrintScore()
          CheckEnd()
        EndIf
      EndIf
    
      ' Red Bricks
      If y > brickStartY + 104 And y < brickStartY + 140 Then  ' y position of brick - diameter of ball = 19
        idx = (x+8) / 40  ' Radius of ball / length of brick
        idx = Math.Floor(idx) ' take integer part
        If Array.GetValue("RedBricks", idx) = 1 Then
          Array.SetValue("RedBricks", idx, 0)
          RemoveRedBrick()
          Sound.PlayChime()
          bricksLeft = bricksLeft - 1
          deltaY = -deltaY  'Change ball direction
          score = score + 5
          PrintScore()
          CheckEnd()
        EndIf
      EndIf
    
    
      If (y < gh) Then  'Ball not reached bottom of window
        Goto RunLoop
      EndIf
    
    EndGame:
      GraphicsWindow.ShowMessage("Your score is: " + score, "BrickWall")
      Program.End()
    
    Sub OnMouseMove
      paddleX = GraphicsWindow.MouseX
      ' GraphicsWindow.MoveShape(paddle, paddleX - 60, GraphicsWindow.Height - 12) 'v0.2
      Shapes.Move(paddle, paddleX - 60, GraphicsWindow.Height - 12) 'v0.3.1
    EndSub
    
    Sub PrintScore
      ' Clear the score first and then draw the real score text
      GraphicsWindow.BrushColor = "White"
      GraphicsWindow.FillRectangle(10, 10, 200, 20)
      GraphicsWindow.BrushColor = "Black"
      GraphicsWindow.DrawText(10, 10, "Score: " + score)
    EndSub
    
    Sub DrawBricks
      For idx = 0 To 15 ' Draw bricks
        'Program.Delay(100)
        If Array.GetValue("GreenBricks", idx) = 1 Then
          GraphicsWindow.PenColor = "Black"
          GraphicsWindow.BrushColor = "Green"
        Else
          GraphicsWindow.PenColor = "White"
          GraphicsWindow.BrushColor = "White"
        EndIf
        GraphicsWindow.FillRectangle(idx * 40, brickStartY, 40, 20)
        GraphicsWindow.DrawRectangle(idx * 40, brickStartY, 40, 20)
    
        GraphicsWindow.BrushColor = "Yellow"
        If Array.GetValue("YellowBricks", idx) = 1 Then
          GraphicsWindow.PenColor = "Black"
          GraphicsWindow.BrushColor = "Yellow"
        Else
          GraphicsWindow.PenColor = "White"
          GraphicsWindow.BrushColor = "White"
        EndIf
        GraphicsWindow.FillRectangle(idx * 40, brickStartY + 60, 40, 20)
        GraphicsWindow.DrawRectangle(idx * 40, brickStartY + 60, 40, 20)
    
        GraphicsWindow.BrushColor = "Red"
        If Array.GetValue("RedBricks", idx) = 1 Then
          GraphicsWindow.PenColor = "Black"
          GraphicsWindow.BrushColor = "Red"
        Else
          GraphicsWindow.PenColor = "White"
          GraphicsWindow.BrushColor = "White"
        EndIf
        GraphicsWindow.FillRectangle(idx * 40, brickStartY + 120, 40, 20)
        GraphicsWindow.DrawRectangle(idx * 40, brickStartY + 120, 40, 20)
      endfor
    EndSub
    
    Sub RemoveGreenBrick
      GraphicsWindow.PenColor = "White"
      GraphicsWindow.BrushColor = "White"
      GraphicsWindow.FillRectangle(idx * 40, brickStartY, 40, 20)
      GraphicsWindow.DrawRectangle(idx * 40, brickStartY, 40, 20)
    EndSub
    
    Sub RemoveYellowBrick
      GraphicsWindow.PenColor = "White"
      GraphicsWindow.BrushColor = "White"
      GraphicsWindow.FillRectangle(idx * 40, brickStartY + 60, 40, 20)
      GraphicsWindow.DrawRectangle(idx * 40, brickStartY + 60, 40, 20)
    EndSub
    
    Sub RemoveRedBrick
      GraphicsWindow.PenColor = "White"
      GraphicsWindow.BrushColor = "White"
      GraphicsWindow.FillRectangle(idx * 40, brickStartY + 120, 40, 20)
      GraphicsWindow.DrawRectangle(idx * 40, brickStartY + 120, 40, 20)
    EndSub
    
    Sub CheckEnd
     If bricksLeft = 0 Then
       GraphicsWindow.ShowMessage("Well Done. Wall destroyed. Your score is: " + score, "BrickWall")
       'Goto GameStart
       Program.End()
       'Goto EndGame
     EndIf
    EndSub
    

3 additional answers

Sort by: Most helpful
  1. Absolute Beginner 171 Reputation points
    2021-03-11T10:10:23.003+00:00

    (translated by Google translator)

    Hi Nomestack.

    I cannot send you a ready-made code. But if you want, I can make your "game engine" together with you.
    I like Small Basic. But, I'm bored because I can't think of an interesting problem for myself.

    If you want to work together with me, then write to me by mail: prikolnyjkent@Stuff .com

    0 comments No comments

  2. WhTurner 1,611 Reputation points
    2021-03-11T10:36:19.953+00:00

    You can have a look at https://learn.microsoft.com/en-us/answers/questions/229285/ball-mechanism-pong-microsoft-small-basic.html
    There I solved a problem with a bouncing ball which did not detect the border.


  3. Scout 541 Reputation points
    2021-03-11T13:34:39.897+00:00

    There is an in-depth article on TechNet: 20865.small-basic-dynamic-graphics.aspx

    The following example can be downloaded from LitDev - Other Resources - Samples:

    'Example of blobs coalescing - collision detection
    
    'Set up Window
    gw = 1250
    gh = 700
    GraphicsWindow.Width = gw
    GraphicsWindow.Height = gh
    GraphicsWindow.Top = 0
    GraphicsWindow.Left = 0
    GraphicsWindow.Title = "Fusion"
    
    'Initialise atoms
    natom = 20
    rad = 5
    speed = 10
    dt = 0.2
    GraphicsWindow.PenWidth = 1
    GraphicsWindow.PenColor = "#10000000"
    GraphicsWindow.BrushColor = "Red"
    For i = 1 To natom
      X[i] = Math.GetRandomNumber(gw)
      Y[i] = Math.GetRandomNumber(gh)
      U[i] = Math.GetRandomNumber(2*speed)-(1+2*speed)/2
      V[i] = Math.GetRandomNumber(2*speed)-(1+2*speed)/2
      atom[i] = Shapes.AddEllipse(2*rad,2*rad)
      scale[i] = 1
    EndFor
    
    While ("True")
      cpu = Clock.ElapsedMilliseconds
      Update()
      'Even time spacing between updates
      dcpu = 10-(Clock.ElapsedMilliseconds-cpu)
      If (dcpu > 0) Then
        Program.Delay(dcpu)
      EndIf
    EndWhile
    
    Sub Update
      For i = 1 To natom
        If (scale[i] > 0) Then
          For j = i+1 To natom
            If (scale[j] > 0) Then
              dx = X[i]-X[j]
              dy = Y[i]-Y[j]
              dist2 = (dx*dx+dy*dy) ' distance squared
              If (dist2 < 10000) Then ' Only consider nearish neighbours
                If (dist2 < rad*rad*scale[i]*scale[j]) Then
                  'Collision, grow one (i) atom and delete the other (j)
                  scale[i] = Math.SquareRoot(scale[i]*scale[i]+scale[j]*scale[j])
                  Shapes.Zoom(atom[i],scale[i],scale[i])
                  scale[j] = 0
                  Shapes.Remove(atom[j])
                  Sound.PlayClickAndWait()
                Else
                  'dist2 = Math.Power(dist2/100,1.5)
                  'Alter velocity by inverse square - repulsive force between atoms
                  dist2 = dist2/50
                  du = dx/dist2
                  dv = dy/dist2
                  U[i] = U[i]+du
                  V[i] = V[i]+dv
                  U[j] = U[j]-du
                  V[j] = V[j]-dv
                EndIf
              EndIf
            EndIf
          EndFor
          'Update position from velocity
          x1 = X[i]
          y1 = Y[i]
          X[i] = X[i]+U[i]*dt
          Y[i] = Y[i]+V[i]*dt
          If (X[i] < 0) Then
            X[i] = -X[i]
            U[i] = -U[i]
          ElseIf (X[i] > gw) Then
            X[i] = 2*gw-X[i]
            U[i] = -U[i]
          EndIf
          If (Y[i] < 0) Then
            Y[i] = -Y[i]
            V[i] = -V[i]
          ElseIf (Y[i] > gh) Then
            Y[i] = 2*gh-Y[i]
            V[i] = -V[i]
          EndIf
          'Move atom to new position
          Shapes.Move(atom[i],X[i]-rad,Y[i]-rad)
          GraphicsWindow.DrawLine(x1,y1,X[i],Y[i])
        EndIf
      EndFor
    EndSub