A downloadable game

Aim of the game

In this game, you control a bouncing ball that jumps between platforms. The screen scrolls to the left, so keep the ball in the visible area.

Attention! Colour of the ball matters! When ball hits the platform, colour of the ball changes to the colour of the platform.

When the ball bounce off the platform, two things may happen:

  • platform will break if colour of the ball is different than colour of the platform, also you will score a point
  • platform will remain if colour of the ball is the same, no points will be given

Try to break as much platforms as you can, but don't break all of them at once as you will fall!

Become incredible, a true Incrediballer! Enjoy the challenge!

Side notes:

  • Use joystick in port 2.
  • Difficulty of the game and variety of platforms progresses with more points gained.
  • Due to technical limitations, points are shown for a short period of time only when game over occurs.

The game was tested on a real hardware and with WinVice 2.4 emulator.

Constants and variables

  • A - read from joystick port 2 for left/right directions
  • A$ - sprite data which is printed as hidden on the screen under location 1664 (sprite bank 16), it's partial data as the remaining zeroes are filled afterwards in line 1, in main loop re-used to print part of the platform
  • B$ - used to pass string to print in line 9
  • C - colour of the ball
  • C$ - sine table data used to set vertical position of the ball
  • D - colour of the platform read from the colour memory using `PEEK`
  • D$ - constant string with horizontal offset used when moving platform one square to the left
  • E - colour memory location of platforms
  • E$ - vertical offset for initial platform drawing
  • F - offset used to pick up the next platform colour
  • G - sine table offset for ball vertical position (1 - 15)
  • H - intermediate calculation for the position X of the ball, used to determine which platform the ball hit
  • I - use in multiple locations for loop iterations
  • J - used in FOR loop to draw blue sky
  • K - constant for 56320, joystick port 2 input address
  • L$ - platform colours
  • M - constant for 3
  • O - score, 1 point is gained when breaking a platform
  • P - calculated horizontal position of the platform, used to check collision of the ball with the platform
  • R - constant for 53248, used for sprite #0 positions X and Y
  • S - horizontal scroll offset
  • T - platform horizontal scroll offset (1, 2 or 3)
  • U - `-1` if colour of the platform is different than colour of the ball, `0` otherwise
  • V - constant for 53270, screen control register where horizontal raster scroll is performed
  • W - sets cursor row, re-used in condition to compare with ball's max vertical position
  • X - sprite position X of the ball
  • Y - sprite position Y of the ball

Scopes

  • world drawing
  • main loop
  • collision detection with the platform
  • horizontal screen scrolling
  • drawing platforms
  • single line drawing

Code line by line

- Line 0 (world drawing):

   - Initialise global constants and variables with READ in the following order: `V`, `T`, `X`, `D$`, `E$`, `R`, `C`, `E`, `K`, `O`, `M`, `W`, `C$`, `L$`, `A$`

   - Set screen foreground colour to green and background colour to blue

   - Clear the screen

   - Draw 15 lines of blue sky

- Line 1 (world drawing):

   - Remaining part of blue sky drawing loop (`GOSUB 9`)

   - Draw line of grass (`GOSUB 9`)

   - Print hidden sprite data (`A$`) under location 1664 (sprite bank 16), followed by filling the remaining zeroes (with another `GOSUB 9`)

   - Print hidden sine table values used to set vertical position of the ball (`C$`)

   - Move slightly down by printing `E$` in order to draw the initial platform (another `GOSUB 9`) so the ball doesn't fall at start

   - Set sprite bank 26 for sprite #0

   - Enable sprite #0 (`POKE V-1,1`)

- Line 2 (main loop):

   - Iterate next vertical position of bouncing ball by incrementing the sine table offset in range 1 - 15

   - Calculate sprite position X of the ball and limit boundaries

   - Get sprite position Y of the ball from sine table (`PEEK(1743+G)`)

   - Set sprite positions (by using `R` constant)

   - Intermediate calculation in `H` for the position X of the ball, used for collision detection with the platform in the following line

- Line 3 (collision detection with the platform):

   - If the ball is not in the lowest height (max value `W=214`), go to line 5 (`W` was possible to be re-used here, see: Tricks and notes, point 6)

   - Otherwise, calculate horizontal position in `P` by using already calculated small part (`H`) that simply didn't fit in that line

   - Read colour of the platform (`PEEK(E+P) AND 15`)

   - Store if colour of the platform is the same as colour of the ball in `U`

   - Set variable `C` to the colour of the platform in case is the same colour as colour of the ball, otherwise set it to a green colour (`5`) to create an effect of disappeared platform

- Line 4:

   - Add 1 point to `O` if colour of the platform and the ball vary

   - Changing colour of the platform (3 squares), if `C=5` (green colour), platform is removed as the surrounding background of this area is also green

   - Setting colour of the ball to the colour of the platform being hit

   - Go to line 6 if any other than green colour has been detected (`D<>5`)

   - Otherwise, print the score in the top left corner of the screen

   - Wait for a while (`FOR I=1 TO 999`)

   - Restore as program will be executed from the very beginning (`READ` is used in line 0)

   - Go to line 0

- Line 5 (joystick read):

   - Read joystick and store in `J`

   - Calculate joystick left/right directions in `A`

   - Data for `V`, `T`, `X`, `D$`, `E$`, `R`, `C`, `E`

- Line 6 (horizontal screen scrolling):

   - Set colour of sprite

   - Calculate new horizontal scroll offset in `S`

   - Wait for raster line

   - Go to line 7 if scroll offset is at the last step and platforms have to be moved one square left

   - Otherwise, set horizontal screen offset (`POKE V,S`)

   - Go to line 2

   - Data for `K`, `O`, `M`

- Line 7 (drawing platforms):

   - Increment `T` as platforms are 3-square wide so they are scrolled to the left in 3 steps

   - Set the next part of the platform to be drawn in `A$` (overwriting `A$` here where sprite data was kept initially)

   - Set horizontal screen offset (`POKE V,S`)

   - Set cursor row (`POKE W,21`)

   - Move line with the platform one square left by using INST DEL (`CHR$(20)`)

   - Set horizontal position to the right as at the end a new character will be drawn

- Line 8:

   - If `T>1` then the current colour will be used to draw a new character of a platform at the very right part of the screen

   - Otherwise, for `T=1`, a new colour will be randomised from a set (minimum of 3 colours) that increases while score progresses

   - Go to line 2

   - Data for `L$`

- Line 9 (single line drawing):

   - Prints given `B$` string 39 times on the screen, used to display grass and initial platform as well as filling remaining zeroes for sprite data

   - Return

   - Data for `A$`

Tricks and notes

  1. Sprite of the ball has been converted to string that is printed but hidden on the screen (below the grass). Data starts under location 1664 (sprite bank 16).
  2. With a little bit of experimentation, I was able to get quite smooth scrolling with wait for the rasterline (WAIT 53265,128).
  3. After struggling with programatical bouncing of the ball by using delta iterations with only 2 speed tests, I decided to hardcode positions from generated sine table. Much nicer effect! To store data, I used the same technique as for the sprite data by printing a hidden string below the sprite data.
  4. On game over, RESTORE is used to start over from line 0 as I had no space to skip the initialisation (READ).
  5. Thanks to line generation code in line 9, it was possible to build more interesting game world and also re-use this code to fill sprite data with the remaining zeroes.
  6. It was fun to look for numbers that could be re-used in many places, e.g. variable `W=214` has been added to shorten `POKE 214,Y` to set cursor row, but in the end this value was also re-used in the condition to compare to ball's max vertical position. It's worth noting, that using variables instead of literals speeds up the code execution as otherwise, BASIC would need to perform parsing to float.
  7. Ball cannot go to the very right part of the screen as I didn't have space left to implement sprite X-coordinate bit #8 (`$D010`).
  8. Two programs have been used to generate data in form of characters, for sprite data, and for sine table data.
  9. Basic Abbreviator (still in alpha version) assisted in writing of this game.
    0 readv,t,x,d$,e$,r,c,e,k,o,m,w,c$,l$,a$:pokev+10,6:pokev+11,5:print"{clr}{blu}";:b$="{rvon} ":forj=.to14
    1 gosub9:next:b$="{SHIFT-POUND}":gosub9:b$="@":print"{grn}"a$;:gosub9:printc$:printe$;:b$="{CBM-P}":gosub9:poke2040,26:pokev-1,1
    2 g=1-(g<15)*g:x=x-a*8*(x+a*8>28andx+a*8<240):y=peek(1743+g):poker,x:poker+1,y:h=x-35-s
    3 on-(y<w)goto5:p=int((int(h/8)+t-1)/m)*m+6-t:d=peek(e+p)and15:u=(c<>d):c=-(u=0)*c-u*5
    4 o=o-u:fori=.to2:pokee+p+i,c:next:c=d:on-(d<>5)goto6:print"{home}{rght}{rvon}{blk}"o:fori=1to999:next:restore:goto0
    5 j=peek(k):a=((jand4)=0)-((jand8)=0):data53270,2,36,"{rght}{rvon}","{down}{down}{down}{down}{rvon}{pur}",53248,4,56214,56320
    6 pokev+17,c:s=-s*(s>-1)-(s<1)*8-2:wait53265,128:on-(s=6)goto7:pokev,s:goto2:data0,3,214
    7 t=1-t*(t<m):a$=mid$("L{CBM-P}{CBM-P}",t,1):pokev,s:pokew,21:printd$chr$(20)tab(39);:data"{rvon}_K7%ui{rvof}{CBM-B}{CBM-F}{CBM-F}{CBM-B}{rvon}iu%7K
    8 f=-f*(t>1)-(t=1)*int(rnd(1)*((o/10)+3)):printmid$(l$,f+1,1)a$:goto2:data"{pur}{blk}{grn}{wht}{orng}{grn}{gry1}{grn}{red}{grn}{grn}{gry3}{grn}{grn}{grn}{cyn}{grn}
    9 fori=.to38:printb$;:next:print:return:data"a{rvon}{CBM-A}{rvof}@c8@f{rvon}{CBM-C}{rvof}@e{rvon}{CBM-C}{rvof}@m{rvon}{CBM-V}{rvof}@m{rvon}{CBM-V}{rvof}@o{rvon}{CBM-V}{rvof}@g{rvon}{CBM-C}{rvof}@f{rvon}{CBM-C}{rvof}@c{rvon}{CBM-U}{rvof}@a{rvon}{CBM-A}{rvof}

Download

Download
incrediball10.d64 170 kB
Download
incrediball10.prg 763 bytes
Download
incrediball-10-listing.txt 1 kB

Comments

Log in with itch.io to leave a comment.

(3 edits)

I noticed I forgot to include README doc that contains the code explanation in the zip file I sent to the contest. Anyways, README is available here: https://commocore.itch.io/incrediball-10

I will add it here.

Oh thanks <3. In case formatting doesn't work, feel free to grab it from https://csdb.dk/release/?id=240426 - it's in summary.

(+1)

Done :)

Thank you very much =D.