Announce: PONG on FIGnition :-) !

69 views
Skip to first unread message

Julian Skidmore

unread,
Nov 23, 2013, 5:28:18 PM11/23/13
to FIGnition
Hi folks,

Here's 862 bytes of pure retro :-) I thought my local church Christmas
faire needed a version of PONG amongst all the bric-a-brac and
cakes... how else were they to work it all off eh :-) ?

So, for everyone's benefit here it is: 2.9Kb of source and 862 byte
compiled :-) This version supports audio; different speeds and bat
sizes (but no attract mode).

How to play (PONG needs Firmware 0.9.8):

1. Load the game by loading the last block (it will load the rest).
2. Type: speed batSize pong <exe> Usually I type 3 8 pong . The speed
is the ratio of bat frames to ball frames, in this case 3 to 1.
3. The left player uses SW1 and SW6 to go up and down; the right
player uses SW4 and SW7 to go up and down.
4. First person to 15 wins!

These days I'm trying to work on making games smoother. This means
that every frame will be a 0 pause frame. However, if I want the bats
to be able to basically keep up with a ball (and the ball has multiple
angles), then it means the ball has to move once every 3 frames or so
and that means the ball is a little jerky compared with the bat. A
better way to do it would be to handle the movement of bats at twice
the frame rate (which is the maximum you can get from the FIGGypad
driver) - but then I'd have to work out how to do a half frame pause.
Timer 1 would be the best option, 1/100th of a second is 25000 cycles
so that's possible. The ball could then run faster and smoother for a
better and / or more challenging game, but perhaps the video
generation would get in the way of operation. But this is OK for the
moment :-)

Here's this listing! Have fun! If I've made any mistakes, let me know :-)

-cheers from Julz

( Pong)
0 var lsc 0 var rsc ( scores)
0 var ly 0 var ry ( left and right coord)
0 var bh ( ball height)
0 var by 0 var bx ( ball x,y)
0 var dx 0 var dy ( ball dir)
sysvars 11 + const joy
0 var audStop

: aud 64 191 42 >port>
drop ;

: beep ( presc freq --)
0 69 ic! ( sound off)
0 110 ic! ( no ints)
66 68 ic! ( ctc mode)
71 ic! ( pitch)
7 and 69 ic! ( oct+on)
;

: audEnd
audStop @ clock i@ -
0< if
0 0 beep
then
;

: sfx
8 clock i@ +
audStop ! beep
;

clock i@ var seed
: rnd ( range -- rnd)
seed @ 75 * 1+ dup
seed ! u* swap drop
;

: initBall
3 198 sfx
24 by ! 25 bx !
2 rnd 2* 1- dy !
2 rnd 2* 1- dx !
;

: mvBally ( y )
dy @ +
dup 2 < over 47 > or if
4 99 sfx
dy @ neg dup dy ! + ( and beep too?)
then
;

: .batUp ( y' dy x --)
1 pen >r + r over plot
2 pen bh @ + r>
swap plot
;

: .batDn ( y' dy x --)
1 pen >r drop ( y' : x)
r over bh @ + plot ( y' x y'+bh:x)
2 pen r> swap plot ( x y')
; ( -- )


: mvBat ( j msk &y x )
>r >r and dup 16 <
over 0= 0= and swap ( [msk&j] [msk&j] : &y x)
15 > neg + ( [[msk&j]>15]+[msk&j]<16]=>dy : &y x)
r @ swap over + 2 max ( y' max[dy+y',2] : &y x)
48 bh @ - min dup r> ! ( y' min[yTmp, 47-bh] : x)
over - r> ( y' y-y' x )
over 0< if ( y' y'-y x)
.batUp ;s
then
over neg 0< if
.batDn
else
drop drop drop
then
;

: .sc
6 0 at lsc @ 2 .r
18 0 at rsc @ 2 .r
;

: init ( bh --)
0 lsc ! 0 rsc ! ( bh)
cls 1 pen .sc ( bh)
dup bh ! dup ( bh bh)
1 >> 24 swap ( bh 24 bh/2)
- dup ly ! dup ry ! ( bh 24-bh/2)
swap over + swap do ( 24-bh/2 bh+24-bh/2)
0 i plot 49 i plot ( draw bats)
loop
48 0 do
i 1 and 1+ pen
25 i plot ( line down the middle)
loop
aud initBall
;

: bHit? ( x y limX &baty)
@ >r over dup r 1- > ( x y limX y [y>=baty]: baty)
swap r bh @ + < and ( x y limX [y>=baty]&[y<baty+bh] : baty)
>r rot = r> and if ( y [limX=x]&[y>baty-1]&[y<baty+bh] : baty)
5 78 sfx
dx @ neg dx ! ( bounce the ball in x)
dup r bh @ 1 >> + ( y y-[baty+[bh>>1]] bounce dy against mid-point of bat)
- dy ! ( y)
then
drop r> drop
; ( --)

: mvBallx ( x y)
swap dx @ + swap ( x+dx y)
2dup 1 ly bHit? ( x+dx y x+dx y 1 ly => bHit?)
2dup 48 ry bHit?
;

: mvBall ( -- x)
3 pen
bx @ by @ 2dup >r >r ( bx' by' : bx' by')
mvBally mvBallx ( bx by : bx' by')
2dup plot by ! dup
bx ! r> r> plot 1 pen
;

blk# @ 4 - 4 loads
: score? ( x --)
dup 0 < neg rsc +! ( x )
dup 49 > neg lsc +!
dup 0< over 49 > or if
3 pen dup by @ plot
.sc 50 pause
initBall 1 pen
then
drop
;

: bats
joy ic@ ( dup . ) ( speed j)
dup $21 ly 0 mvBat ( speed j)
$48 ry 49 mvBat ( speed)
;

: pong ( speed bh --)
init 1- ( speed)
begin
dup 0 do
bats 0 pause
loop
bats mvBall score? ( speed)
0 pause audEnd ( speed)
lsc @ 15 = rsc @ 15 =
or inkey asc A = or
until
0 0 beep drop
;


--

The DIY 8-bit computer from nichemachines™
Pong.png
Pong.zip

carl

unread,
Nov 24, 2013, 5:46:03 AM11/24/13
to fign...@googlegroups.com
Thanks Julz,

It works a treat.
There is a relative loader in your code so you only need load up the last block and the loader will do the rest, providing they are saved in the logical order.

The game performs realy well on the figgypad, seems to miss a bit on my keyboard- this could be a good test of your FIGkeys 1.1

One question, how did you define the keys?
 not a dup, if, then, in sight!


here is a video of it working.

regards.



Julian Skidmore

unread,
Nov 24, 2013, 10:30:00 AM11/24/13
to FIGnition

Hi Carl,

Thanks for the feedback and the video :-)

How does the key input work on FIGnition PONG, why no dup ... if ... then?

The FIGnition keypad uses 6 signals to read 8 keys. The limitation is that it can't properly see every combination of more than 2 keys - and for a two player PONG game you need to handle up to 4 key presses (in case they both momentarily press up & down at the same time).

So PONG must read the keypad directly. This is done by defining sysvars 11 + const joy

And later reading it using joy ic@ which reads the raw, debounced keypad state from internal AVR memory. It's possible to read up to 4 buttons at the same time if they're all on different columns, so I picked SW1 and SW6 for the left player, and SW4 and SW7 for the right player. That way all the keys are on different columns and player keys are as far apart as I can make it. But note also, the up keys are both on the top row and the down keys are on the bottom row.

So bat handling is done using 2 commands: bats and mvBat. When we call bats we read the keypad (an 8-bit value) and supply it along with a mask (e.g. $21) along with a player's bat y variable address to mvBat.

MvBat ands its key input with the mask. So, if you take the FIGgypad keypad state and and with $21, only 1 bit will be set on the upper nybble (if SW6 is pressed) and/or 1 bit on the lower nybble (if SW1 is pressed).

MvBat then takes the mask value and compares each nybble. The 15 > test results in -1 if SW6 is pressed (or 0 otherwise). Since SW6 is for moving the bat down, which increments the y-coordinate the result is negated. The 16<test results in -1 if SW1 is presssed (or 0 otherwise), which is the correct value to add to the y coordinate to move the bat up. Simply by adding these two test results together gives the correct change to the bat's y coordinate.

So, deciding whether to move a bat up or down can be done with a pure calculation rather than if's and then's. It works because comparisons return results which are just numbers like any other calculation. The technique was very popular with BASIC games in the 80s because IF THEN and GOTO were much slower than doing it by calculation. Typically we'd do things like LET key=CODE INKEY$: LET y=y+(key=10)-(key=11). In Sinclair BASIC comparisons returned 1 for true and 0 for false (in Microsoft, commodore and BBC BASIC it was -1 for true).

Does this help?

-cheers julz

--
You received this message because you are subscribed to the Google Groups "FIGnition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fignition+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Reply all
Reply to author
Forward
0 new messages