|
1 | 1 | 1 REM GFX JIFFY CLOCK DEMO: smooth player + simple enemy motion |
2 | 2 | 2 REM Run with: ./basic-gfx -petscii examples/gfx_jiffy_game_demo.bas |
3 | | -3 REM Controls: hold W/A/S/D to move, ESC to quit |
4 | | -4 REM |
5 | | -5 REM Uses TI (60Hz) to update at a steady rate regardless of input bursts. |
6 | | -6 REM Each line number must be unique — duplicate numbers replace earlier lines. |
| 3 | +3 REM Canvas WASM: TI is wall-clock jiffies; use SLEEP 1 + simple loop (no TI bucket wait). |
| 4 | +4 REM Controls: hold W/A/S/D to move, ESC to quit |
| 5 | +5 REM |
7 | 6 | 10 SCR = 1024 |
8 | 7 | 20 COL = 55296 |
9 | 8 | 30 WIDTH = 40 |
|
14 | 13 | 80 PRINT "{CLR}{WHITE}JIFFY CLOCK DEMO (WASD MOVE, ESC QUITS)" |
15 | 14 | 90 PRINT "{CYAN}PLAYER IS '@' ENEMY IS 'X' (SINE WAVE)" |
16 | 15 |
|
17 | | -100 REM Player state |
| 16 | +100 REM Player / enemy |
18 | 17 | 110 PX = 5 |
19 | 18 | 120 PY = 12 |
20 | 19 | 130 PCOL = 1 |
| 20 | +140 EX0 = 20 |
| 21 | +150 EY = 12 |
| 22 | +160 ECOL = 2 |
| 23 | +170 AMP = 4 |
| 24 | +180 PERIOD = 180 |
| 25 | +185 ECH = 160 |
| 26 | +190 EX = EX0 |
21 | 27 |
|
22 | | -140 REM Enemy state (sine wave in X) |
23 | | -150 EX0 = 20 |
24 | | -160 EY = 12 |
25 | | -170 ECOL = 2 |
26 | | -180 AMP = 4 |
27 | | -190 PERIOD = 180 |
28 | | -195 ECH = 160 |
29 | | - |
30 | | -200 REM Timing (in jiffies) |
31 | | -210 REM LT one behind TI so first IF T<=LT passes (canvas TI = wall ms/60Hz) |
32 | | -220 LT = TI - 1 |
33 | | -230 PSTEP = 3 |
34 | | -235 PMOVE = TI |
35 | | -240 ESTEP = 6 |
36 | | -245 ELT = TI |
37 | | - |
38 | | -250 REM Initial draw |
39 | | -260 POKE SCR + PY*WIDTH + PX, 0 |
40 | | -270 POKE COL + PY*WIDTH + PX, PCOL |
41 | | -280 POKE SCR + EY*WIDTH + EX0, ECH |
42 | | -290 POKE COL + EY*WIDTH + EX0, ECOL |
43 | | -295 LXE = EX0 |
| 28 | +200 REM Initial draw |
| 29 | +210 POKE SCR + PY*WIDTH + PX, 0 |
| 30 | +220 POKE COL + PY*WIDTH + PX, PCOL |
| 31 | +230 POKE SCR + EY*WIDTH + EX, ECH |
| 32 | +240 POKE COL + EY*WIDTH + EX, ECOL |
| 33 | +250 LXE = EX |
44 | 34 |
|
45 | 35 | 300 REM Main loop |
46 | 36 | 310 IF PEEK(KEYBASE+27) <> 0 THEN END |
47 | 37 | 320 T = TI |
48 | | -330 REM Wait until a new jiffy (TI>T); "=" alone can spin on same bucket |
49 | | -340 IF T <= LT THEN SLEEP 1 : GOTO 310 |
50 | | - |
51 | | -350 REM --- Enemy updates at a steady rate (about 10 fps) --- |
52 | | -355 IF T < ELT + ESTEP THEN GOTO 398 |
53 | | -357 ELT = T |
54 | | -360 REM Use seconds-ish phase: (T/PERIOD)*2*pi |
55 | | -370 Q = INT(T / PERIOD) |
56 | | -380 PH = T - Q * PERIOD |
57 | | -390 EX = EX0 + INT(AMP * SIN(6.28318 * (PH / PERIOD))) |
58 | | -392 IF EX < 0 THEN EX = 0 |
59 | | -394 IF EX > 39 THEN EX = 39 |
60 | | - |
61 | | -396 REM --- Player updates at fixed speed while key held --- |
62 | | -398 NX = PX : NY = PY |
63 | | -400 IF T < PMOVE + PSTEP THEN GOTO 500 |
64 | | -420 IF PEEK(KEYBASE+87) <> 0 THEN NY = PY - 1 |
65 | | -430 IF PEEK(KEYBASE+83) <> 0 THEN NY = PY + 1 |
66 | | -440 IF PEEK(KEYBASE+65) <> 0 THEN NX = PX - 1 |
67 | | -450 IF PEEK(KEYBASE+68) <> 0 THEN NX = PX + 1 |
68 | | -460 IF NX < 0 THEN NX = 0 |
69 | | -470 IF NX > 39 THEN NX = 39 |
70 | | -480 PMOVE = T |
71 | | -500 IF NY < 2 THEN NY = 2 |
72 | | -510 IF NY > 24 THEN NY = 24 |
| 38 | +330 SLEEP 1 |
73 | 39 |
|
74 | | -520 REM --- Redraw only when positions change --- |
75 | | -530 IF NX <> PX OR NY <> PY THEN POKE SCR + PY*WIDTH + PX, 32 |
| 40 | +340 REM Enemy: phase from jiffy clock TI (updates every frame after SLEEP) |
| 41 | +350 Q = INT(T / PERIOD) |
| 42 | +360 PH = T - Q * PERIOD |
| 43 | +370 EX = EX0 + INT(AMP * SIN(6.28318 * (PH / PERIOD))) |
| 44 | +380 IF EX < 0 THEN EX = 0 |
| 45 | +390 IF EX > 39 THEN EX = 39 |
76 | 46 |
|
77 | | -540 IF NX <> PX OR NY <> PY THEN PX = NX : PY = NY |
| 47 | +400 REM Player: read keys every frame (no TI gate — works in canvas + basic-gfx) |
| 48 | +410 NX = PX |
| 49 | +420 NY = PY |
| 50 | +430 IF PEEK(KEYBASE+87) <> 0 THEN NY = PY - 1 |
| 51 | +440 IF PEEK(KEYBASE+83) <> 0 THEN NY = PY + 1 |
| 52 | +450 IF PEEK(KEYBASE+65) <> 0 THEN NX = PX - 1 |
| 53 | +460 IF PEEK(KEYBASE+68) <> 0 THEN NX = PX + 1 |
| 54 | +470 IF NX < 0 THEN NX = 0 |
| 55 | +480 IF NX > 39 THEN NX = 39 |
| 56 | +490 IF NY < 2 THEN NY = 2 |
| 57 | +500 IF NY > 24 THEN NY = 24 |
78 | 58 |
|
79 | | -550 POKE SCR + PY*WIDTH + PX, 0 |
80 | | -560 POKE COL + PY*WIDTH + PX, PCOL |
| 59 | +510 REM Redraw when moved |
| 60 | +520 IF NX <> PX OR NY <> PY THEN POKE SCR + PY*WIDTH + PX, 32 |
| 61 | +530 IF NX <> PX OR NY <> PY THEN PX = NX : PY = NY |
| 62 | +540 POKE SCR + PY*WIDTH + PX, 0 |
| 63 | +550 POKE COL + PY*WIDTH + PX, PCOL |
81 | 64 |
|
82 | | -570 REM Draw enemy first, then clear old to avoid "blank" tear on concurrent render |
83 | | -580 POKE SCR + EY*WIDTH + EX, ECH |
84 | | -590 POKE COL + EY*WIDTH + EX, ECOL |
85 | | -600 IF EX <> LXE THEN POKE SCR + EY*WIDTH + LXE, 32 |
| 65 | +560 POKE SCR + EY*WIDTH + EX, ECH |
| 66 | +570 POKE COL + EY*WIDTH + EX, ECOL |
| 67 | +580 IF EX <> LXE THEN POKE SCR + EY*WIDTH + LXE, 32 |
86 | 68 |
|
87 | | -610 REM HUD: rows 0-1 are the PRINT banner — use row 2-3 or text is hidden |
88 | | -620 TEXTAT 0,2,"TI$=" + TI$ + " " |
89 | | -630 TEXTAT 0,3,"TI=" + STR$(TI) + " " |
| 69 | +590 REM HUD under banner (rows 2-3) |
| 70 | +600 TEXTAT 0,2,"TI$=" + TI$ + " " |
| 71 | +610 TEXTAT 0,3,"TI=" + STR$(TI) + " " |
90 | 72 |
|
91 | | -640 REM Save last positions/time and loop |
92 | | -650 LXE = EX |
93 | | -660 LT = T |
94 | | -670 GOTO 310 |
| 73 | +620 LXE = EX |
| 74 | +630 GOTO 310 |
0 commit comments