Next 1K hires game, BREAKOUT

Any discussions related to the creation of new hardware or software for the ZX80 or ZX81
dr beep
Posts: 1079
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: Next 1K hires game, BREAKOUT

Post by dr beep » Thu Sep 07, 2017 3:35 pm

The entire developmentstory:

Breakout, the development story.

After coding AIRPIPES Shaun Bebbers mentioned BREAKOUT.
I had been thinking about this long time ago. With the technic used on K-Bird it could be possible.

The screen:
As in all games the screen is the first to display the correct picture.
Take K-Bird. When nothing is moving you have a screen with bird and 3 pipes.
The pipes are replaced by walls. The bird is now a ball.
Add an extra wall and a bat. Simple as that. This is what would work if you had a full
hires screen of 6K available and you could just write to that screen. In 1K however it nneeds another way of displaying, although the base is ok.
Unlike K-Bird you have 11 horizontal screens. K-Bird uses 3 pointers to either a pipe or an open area where each pointer has a different startposition. This creates the alteration in the gap between the pipes. On BREAKOUT each screen points to a defined brick for each wall. After 16 screenlines the next bricks must be selected and shown. At the start of the line you also need to check if a bat must be displayed. The most important part of the display is the ball. The ball can go over the entire screen so you need 4 lines sized the width of the game to place a ball on ANY X-position.
The Y-position of the ball is checked during the display. The screen follows this schedule

Show text
Show topline
Loop Counter 176-1 to display all lines
– counter = ball-y ; display the ballscreen
– if not: test on bat-y if so display bat
– test if next 16 lines are reached, if so get new brickdata
– show brickdata
do next line in loop
Show bottomline

A game like PONG does the same. Test ball, Show ballline, do next line
However: this game also needs the check of passing 16 lines.
The time it takes to do this is more than fits a screenline of the ball.
The ballscreen is therefore not tested on each line but all 4 lines are displayed directly when the ball must be displayed. Adjusting the bricklines and the batcounter. This saves testing on the ball and just gave enough time to do all other checks needed. Only a test on ball is displayed is done.
The display works.... time for the game

The game:
During the game the screen changes. So the first thing to do is to built a screen according to the current situation. The bricks outside the ballscreen are set on initialization. The bat is set according to the currentposition where the bat is drawn on the ballscreen when the ball is at the same line. On the ballscreen the walls are drawn and finally the ball itself is drawn and tested on collision.
Now each situation works for the display of the screen.

Next to do is add movement.
First thing: after loading/game over, start the game.
A standard reading of NEWLINE. Nothing special
Set up the level, reset score, set startpositions.

Now you enter the playloop
Each loop the screen needs rebuilding, read controls, do movement,
do collision, erase hit brick, add score, test gameover, repeat the loop.

On start the ball is not moving.
When the bat moves, the ball goes with it (except for the hit bottombug).
With the bat movement the y-direction of the ball is set. This will however do nothing
while the ball is not released. After release the x-direction is set too. Now the ball will move on its
own even if the bat keeps still.
When the ball reaches top or bottom (this is not a collision) the y-direction changes.
When the ball HITS anything the X-direction is changed. When a wall is hit, the wall is reduced in thickness.
The gameloop ends in 2 situations.
1) the bat missed the ball ; GAME OVER
2) the ball BROKE through the final wall. Level ends.
The gameplay is now ready.

Although the game is playable it is nothing without some scoring.
You score a point for each brick you hit.
For each remaining brick at the end of the level you score 10 points.

Size reduction
Now the game runs in 2K. The location for the stack is too small to have the stack there.
Only 7 bytes for a stack is too small. The code needs reduction.

The hiscore check was not added yet. This would cost another 22 bytes.
Without the check the display of a hiscore is not needed (7 bytes won)

-Max. score
If you would go directly to next level you still wouldn't reach 10.000 points after level 6.
The score is reduced to 4 bytes (2 bytes won)

-Name display
Don't display “ BREAKOUT” (9 bytes won)

The stack is now 7+7+2+9=25 bytes. Some testing shows that we need 26 bytes.
After some time I found the final byte and the game run in 1K

End of game
Although I haven't reached the final level nor reached the end of it.
The game ends when level 6 is finished. However an end of game check needs 5
additional bytes. I found 4 by making a different delay routine and
to delete a RET and go through -at that moment- meaningless routine.
The final byte was found by SUB A in the same meaningless routine.
During display in high memory this byte inverts the display. When run in low
memory it will reset A which saves a XOR A to reset x-direction of the ball in the next level.

Alternative options:
The game COULD have hiscore if I delete the TOP and BOTTOM-line.

Character of the displaybuffer
A displaybuffer needs bit 6 to be reset. When bit 7 is set the data is inverted.
Therefore there are 6 bits not relevant to the value it has.
The displaybuffer for top and bottom has bit 7 set and uses the displaybuffer of the ball
(only spaces) as data. Spaces are shown as lines. The bits 0 to 5 of the inverted displaybuffer
are irrelevant. Suddenly I noticed that the pointers to the bricks all have bit 7 set and something in bit 0-5. This data can be used as a displaybuffer when at the end only a RET is added.
This saves 31 bytes at once. Suddenly the hiscore and name of the game could be added.

Alteration in the display(-routine)
Since I have 6 levels 2 bits are not used. To make the first wall on the ballscreen I need
a 2 bits shift to the left. By altering the view from 11111100 to 00111111 I can ALWAYS
shift 2 bits left without needing 2 registers. Also for timing 2 screendelayloops ressembled a lot.
It was possible to merge them. The space won with these final changes were enough to
add a lifecounter.

Final bytes
The display looks better when the lowres would fill out the whole line.
Can I find the bytes needed for this? Since the program itself clears the ball and the bat
and places bricks or spaces a full CLS for it is not needed. However on the screen
initialization data is set so this needs to be cleared. When this is done by the init-routine
the game won't need the CLS anymore. By using the LDIR-copy from hiscore it could fit
the maximum code loadable in 1k (951 bytes).
The lowres now has score, centered name, lives an at the end hiscore.

Post Reply