Author Topic: Breakout principles (again, maybe)  (Read 773 times)

John

  • Sr. Member
  • ****
  • Posts: 362
    • View Profile
Breakout principles (again, maybe)
« on: May 01, 2015 »
Hello and sorry for being away for so long,

Here is some very basic starter code for a breakout game, wrote it while waiting for Windows to make all its updates on this new computer:

Code: [Select]
rem Breakout principles.

import "Speed.lib"

visible:
rem Bricks.
bricks[20][15]
rem Paddle.
paddleX = 320
paddleY = 400
rem Ball.
ballX# = 0.0
ballY# = 0.0
ballDX# = 0.0
ballDY# = 0.0
ballSpeed = 4
ballCaptured = true

hidden:

rem Turn off automatic redraw.
set redraw off

rem Init bricks.
for y = 0 to 14; for x = 0 to 19
bricks[x][y] = 1
next; next

rem Game loop.
do
rem Update paddle and balls.
proc UpdatePaddle
proc UpdateBall

rem Draw.
set color 0, 0, 0
cls
proc DrawBricks
proc DrawPaddle
proc DrawBall

rem Copy graphics to window and wait.
redraw
_SPD_HoldFrame 60
loop

rem Update paddle.
procedure UpdatePaddle()
paddleX = mousex()
endproc

rem Update ball.
procedure UpdateBall()
rem Is ball captured?
if ballCaptured
rem Set above paddle.
ballX = float(paddleX - 8)
ballY = float(paddleY - 16)
rem Launch?
if mousebutton(0, true)
ballDX# = 0.0
ballDY# = -1.0
ballSpeed = 4
ballCaptured = false
endif
else
rem Move ball ballSpeed times.
for i = 1 to ballSpeed
rem Move.
ballX = ballX + ballDX
ballY = ballY + ballDY

rem Collision with paddle?
dx# = ballX + 8.0 - float(paddleX)
if dx < 48.0 and ballY + 16.0 > float(paddleY) and ballY < float(paddleY) + 16.0
rem Bounce.
ballDY = -1.0
ballDX = dx/24.0
k# = 1.0/sqr(ballDX*ballDX + ballDY*ballDY)
ballDX = ballDX*k
ballDY = ballDY*k
endif

rem Check vertical collisions with bricks.
brickX = int(ballX + 8.0)/32
if brickX >= 0 and brickX < sizeof(bricks, 0)
rem Check brick above ball.
brickY = int(ballY)/16
if brickY < sizeof(bricks, 1) and brickY >= 0 and bricks[brickX][brickY]
bricks[brickX][brickY] = 0
ballDY = abs#(ballDY)
endif
rem Check brick below ball.
brickY = int(ballY + 16.0)/16
if brickY < sizeof(bricks, 1) and brickY >= 0 and bricks[brickX][brickY]
bricks[brickX][brickY] = 0
ballDY = -abs#(ballDY)
endif
endif

rem Check horizontal collisions with bricks.
brickY = int(ballY + 8.0)/16
if brickY >= 0 and brickY < sizeof(bricks, 1)
rem Check brick left of ball.
brickX = int(ballX)/32
if brickX < sizeof(bricks, 0) and brickX >= 0 and bricks[brickX][brickY]
bricks[brickX][brickY] = 0
ballDX = abs#(ballDX)
endif
rem Check brick right of ball.
brickX = int(ballX + 16.0)/32
if brickX < sizeof(bricks, 0) and brickX >= 0 and bricks[brickX][brickY]
bricks[brickX][brickY] = 0
ballDX = -abs#(ballDX)
endif
endif

rem Bounce on walls and ceiling.
if ballX < 0.0
ballDX = abs#(ballDX)
elseif ballX > 624.0
ballDX = -abs#(ballDX)
endif
if ballY < 0.0
ballDY = abs#(ballDY)
rem Ball lost?
elseif ballY > 480.0
ballCaptured = true
endif
next
endif
endproc

rem Draw bricks.
procedure DrawBricks()
set color 192, 192, 192
for y = 0 to 14; for x = 0 to 19
if bricks[x][y] then draw rect x*32 + 1, y*16 + 1, 30, 14, true
next; next
endproc

rem Draw paddle.
procedure DrawPaddle()
set color 128, 128, 128
draw rect paddleX - 48, paddleY, 96, 16, true
endproc

rem Draw ball.
procedure DrawBall()
set color 255, 255, 255
draw rect int(ballX), int(ballY), 16, 16, true
endproc

Marcus

  • Administrator
  • Hero Member
  • *****
  • Posts: 542
    • View Profile
Re: Breakout principles (again, maybe)
« Reply #1 on: June 04, 2016 »
Made some modifications to this one, since I love breakout games. Added support for multiple balls and the player can now shoot bullets to destroy bricks (better be a powerup later on).

Code: [Select]
rem Breakout principles, part 2.
rem
rem Original version by John, continued by Marcus.
rem    2016-06-04: Support for multiple balls (not used yet)
rem                Bullets
rem

import "Speed.lib"

constant:
MAX_BALLS 16
MAX_BULLETS 8

visible:
rem Bricks.
bricks[20][15]
rem Paddle.
paddleX = 320
paddleY = 400
rem Balls.
balls?[MAX_BALLS]
ballCaptured
rem Bullets.
bullets?[MAX_BULLETS]

hidden:

rem Turn off automatic redraw.
set redraw off

rem Init bricks.
for y = 0 to 14; for x = 0 to 19
bricks[x][y] = 1
next; next

proc InitBalls
proc InitBullets

rem Game loop.
do
rem Update paddle and balls.
proc UpdatePaddle
proc UpdateBalls
proc UpdateBullets

if ballCaptured = false and mousebutton(0, true)
proc AddBullet paddleX - 32, paddleY - 16
proc AddBullet paddleX + 32, paddleY - 16
endif

rem Draw.
set color 0, 0, 0
cls
proc DrawBricks
proc DrawPaddle
proc DrawBullets
proc DrawBall

rem Instructions.
set color 255, 255, 255
set caret width(primary)/2, 440
center "Left mouse button: Launch ball, shoot bullets"

rem Copy graphics to window and wait.
redraw
_SPD_HoldFrame 60
loop

rem Update paddle.
procedure UpdatePaddle()
paddleX = mousex()
endproc

rem Init balls.
procedure InitBalls()
for i = 0 to MAX_BALLS - 1
balls[i].x# = 0.0
balls[i].y# = 0.0
balls[i].dx# = 0.0
balls[i].dy# = 0.0
balls[i].speed = 4
balls[i].alive = false
next
ballCaptured = true
balls[0].alive = true
endproc

rem Update ball.
procedure UpdateBalls()
rem Is ball captured?
if ballCaptured
rem Set above paddle.
balls[0].x# = float(paddleX - 8)
balls[0].y# = float(paddleY - 16)
rem Launch?
if mousebutton(0, true)
balls[0].dx# = 0.0
balls[0].dy# = -1.0
balls[0].speed = 4
balls[0].alive = true
ballCaptured = false
endif
else
anyAlive = false
for i = 0 to MAX_BALLS - 1
if balls[i].alive
proc UpdateBall balls[i]
anyAlive = true
endif
next
if not anyAlive
ballCaptured = true
balls[0].alive = true
endif
endif
endproc

procedure UpdateBall(&ball?)
rem Being lazy here, don't wanna modify John's code, so I'm just
rem copying the object's members to local variables, which I copy
rem back at the end of the function.
ballX# = ball.x#
ballY# = ball.y#
ballDX# = ball.dx#
ballDY# = ball.dy#
ballSpeed = ball.speed

rem Move ball ballSpeed times.
for i = 1 to ballSpeed
rem Move.
ballX = ballX + ballDX
ballY = ballY + ballDY

rem Collision with paddle?
dx# = ballX + 8.0 - float(paddleX)
if abs#(dx) < 48.0 and ballY + 16.0 > float(paddleY) and ballY < float(paddleY) + 16.0
rem Bounce.
ballDY = -1.0
ballDX = dx/24.0
k# = 1.0/sqr(ballDX*ballDX + ballDY*ballDY)
ballDX = ballDX*k
ballDY = ballDY*k
endif

rem Check vertical collisions with bricks.
brickX = int(ballX + 8.0)/32
if brickX >= 0 and brickX < sizeof(bricks, 0)
rem Check brick above ball.
brickY = int(ballY)/16
if brickY < sizeof(bricks, 1) and brickY >= 0 and bricks[brickX][brickY]
bricks[brickX][brickY] = 0
ballDY = abs#(ballDY)
endif
rem Check brick below ball.
brickY = int(ballY + 16.0)/16
if brickY < sizeof(bricks, 1) and brickY >= 0 and bricks[brickX][brickY]
bricks[brickX][brickY] = 0
ballDY = -abs#(ballDY)
endif
endif

rem Check horizontal collisions with bricks.
brickY = int(ballY + 8.0)/16
if brickY >= 0 and brickY < sizeof(bricks, 1)
rem Check brick left of ball.
brickX = int(ballX)/32
if brickX < sizeof(bricks, 0) and brickX >= 0 and bricks[brickX][brickY]
bricks[brickX][brickY] = 0
ballDX = abs#(ballDX)
endif
rem Check brick right of ball.
brickX = int(ballX + 16.0)/32
if brickX < sizeof(bricks, 0) and brickX >= 0 and bricks[brickX][brickY]
bricks[brickX][brickY] = 0
ballDX = -abs#(ballDX)
endif
endif

rem Bounce on walls and ceiling.
if ballX < 0.0
ballDX = abs#(ballDX)
elseif ballX > 624.0
ballDX = -abs#(ballDX)
endif
if ballY < 0.0
ballDY = abs#(ballDY)
rem Ball lost?
elseif ballY > 480.0
ball.alive = false
break
endif
next

rem Lazy finish up by copying locals to object.
ball.x# = ballX#
ball.y# = ballY#
ball.dx# = ballDX#
ball.dy# = ballDY#
ball.speed = ballSpeed
endproc

rem Init bullets.
procedure InitBullets()
for i = 0 to MAX_BULLETS - 1
bullets[i].alive = false
next
endproc

rem Add bullet if possible.
procedure AddBullet(x, y)
rem look for free spot.
for i = 0 to MAX_BULLETS - 1
if bullets[i].alive = false then break
next
if i = MAX_BULLETS then return
bullets[i].alive = true
bullets[i].x = x
bullets[i].y = y
endproc

rem Update bullets.
procedure UpdateBullets()
for i = 0 to MAX_BULLETS - 1
if bullets[i].alive then proc UpdateBullet bullets[i]
next
endproc

rem Update bullet.
procedure UpdateBullet(&bullet?)
bullet.y = bullet.y - 8
if bullet.y < -16
bullet.alive = false
endif
x = bullet.x/32
y = bullet.y/16
if x >= 0 and x < sizeof(bricks, 0) and y >= 0 and y < sizeof(bricks, 1)
if bricks[x][y]
bricks[x][y] = 0
bullet.alive = false
endif
endif
endproc

rem Draw bullets.
procedure DrawBullets()
set color 255, 255, 255
for i = 0 to MAX_BULLETS - 1
if bullets[i].alive
draw rect bullets[i].x - 4, bullets[i].y, 8, 16, true
endif
next
endproc

rem Draw bricks.
procedure DrawBricks()
set color 192, 192, 192
for y = 0 to 14; for x = 0 to 19
if bricks[x][y] then draw rect x*32 + 1, y*16 + 1, 30, 14, true
next; next
endproc

rem Draw paddle.
procedure DrawPaddle()
set color 128, 128, 128
draw rect paddleX - 48, paddleY, 96, 16, true
endproc

rem Draw ball.
procedure DrawBall()
set color 255, 255, 255
for i = 0 to MAX_BALLS - 1
if balls[i].alive
draw rect int(balls[i].x#), int(balls[i].y#), 16, 16, true
endif
next
endproc
.\\\opz

Marcus

  • Administrator
  • Hero Member
  • *****
  • Posts: 542
    • View Profile
Re: Breakout principles (again, maybe)
« Reply #2 on: January 18, 2017 »
I've been messing around a bit more with the code originaly from John, not sure if I'll finish it. CrackTheBricks is the game, CTBED is the editor (uses IUP).
« Last Edit: January 18, 2017 by Marcus »
.\\\opz

B+

  • Full Member
  • ***
  • Posts: 215
    • View Profile
Re: Breakout principles (again, maybe)
« Reply #3 on: January 18, 2017 »
I have recently done versions of Breakout and so am very curious to compare code.

Is there a way to find out what is in Speed.lib?

And I notice the ball angles differently if hits paddle in middle or left or right, is it 3 angles or more variations according to where it hits paddle? In my versions I had to throw in some randomness to prevent monotonous and non productive ball pattern bouncing.

Code: [Select]
rem Collision with paddle?
dx# = ballX + 8.0 - float(paddleX)
if abs#(dx) < 48.0 and ballY + 16.0 > float(paddleY) and ballY < float(paddleY) + 16.0
rem Bounce.
ballDY = -1.0
ballDX = dx/24.0
k# = 1.0/sqr(ballDX*ballDX + ballDY*ballDY)
ballDX = ballDX*k
ballDY = ballDY*k
endif

Yes, angle depends how far from center of paddle, I think?

Bullets!  ;D 

Surely must have some tanks left from Gorillas and Tanks game.  >:D

« Last Edit: January 19, 2017 by B+ »
B+

Rick3137

  • Sr. Member
  • ****
  • Posts: 341
  • May the Force be with You
    • View Profile
    • Rick's Programs
Re: Breakout principles (again, maybe)
« Reply #4 on: January 19, 2017 »
   Nice work.

   It's times like this that I need a joystick. Using that laptop finger thingy gets a little tricky.
   Perhaps some arrow key action would work.  ^-^