Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
BumpBall - A little ball bumping game
#1
I put a few existing program pieces together yesterday to make a little ball bumping game.  It's an easy game, you use arrows to bump your ball into the enemy ball - the goal is to knock your enemy to the screen edges.  The enemy tries to do the same to you.  Hitting the screen edges costs a life.  You both have three lives.  To make it more interesting, a few dummy balls bounce around in your way.

Use the arrow keys to move your ball.  ESC quits.

- Dav

Code: (Select All)
'============
'BumpBall.bas
'============
'A tiny ball bumping game. Coded by Dav, NOV/2025.
'Try to bump the enemy ball into the edge of screen.

'Bump into enemy ball, make it hit the screen edges.
'Enemy ball will charge at you to make you hit egde.
'If you or enemy hits the edge a life will be lost.
'You and the enemy have 3 lives.  You will win if you
'make enemy lose all 3 lives before you do.

'The bouncing balls can help you -- or be a problem.
'Don't let balls bounce you into the edge either.

'Use the arrow keys to move your bump ball.
'ESC quits.


Dim Shared soundon: soundon = 1 'sound on, use 0 for none.

'=== set screen to use
Randomize Timer
Screen _NewImage(1024, 768, 32)
_FullScreen _SquarePixels

'======
NEWGAME:
'=======

'=== init player/enemy specs
playerx = _Width / 2: playery = _Height / 2
playersize = Int(_Height / 20): playervx = 0: playervy = 0
enemyx = Int(_Width / 4): enemyy = Int(_Height / 4): enemysize = Int(_Height / 25)
enemyvx = Rnd * 4 - 2: enemyvy = Rnd * 4 - 2
playerlives = 3: enemylives = 3

'=== init space dust
dustmax = 600: dustcount = 0
ReDim dustx(dustmax), dusty(dustmax), dustxv(dustmax), dustyv(dustmax)
ReDim dustr(dustmax), dusta(dustmax)

'=== init bouncing balls
ballsmax = 5 'num of bouncing balls
ReDim ballx(ballsmax), bally(ballsmax)
ReDim ballvx(ballsmax), ballvy(ballsmax)
ReDim ballsize(ballsmax)
For i = 1 To ballsmax
    ballsize(i) = Int(_Height / 30) + 10
    ballx(i) = Rnd * (_Width - 2 * ballsize(i)) + ballsize(i)
    bally(i) = Rnd * (_Height - 2 * ballsize(i)) + ballsize(i)
    ballvx(i) = Rnd * 4 - 2: ballvy(i) = Rnd * 4 - 2
Next


'=== main game loop ===

Do

    'clear screen with some alpha
    Line (0, 0)-(_Width, _Height), _RGBA(16, 16, 64, 125), BF

    ax = 0: ay = 0: down = 0 'keypress flags
    If _KeyDown(19200) Then down = 1: ax = ax - .3 'left arrow
    If _KeyDown(19712) Then down = 1: ax = ax + .3 'right arrow
    If _KeyDown(18432) Then down = 1: ay = ay - .3 'up arrow
    If _KeyDown(20480) Then down = 1: ay = ay + .3 'down arrow
    If _KeyDown(27) Then Exit Do 'ESC quits

    '=== update player movement
    playerx = playerx + playervx
    playery = playery + playervy

    playervx = playervx + ax
    playervy = playervy + ay

    '=== apply some friction to players velocity
    If playervx > 0 Then
        playervx = playervx - .06
    Else
        If playervx < 0 Then playervx = playervx + .06
    End If
    If playervy > 0 Then
        playervy = playervy - .06
    Else
        If playervy < 0 Then playervy = playervy + .06
    End If

    '== limit players maximum speed
    If playervx > 8 Then playervx = 8
    If playervx < -8 Then playervx = -8
    If playervy > 8 Then playervy = 8
    If playervy < -8 Then playervy = -8

    '=== If player hits edges
    If playerx - playersize < 0 Then
        playerx = playersize
        playervx = -playervx * .6
        playerlives = playerlives - 1
        If soundon = 1 Then Sound 1000, .1
        Line (0, 0)-(playersize / 3, _Height), _RGB(100, 0, 0), BF
    ElseIf playerx + playersize > _Width Then
        playerx = _Width - playersize
        playervx = -playervx * .6
        playerlives = playerlives - 1
        If soundon = 1 Then Sound 1000, .1
        Line (_Width - playersize / 3, 0)-(_Width, _Height), _RGB(100, 0, 0), BF
    End If
    If playery - playersize < 0 Then
        playery = playersize
        playervy = -playervy * .6
        playerlives = playerlives - 1
        If soundon = 1 Then Sound 1000, .1
        Line (0, 0)-(_Width, playersize / 3), _RGB(100, 0, 0), BF
    ElseIf playery + playersize > _Height Then
        playery = _Height - playersize
        playervy = -playervy * .6
        playerlives = playerlives - 1
        If soundon = 1 Then Sound 1000, .1
        Line (0, _Height - (playersize / 3))-(_Width, _Height), _RGB(100, 0, 0), BF
    End If

    '=== make space dust when moving player
    If ax <> 0 Or ay <> 0 Then
        For ex = 1 To playersize
            If dustcount < dustmax Then
                dustcount = dustcount + 1
                dustx(dustcount) = playerx
                dusty(dustcount) = playery
                dustxv(dustcount) = Rnd * 5 - 2.5
                dustyv(dustcount) = Rnd * 5 - 2.5
                dustr(dustcount) = Int(Rnd * 2) + 1
                dusta(dustcount) = Rnd * 255
            End If
        Next
    End If

    '=== handle active space dust particles
    If dustcount > 0 Then
        For i = 1 To dustcount
            dustyv(i) = dustyv(i) + .05
            dustx(i) = dustx(i) + dustxv(i)
            dusty(i) = dusty(i) + dustyv(i)
            If dusta(i) > 0 Then
                Line (dustx(i), dusty(i))-Step(dustr(i) * 2, dustr(i) * 2), _RGBA(Rnd * 25 + 100, Rnd * 25 + 100, Rnd * 155 + 100, dusta(i)), BF
                dusta(i) = dusta(i) - (playersize / 12)
            End If
        Next
        '=== remove fully faded dust particles
        For i = 1 To dustcount
            If dusta(i) <= 0 Then
                For j = i To dustcount - 1
                    dustx(j) = dustx(j + 1)
                    dusty(j) = dusty(j + 1)
                    dustxv(j) = dustxv(j + 1)
                    dustyv(j) = dustyv(j + 1)
                    dustr(j) = dustr(j + 1)
                    dusta(j) = dusta(j + 1)
                Next
                dustcount = dustcount - 1
            End If
        Next
    End If

    '=== draw player
    DrawBall playerx, playery, playersize, 255, 125, 255, 255
    '=== players nose pointing in moving direction
    If down = 1 Then angle = _Atan2(playervy, playervx)
    nosesize = Int(playersize / 4)
    noseX = playerx + (playersize + nosesize) * Cos(angle)
    noseY = playery + (playersize + nosesize) * Sin(angle)
    '=== draw players nose
    DrawBall noseX, noseY, nosesize, 255, 0, 0, 255


    '=== update bouncing balls
    For i = 1 To ballsmax
        '=== update position
        ballx(i) = ballx(i) + ballvx(i)
        bally(i) = bally(i) + ballvy(i)
        '=== bounce off edges
        If ballx(i) - ballsize(i) < 0 Then
            ballx(i) = ballsize(i)
            ballvx(i) = -ballvx(i)
        ElseIf ballx(i) + ballsize(i) > _Width Then
            ballx(i) = _Width - ballsize(i)
            ballvx(i) = -ballvx(i)
        End If
        If bally(i) - ballsize(i) < 0 Then
            bally(i) = ballsize(i)
            ballvy(i) = -ballvy(i)
        ElseIf bally(i) + ballsize(i) > _Height Then
            bally(i) = _Height - ballsize(i)
            ballvy(i) = -ballvy(i)
        End If
    Next

    '=== handle bouncing balls collision with each other
    For i = 1 To ballsmax - 1
        For j = i + 1 To ballsmax
            dx = ballx(j) - ballx(i)
            dy = bally(j) - bally(i)
            disq = dx * dx + dy * dy
            radsum = ballsize(i) + ballsize(j)
            '=== if balls collide...
            If disq < radsum * radsum Then
                dis = Abs(Sqr(disq))
                fx = dx / dis: fy = dy / dis
                Swap ballvx(i), ballvx(j)
                Swap ballvy(i), ballvy(j)
                If ballvx(i) > 8 Then ballvx(i) = 8
                If ballvx(i) < -8 Then ballvx(i) = -8
                If ballvy(i) > 8 Then ballvy(i) = 8
                If ballvy(i) < -8 Then ballvy(i) = -8
                If ballvx(j) > 8 Then ballvx(j) = 8
                If ballvx(j) < -8 Then ballvx(j) = -8
                If ballvy(j) > 8 Then ballvy(j) = 8
                If ballvy(j) < -8 Then ballvy(j) = -8
                overlap = .5 * (dis - radsum)
                fx = dx / dis: fy = dy / dis
                ballx(i) = ballx(i) + fx * overlap
                bally(i) = bally(i) + fy * overlap
                ballx(j) = ballx(j) - fx * overlap
                bally(j) = bally(j) - fy * overlap
            End If
        Next
    Next

    '=== handle players collision with bouncing balls
    For i = 1 To ballsmax
        dx = ballx(i) - playerx
        dy = bally(i) - playery
        disq = dx * dx + dy * dy
        radsum = ballsize(i) + playersize
        '=== if player hits ball
        If disq < radsum * radsum Then
            dis = Abs(Sqr(disq))
            fx = dx / dis: fy = dy / dis
            Swap playervx, ballvx(i)
            Swap playervy, ballvy(i)
            If playervx > 8 Then playervx = 8
            If playervx < -8 Then playervx = -8
            If playervy > 8 Then playervy = 8
            If playervy < -8 Then playervy = -8
            overlap = .5 * (dis - radsum)
            fx = dx / dis: fy = dy / dis
            playerx = playerx + fx * overlap
            playery = playery + fy * overlap
            ballx(i) = ballx(i) - fx * overlap
            bally(i) = bally(i) - fy * overlap
        End If
    Next

    '=== make enemy chase/accelerate towards player
    dx = playerx - enemyx
    dy = playery - enemyy
    dis = Sqr(dx * dx + dy * dy)
    If dis > 1 Then
        fx = dx / dis: fy = dy / dis
        enemyvx = enemyvx + fx * .1 'how strong enemy move
        enemyvy = enemyvy + fy * .1
    End If
    'apply some friction too
    enemyvx = enemyvx * .98
    enemyvy = enemyvy * .98

    '=== do a periodic faster enemy charge to player
    enemycharge = enemycharge + 1
    If enemycharge >= 300 Then
        enemycharge = 0: enemychargecount = 0
    End If

    '=== apply the enemy charge if in counter
    If enemychargecount < 30 Then
        dx = playerx - enemyx
        dy = playery - enemyy
        dis = Sqr(dx * dx + dy * dy)
        If dis > 1 Then
            fx = dx / dis: fy = dy / dis
            enemyvx = enemyvx + fx * .2 'charge strength
            enemyvy = enemyvy + fy * .2
        End If
        enemychargecount = enemychargecount + 1
    End If

    '=== move enemy
    enemyx = enemyx + enemyvx
    enemyy = enemyy + enemyvy

    '=== if enemy hits edge of screen
    If enemyx - enemysize < 0 Then
        enemyx = enemysize
        enemyvx = -enemyvx
        enemylives = enemylives - 1
        If soundon = 1 Then Sound 1000, .1
        Line (0, 0)-(playersize / 3, _Height), _RGB(0, 100, 0), BF
    ElseIf enemyx + enemysize > _Width Then
        enemyx = _Width - enemysize
        enemyvx = -enemyvx
        enemylives = enemylives - 1
        If soundon = 1 Then Sound 1000, .1
        Line (_Width - playersize / 3, 0)-(_Width, _Height), _RGB(0, 100, 0), BF
    End If
    If enemyy - enemysize < 0 Then
        enemyy = enemysize
        enemyvy = -enemyvy
        enemylives = enemylives - 1
        If soundon = 1 Then Sound 1000, .1
        Line (0, 0)-(_Width, playersize / 3), _RGB(0, 100, 0), BF
    ElseIf enemyy + enemysize > _Height Then
        enemyy = _Height - enemysize
        enemyvy = -enemyvy
        enemylives = enemylives - 1
        If soundon = 1 Then Sound 1000, .1
        Line (0, _Height - (playersize / 3))-(_Width, _Height), _RGB(0, 100, 0), BF
    End If


    '=== draw enemy
    DrawBall enemyx, enemyy, enemysize, 255, 255, 0, 255
    'draw enemy nose based on direction moving
    If enemyvx <> 0 Or enemyvy <> 0 Then enemyangle = _Atan2(enemyvy, enemyvx)
    enemynosesize = Int(enemysize / 4)
    enemynosex = enemyx + (enemysize + enemynosesize) * Cos(enemyangle)
    enemynosey = enemyy + (enemysize + enemynosesize) * Sin(enemyangle)
    DrawBall enemynosex, enemynosey, enemynosesize, 255, 0, 0, 255 ' Nose for direction


    '=== handle collision with player and enemy
    dx = playerx - enemyx: dy = playery - enemyy
    disq = dx * dx + dy * dy
    radsum = playersize + enemysize
    'if they hit
    If disq < radsum * radsum Then
        If soundon = 1 Then Sound 200, .2
        dis = Abs(Sqr(disq))
        fx = dx / dis: fy = dy / dis
        rvx = playervx - enemyvx
        rvy = playervy - enemyvy
        velnorm = rvx * fx + rvy * fy
        'if they are moving towards each other...
        If velnorm < 0 Then
            playervx = playervx + ((-1.8 * velnorm) * fx)
            playervy = playervy + ((-1.8 * velnorm) * fy)
            enemyvx = enemyvx - ((-1.8 * velnorm) * fx)
            enemyvy = enemyvy - ((-1.8 * velnorm) * fy)
            'limit velocity
            If playervx > 8 Then playervx = 8
            If playervx < -8 Then playervx = -8
            If playervy > 8 Then playervy = 8
            If playervy < -8 Then playervy = -8
            If enemyvx > 8 Then enemyvx = 8
            If enemyvx < -8 Then enemyvx = -8
            If enemyvy > 8 Then enemyvy = 8
            If enemyvy < -8 Then enemyvy = -8
            overlap = .5 * (dis - radsum)
            fx = dx / dis: fy = dy / dis
            playerx = playerx - fx * overlap
            playery = playery - fy * overlap
            enemyx = enemyx + fx * overlap
            enemyy = enemyy + fy * overlap
        End If
    End If

    '=== handle collision between enemy and bouncing balls
    For i = 1 To ballsmax
        dx = ballx(i) - enemyx: dy = bally(i) - enemyy
        disq = dx * dx + dy * dy
        radsum = ballsize(i) + enemysize
        'if they hit...
        If disq < radsum * radsum Then
            dis = Abs(Sqr(disq))
            fx = dx / dis: fy = dy / dis
            rvx = ballvx(i) - enemyvx
            rvy = ballvy(i) - enemyvy
            velnorm = rvx * fx + rvy * fy
            'only if moving towards each other
            If velnorm < 0 Then
                enemyvx = enemyvx - ((-(1.8) * velnorm) * fx)
                enemyvy = enemyvy - ((-(1.8) * velnorm) * fy)
                ballvx(i) = ballvx(i) + ((-(1.8) * velnorm) * fx)
                ballvy(i) = ballvy(i) + ((-(1.8) * velnorm) * fy)
                'limit velocity
                If enemyvx > 8 Then enemyvx = 8
                If enemyvx < -8 Then enemyvx = -8
                If enemyvy > 8 Then enemyvy = 8
                If enemyvy < -8 Then enemyvy = -8
                If ballvx(i) > 8 Then ballvx(i) = 8
                If ballvx(i) < -8 Then ballvx(i) = -8
                If ballvy(i) > 8 Then ballvy(i) = 8
                If ballvy(i) < -8 Then ballvy(i) = -8
                overlap = .5 * (dis - radsum)
                fx = dx / dis: fy = dy / dis
                enemyx = enemyx + fx * overlap
                enemyy = enemyy + fy * overlap
                ballx(i) = ballx(i) - fx * overlap
                bally(i) = bally(i) - fy * overlap
            End If
        End If
    Next

    '=== draw all bouncing balls
    For i = 1 To ballsmax
        DrawBall ballx(i), bally(i), ballsize(i), 125, 125, 255, 255
    Next

    '=== draw player lives
    px = playersize: py = playersize
    For t = 1 To playerlives
        DrawBall px, py, Int(playersize / 3), 255, 125, 255, 100
        px = px + playersize
    Next

    '=== draw enemy lives
    px = _Width - (playersize * enemylives): py = playersize
    For t = 1 To enemylives
        DrawBall px, py, Int(playersize / 3), 255, 255, 0, 100
        px = px + playersize
    Next

    If enemylives = 0 Then WinGame: GoTo NEWGAME
    If playerlives = 0 Then LoseGame: GoTo NEWGAME

    _Limit 60
    _Display

Loop

End


Sub DrawBall (cx, cy, rad, r, g, b, a)
    rad2 = rad * rad
    For y = -rad To rad
        x = Abs(Sqr(rad2 - y * y))
        For i = -x To x
            d = Sqr(i * i + y * y) / rad
            r2 = r * (1 - d) + (r / 2) * d
            g2 = g * (1 - d) + (g / 2) * d
            b2 = b * (1 - d) + (b / 2) * d
            Line (cx + i, cy + y)-(cx + i, cy + y), _RGBA(r2, g2, b2, a), BF
        Next
    Next
End Sub

Sub WinGame
    'Play fanfare
    If soundon = 1 Then Play "mb l8 o3e,g,o4c o3g,o4c,e c,e,g e,g,o5c"
    Line (0, 0)-(_Width, _Height), _RGBA(0, 255, 0, 30), BF
    s = Int(_Width / 40): cw = _Width / 2: ch = _Height / 2
    PPRINT cw - (s * 5), ch - s, s, _RGB(255, 255, 255), 0, "YOU WON!"
    _Display
    _Delay 3
End Sub

Sub LoseGame
    If soundon = 1 Then Play "mb l16 o2 c,f f,b c,f f,b c,f"
    Line (0, 0)-(_Width, _Height), _RGBA(255, 0, 0, 30), BF
    s = Int(_Width / 40): cw = _Width / 2: ch = _Height / 2
    PPRINT cw - (s * 5), ch - s, s, _RGB(255, 255, 255), 0, "YOU LOST!"
    _Display
    _Delay 3
End Sub


Sub PPRINT (x, y, size, clr&, trans&, text$)
    orig& = _Dest
    bit = 32: If _PixelSize(0) = 1 Then bit = 256
    For t = 0 To Len(text$) - 1
        pprintimg& = _NewImage(16, 16, bit)
        _Dest pprintimg&
        Cls , trans&: Color clr&
        Print Mid$(text$, t + 1, 1);
        _ClearColor _RGB(0, 0, 0), pprintimg&
        _Dest orig&
        x1 = x + (t * size): x2 = x1 + size
        y1 = y: y2 = y + size
        _PutImage (x1 - (size / 2), y1)-(x2, y2 + (size / 3)), pprintimg&
        _FreeImage pprintimg&
    Next
End Sub

Find my programs here in Dav's QB64 Corner
Reply


Messages In This Thread
BumpBall - A little ball bumping game - by Dav - 11-21-2025, 03:59 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Bumper ball game (like plinko). Dav 3 965 09-05-2024, 10:33 PM
Last Post: bplus
  Find the ball - classic shell game Dav 2 1,006 06-01-2024, 05:37 PM
Last Post: bplus

Forum Jump:


Users browsing this thread: 1 Guest(s)