1 /*
2
3 Z88DK base graphics libraries examples
4 Colour version
5
6 A classic 2 players game, the opponents must trap each other.
7
8 Build options:
9 -DJOYSTICK_DIALOG - let the players choose their controllers
10 -DPSG -lm - PSG sound support (e.g. ZON-X on the ZX81, maths library is required)
11
12
13 SPEED must be adjusted according to the CPU speed (e.g. must be around 500 on a ZX81)
14
15 zcc +trs80 -subtype=eg2000disk -lgfxeg2000 -create-app -DSPEED=1500 -DJOYSTICK_DIALOG -DDEFINE_JOYSTICK_TYPE csnakes.c
16
17 */
18
19 #include <games.h>
20 #include <graphics.h>
21
22 #ifdef JOYSTICK_DIALOG
23 #include <stdio.h>
24 #endif
25
26 #ifdef PSG
27 #include <psg.h>
28 #endif
29
30 struct snake {
31 int joystick;
32 int direction;
33 int x;
34 int y;
35 int x_incr;
36 int y_incr;
37 int c;
38 };
39
40 struct snake p1;
41 struct snake p2;
42
43 int x, y;
44
crash(int a,int b)45 void crash(int a, int b)
46 {
47 for (y = 0; y < 30; y++) {
48
49 cplot(a + 1, b + 1, y & 3);
50 cplot(a - 1, b - 1, y & 3);
51 cplot(a - 1, b + 1, y & 3);
52 cplot(a + 1, b - 1, y & 3);
53
54 for (x = 0; x < SPEED * 2; x++) {
55 }
56 }
57 }
58
move_snake(struct snake * p)59 int move_snake(struct snake* p)
60 {
61
62 if (p->direction & MOVE_RIGHT) {
63 p->x_incr = 1;
64 p->y_incr = 0;
65 }
66 if (p->direction & MOVE_LEFT) {
67 p->x_incr = -1;
68 p->y_incr = 0;
69 }
70 if (p->direction & MOVE_DOWN) {
71 p->y_incr = 1;
72 p->x_incr = 0;
73 }
74 if (p->direction & MOVE_UP) {
75 p->y_incr = -1;
76 p->x_incr = 0;
77 }
78
79 p->x += p->x_incr;
80 p->y += p->y_incr;
81
82 if (cpoint(p->x, p->y)!=0)
83 return (0);
84 cplot(p->x, p->y, p->c);
85
86 p->direction = joystick(p->joystick);
87
88 for (x = 0; x < SPEED; x++) {
89 };
90 return (1);
91 }
92
play_game()93 int play_game()
94 {
95 while (1) {
96 if (move_snake(&p1) == 0) {
97 #ifdef PSG
98 psg_envelope(envD, psgT(10), chanAll); // set a fading volume envelope on all channels
99 #endif
100 crash(p1.x - p1.x_incr, p1.y - p1.y_incr);
101 return (1);
102 }
103
104 #ifdef PSG
105 psg_tone(1, psgT(p1.x + p1.y + 10 * (15 + 2 * p1.x_incr + p1.y_incr)));
106 #endif
107
108 if (move_snake(&p2) == 0) {
109 #ifdef PSG
110 psg_envelope(envD, psgT(10), chanAll); // set a fading volume envelope on all channels
111 #endif
112 crash(p2.x - p2.x_incr, p2.y - p2.y_incr);
113 return (2);
114 }
115
116 #ifdef PSG
117 psg_tone(2, psgT(p2.x + p2.y + 12 * (15 + 2 * p2.x_incr + p2.y_incr)));
118 #endif
119 }
120 }
121
main()122 main()
123 {
124
125 #ifdef JOYSTICK_DIALOG
126
127
128 printf("%c\nLeft player controller:\n\n", 12);
129
130 for (x = 0; x != GAME_DEVICES; x++)
131 printf("%u - %s\n", x + 1, joystick_type[x]);
132
133 p1.joystick = 0;
134 while ((p1.joystick < 1) || (p1.joystick > GAME_DEVICES))
135 p1.joystick = getk() - 48;
136
137 while (getk())
138 ;
139
140 printf("%c\nRight player controller:\n\n", 12);
141
142 for (x = 0; x != GAME_DEVICES; x++)
143 printf("%u - %s\n", x + 1, joystick_type[x]);
144
145 p2.joystick = 0;
146 while ((p2.joystick < 1) || (p2.joystick > GAME_DEVICES))
147 p2.joystick = getk() - 48;
148
149 #else
150
151 p1.joystick = 1;
152 p2.joystick = 2;
153
154 #endif
155
156 while (1) {
157 cclg();
158
159
160 #ifdef PSG
161 psg_init();
162 psg_volume(1, 10);
163 psg_volume(2, 10);
164 #endif
165
166 for (x = 0; x <= 127; x++) {
167 cplot(x, 0, 2);
168 cplot(x, 63, 2);
169 }
170 for (y = 0; y <= 63; y++) {
171 cplot(0, y, 2);
172 cplot(127, y, 2);
173 }
174
175 p1.x = 127 / 5;
176 p1.y = 63 / 5;
177 p1.direction = MOVE_LEFT;
178 p1.x_incr = -1;
179 p1.y_incr = 0;
180 p1.c = 1;
181
182 p2.x = 127 - 127 / 5;
183 p2.y = 63 - 63 / 5;
184 p2.direction = MOVE_RIGHT;
185 p2.x_incr = 1;
186 p2.y_incr = 0;
187 p2.c = 3;
188
189 play_game();
190 }
191 }
192