11-23-2025, 01:32 AM
Here's the shooting version. A little more fun maybe. Shooting the enemy ball will stun it for a couple seconds so you can bump it. Enemy can shoot at you too. I changed the ball sizes to make it more playable. Added more health (7) before game over. Was going to add more stuff before posting this, but with the holiday coming up I doubt I'll be working on this for a while, so decided to post it now. Need to work on colors, overall appeal, real sound effects, other goals or objects, organize code better, blah blah blah...
- Dav
- Dav
Code: (Select All)
'=============
'BumpBall2.bas
'=============
'A tiny ball bumping game. Coded by Dav, NOV/2025.
'Try to bump the enemy ball into the edge of screen.
'New for version 2:
'Added: player/enemy shoots stun bullets (SPACE shoots)
' when hit, player or enemy is stunned for 2 secs.
' balls will be flahing while stunned.
'fixed: changed ball sizes to smaller (was too cramped)
'Fixed: increased lives to 7 now (game was too short)
'Fixed: made enemy ball same as player
'==========
'ABOUT GAME
'==========
'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.
'Shoot enemy to temporarily stun it for 2 secs.
'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.
'Use SPACE bar to shoot your stun bullets.
'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 / 25): 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 = 7: enemylives = 7: enemystun = 0: playerstun = 0
playerstuncount = 0: enemystuncount = 0
'=== 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 / 35) + 5
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
playershotmax = 20: playershotwait = 0
ReDim playershotx(playershotmax), playershoty(playershotmax)
ReDim playershotvx(playershotmax), playershotvy(playershotmax)
ReDim playershota(playershotmax)
For i = 1 To playershotmax
playershota(i) = 0
Next
enemyshotmax = 20: enemyshottimer = 0
ReDim enemyshotx(enemyshotmax), enemyshoty(enemyshotmax)
ReDim enemyshotvx(enemyshotmax), enemyshotvy(enemyshotmax)
ReDim enemyshota(enemyshotmax)
For i = 1 To enemyshotmax
enemyshota(i) = 0
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 playerstun = 0 Then
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
End If
If _KeyDown(27) Then Exit Do 'ESC quits
'=== update player movement
playerx = playerx + playervx
playery = playery + playervy
If playerstun = 0 Then
playervx = playervx + ax
playervy = playervy + ay
End If
'=== 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
If playerstun = 1 Then
DrawBall playerx, playery, playersize, Rnd * 255, 125, Rnd * 255, 255
Else
DrawBall playerx, playery, playersize, 255, 125, 255, 255
End If
'=== 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
If enemystun = 0 Then
'=== 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
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
If enemystun = 0 Then
DrawBall enemyx, enemyy, enemysize, 255, 255, 0, 255
Else
DrawBall enemyx, enemyy, enemysize, Rnd * 255, Rnd * 255, 0, 255
End If
'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
'=== handle player shooting (if not stunned)
If playerstun = 0 Then
If _KeyDown(32) And playershotwait = 0 Then 'space bar
For i = 1 To playershotmax
If playershota(i) = 0 Then
playershotx(i) = noseX
playershoty(i) = noseY
playershotvx(i) = 10 * Cos(angle)
playershotvy(i) = 10 * Sin(angle)
playershota(i) = 1
Exit For
End If
Next
playershotwait = 15 'wait this long to shoot again
End If
End If
'=== update player shot wait count
If playershotwait > 0 Then playershotwait = playershotwait - 1
'=== handle enemy shooting
enemyshottimer = enemyshottimer + 1
If enemystun = 0 Then
If enemyshottimer >= 120 Then 'shoots every 2 secs (60*2)
For i = 1 To enemyshotmax
If enemyshota(i) = 0 Then
enemyshotx(i) = enemynosex
enemyshoty(i) = enemynosey
enemyshotvx(i) = 8 * Cos(enemyangle)
enemyshotvy(i) = 8 * Sin(enemyangle)
enemyshota(i) = 1
Exit For
End If
Next
enemyshottimer = 0
End If
End If
'=== update player shots
For i = 1 To playershotmax
If playershota(i) = 1 Then
playershotx(i) = playershotx(i) + playershotvx(i)
playershoty(i) = playershoty(i) + playershotvy(i)
If playershotx(i) < 0 Or playershotx(i) > _Width Or playershoty(i) < 0 Or playershoty(i) > _Height Then playershota(i) = 0
End If
Next
'=== update enemy shots
For i = 1 To enemyshotmax
If enemyshota(i) = 1 Then
enemyshotx(i) = enemyshotx(i) + enemyshotvx(i)
enemyshoty(i) = enemyshoty(i) + enemyshotvy(i)
If enemyshotx(i) < 0 Or enemyshotx(i) > _Width Or enemyshoty(i) < 0 Or enemyshoty(i) > _Height Then enemyshota(i) = 0
End If
Next
'=== handle collision of player shots hitting enemy
For i = 1 To playershotmax
If playershota(i) = 1 Then
dx = playershotx(i) - enemyx
dy = playershoty(i) - enemyy
disq = dx * dx + dy * dy
radsum = enemysize
If disq < radsum * radsum Then
playershota(i) = 0
enemystun = 1: enemyvx = 1: enemyvy = 1
If soundon = 1 Then Sound 2000, .2
End If
End If
Next
'=== handle collision of enemy shots hitting player
For i = 1 To enemyshotmax
If enemyshota(i) = 1 Then
dx = enemyshotx(i) - playerx
dy = enemyshoty(i) - playery
disq = dx * dx + dy * dy
If disq < playersize * playersize Then
enemyshota(i) = 0
playerstun = 1: playervx = 1: playervy = 1
If soundon = 1 Then Sound 2000, .2
End If
End If
Next
'=== draw/update player shots
For i = 1 To playershotmax
If playershota(i) = 1 Then
DrawBall playershotx(i), playershoty(i), Int(playersize / 4), 255, 255, 255, 255
End If
Next
'=== draw/update enemy shots
For i = 1 To enemyshotmax
If enemyshota(i) = 1 Then
DrawBall enemyshotx(i), enemyshoty(i), Int(enemysize / 4), 255, 50, 50, 255
End If
Next
'=== check/handle playerstun status
If playerstun = 1 Then
playerstuncount = playerstuncount + 1
If playerstuncount > 120 Then
playerstuncount = 0
playerstun = 0
End If
End If
'=== check/handle enemystun status
If enemystun = 1 Then
enemystuncount = enemystuncount + 1
If enemystuncount > 120 Then
enemystuncount = 0
enemystun = 0
End If
End If
'=== 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 7
If t <= playerlives Then
DrawBall px, py, Int(playersize / 3), 255, 125, 255, 150
Else
DrawBall px, py, Int(playersize / 3), 255, 125, 255, 30
End If
px = px + playersize
Next
'=== draw enemy lives
px = _Width - (playersize * 7): py = playersize
For t = 7 To 1 Step -1
If t <= enemylives Then
DrawBall px, py, Int(enemysize / 3), 255, 255, 0, 150
Else
DrawBall px, py, Int(enemysize / 3), 255, 255, 0, 30
End If
px = px + enemysize
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

