11-21-2025, 03:59 PM
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
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

