|
@@ -73,9 +73,11 @@
|
73
|
73
|
#define SCORE_SMALL 5
|
74
|
74
|
#define SCORE_LARGE 10
|
75
|
75
|
|
76
|
|
-#define DESPAWN_RANGE (250 << POS_SCALE_OBJS)
|
|
76
|
+//#define DESPAWN_RANGE (0x7F << POS_SCALE_OBJS)
|
77
|
77
|
|
78
|
|
-#define PLACEMENT_DISTANCE 42
|
|
78
|
+#define INITIAL_DISTANCE 30 // from center
|
|
79
|
+#define RESPAWN_DISTANCE 100 // from center
|
|
80
|
+#define PLACEMENT_DISTANCE 42 // relative to each other
|
79
|
81
|
|
80
|
82
|
struct obj {
|
81
|
83
|
uint8_t active;
|
|
@@ -90,88 +92,108 @@ struct obj {
|
90
|
92
|
static struct obj objs[MAX_OBJ];
|
91
|
93
|
static uint8_t obj_cnt[SPRITE_COUNT];
|
92
|
94
|
|
|
95
|
+static const uint8_t obj_max[SPRITE_COUNT] = {
|
|
96
|
+ 1, // SPR_SHIP
|
|
97
|
+ MAX_LIGHT, // SPR_LIGHT
|
|
98
|
+ MAX_DARK, // SPR_DARK
|
|
99
|
+ MAX_SHOT, // SPR_SHOT
|
|
100
|
+ MAX_SHOT_LIGHT, // SPR_SHOT_LIGHT
|
|
101
|
+ MAX_SHOT_DARK, // SPR_SHOT_DARK
|
|
102
|
+ 4, // SPR_HEALTH
|
|
103
|
+ 4, // SPR_POWER
|
|
104
|
+ 1, // SPR_EXPL
|
|
105
|
+ 1, // SPR_PAUSE
|
|
106
|
+ 1, // SPR_DEBUG
|
|
107
|
+ 1, // SPR_DEBUG_LARGE
|
|
108
|
+};
|
|
109
|
+
|
93
|
110
|
void obj_init(void) BANKED {
|
94
|
111
|
memset(objs, 0, sizeof(objs));
|
95
|
112
|
memset(obj_cnt, 0, sizeof(obj_cnt));
|
96
|
113
|
}
|
97
|
114
|
|
98
|
|
-static uint8_t is_too_close(int8_t x, int8_t y, uint8_t n, int8_t *x_c, int8_t *y_c) {
|
99
|
|
- for (uint8_t i = 0; i < n; i++) {
|
100
|
|
- int dst_x = abs(x_c[i] - x);
|
101
|
|
- int dst_y = abs(y_c[i] - y);
|
|
115
|
+static uint8_t is_too_close(int8_t x, int8_t y, int8_t center_dist) {
|
|
116
|
+ if ((abs(x) < center_dist) && (abs(y) < center_dist)) {
|
|
117
|
+ return 1;
|
|
118
|
+ }
|
|
119
|
+
|
|
120
|
+ for (uint8_t i = 0; i < MAX_OBJ; i++) {
|
|
121
|
+ if (!objs[i].active) {
|
|
122
|
+ continue;
|
|
123
|
+ }
|
|
124
|
+
|
|
125
|
+ int dst_x = abs((objs[i].off_x >> POS_SCALE_OBJS) - x);
|
|
126
|
+ int dst_y = abs((objs[i].off_y >> POS_SCALE_OBJS) - y);
|
|
127
|
+
|
102
|
128
|
if ((dst_x < PLACEMENT_DISTANCE) && (dst_y < PLACEMENT_DISTANCE)) {
|
103
|
129
|
return 1;
|
104
|
130
|
}
|
105
|
131
|
}
|
|
132
|
+
|
106
|
133
|
return 0;
|
107
|
134
|
}
|
108
|
135
|
|
109
|
|
-static void generate_coords(uint8_t n, int8_t *x_c, int8_t *y_c) {
|
|
136
|
+static void generate_coords(int8_t *x_c, int8_t *y_c, int8_t center_dist) {
|
110
|
137
|
int8_t x = 0;
|
111
|
138
|
int8_t y = 0;
|
112
|
139
|
|
113
|
140
|
do {
|
114
|
141
|
x = arand();
|
115
|
142
|
y = arand();
|
116
|
|
- } while (is_too_close(x, y, n, x_c, y_c));
|
|
143
|
+ } while (is_too_close(x, y, center_dist));
|
117
|
144
|
|
118
|
|
- x_c[n] = x;
|
119
|
|
- y_c[n] = y;
|
|
145
|
+ *x_c = x;
|
|
146
|
+ *y_c = y;
|
120
|
147
|
}
|
121
|
148
|
|
122
|
|
-void obj_spawn(void) BANKED {
|
123
|
|
- int8_t x_coords[MAX_DARK + MAX_LIGHT + MAX_SHOT_DARK + MAX_SHOT_LIGHT + 1];
|
124
|
|
- int8_t y_coords[MAX_DARK + MAX_LIGHT + MAX_SHOT_DARK + MAX_SHOT_LIGHT + 1];
|
125
|
|
- memset(x_coords, 0, sizeof(x_coords));
|
126
|
|
- memset(y_coords, 0, sizeof(y_coords));
|
127
|
|
-
|
128
|
|
- for (uint8_t i = 0; i < MAX_DARK; i++) {
|
129
|
|
- uint8_t n = i + 1;
|
130
|
|
- generate_coords(n, x_coords, y_coords);
|
131
|
|
- obj_add(SPR_DARK, x_coords[n], y_coords[n], 0, 0);
|
132
|
|
- }
|
133
|
|
- for (uint8_t i = 0; i < MAX_LIGHT; i++) {
|
134
|
|
- uint8_t n = MAX_DARK + i + 1;
|
135
|
|
- generate_coords(n, x_coords, y_coords);
|
136
|
|
- obj_add(SPR_LIGHT, x_coords[n], y_coords[n], 0, 0);
|
137
|
|
- }
|
138
|
|
- for (uint8_t i = 0; i < MAX_SHOT_DARK; i++) {
|
139
|
|
- uint8_t n = MAX_DARK + MAX_LIGHT + i + 1;
|
140
|
|
- generate_coords(n, x_coords, y_coords);
|
141
|
|
- obj_add(SPR_SHOT_DARK, x_coords[n], y_coords[n], 0, 0);
|
142
|
|
- }
|
143
|
|
- for (uint8_t i = 0; i < MAX_SHOT_LIGHT; i++) {
|
144
|
|
- uint8_t n = MAX_DARK + MAX_LIGHT + MAX_SHOT_LIGHT + i + 1;
|
145
|
|
- generate_coords(n, x_coords, y_coords);
|
146
|
|
- obj_add(SPR_SHOT_LIGHT, x_coords[n], y_coords[n], 0, 0);
|
|
149
|
+static void obj_respawn(int8_t center_dist) {
|
|
150
|
+ for (uint8_t spr = SPR_LIGHT; spr <= SPR_SHOT_DARK; spr++) {
|
|
151
|
+ if (spr == SPR_SHOT) {
|
|
152
|
+ continue;
|
|
153
|
+ }
|
|
154
|
+
|
|
155
|
+ while (obj_cnt[spr] < obj_max[spr]) {
|
|
156
|
+ int8_t x, y;
|
|
157
|
+ generate_coords(&x, &y, center_dist);
|
|
158
|
+ obj_add(spr, x, y, 0, 0);
|
|
159
|
+ }
|
147
|
160
|
}
|
148
|
161
|
}
|
149
|
162
|
|
|
163
|
+void obj_spawn(void) BANKED {
|
|
164
|
+ obj_respawn(INITIAL_DISTANCE);
|
|
165
|
+}
|
|
166
|
+
|
150
|
167
|
enum OBJ_STATE obj_add(enum SPRITES sprite, int16_t off_x, int16_t off_y, int16_t spd_x, int16_t spd_y) BANKED {
|
151
|
|
- uint8_t obj_cnt = 0xFF;
|
|
168
|
+ uint8_t next = 0xFF;
|
152
|
169
|
for (uint8_t i = 0; i < MAX_OBJ; i++) {
|
153
|
170
|
if (!objs[i].active) {
|
154
|
|
- obj_cnt = i;
|
|
171
|
+ next = i;
|
155
|
172
|
break;
|
156
|
173
|
}
|
157
|
174
|
}
|
158
|
|
- if (obj_cnt >= MAX_OBJ) {
|
|
175
|
+ if (next >= MAX_OBJ) {
|
159
|
176
|
return OBJ_LIST_FULL;
|
160
|
177
|
}
|
161
|
178
|
|
162
|
|
- objs[obj_cnt].active = 1;
|
163
|
|
- objs[obj_cnt].sprite = sprite;
|
164
|
|
- objs[obj_cnt].off_x = off_x << POS_SCALE_OBJS;
|
165
|
|
- objs[obj_cnt].off_y = off_y << POS_SCALE_OBJS;
|
166
|
|
- objs[obj_cnt].spd_x = spd_x;
|
167
|
|
- objs[obj_cnt].spd_y = spd_y;
|
168
|
|
- objs[obj_cnt].travel = 0;
|
|
179
|
+ if (obj_cnt[sprite] >= obj_max[sprite]) {
|
|
180
|
+ return OBJ_TYPE_FULL;
|
|
181
|
+ }
|
|
182
|
+
|
|
183
|
+ obj_cnt[sprite]++;
|
|
184
|
+
|
|
185
|
+ objs[next].active = 1;
|
|
186
|
+ objs[next].sprite = sprite;
|
|
187
|
+ objs[next].off_x = off_x << POS_SCALE_OBJS;
|
|
188
|
+ objs[next].off_y = off_y << POS_SCALE_OBJS;
|
|
189
|
+ objs[next].spd_x = spd_x;
|
|
190
|
+ objs[next].spd_y = spd_y;
|
|
191
|
+ objs[next].travel = 0;
|
169
|
192
|
|
170
|
|
- obj_cnt += 1;
|
171
|
193
|
return OBJ_ADDED;
|
172
|
194
|
}
|
173
|
195
|
|
174
|
|
-int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *hiwater) BANKED {
|
|
196
|
+int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *hiwater, uint8_t is_splash) BANKED {
|
175
|
197
|
int16_t damage = 0;
|
176
|
198
|
|
177
|
199
|
// initial speed
|
|
@@ -206,6 +228,7 @@ int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *
|
206
|
228
|
// remove objects that have traveled for too long
|
207
|
229
|
if (objs[i].travel >= MAX_TRAVEL) {
|
208
|
230
|
objs[i].active = 0;
|
|
231
|
+ obj_cnt[objs[i].sprite]--;
|
209
|
232
|
continue;
|
210
|
233
|
}
|
211
|
234
|
|
|
@@ -215,10 +238,13 @@ int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *
|
215
|
238
|
// handle collision
|
216
|
239
|
switch (objs[i].sprite) {
|
217
|
240
|
case SPR_DARK:
|
|
241
|
+#ifdef DESPAWN_RANGE
|
218
|
242
|
if ((abs_off_x >= DESPAWN_RANGE) || (abs_off_y >= DESPAWN_RANGE)) {
|
219
|
|
- // TODO find new (random) position
|
220
|
|
- //objs[i].active = 0;
|
|
243
|
+ objs[i].active = 0;
|
|
244
|
+ obj_cnt[objs[i].sprite]--;
|
|
245
|
+ obj_respawn(RESPAWN_DISTANCE);
|
221
|
246
|
}
|
|
247
|
+#endif // DESPAWN_RANGE
|
222
|
248
|
|
223
|
249
|
if ((abs_off_x <= GRAVITY_RANGE) && (abs_off_y <= GRAVITY_RANGE)) {
|
224
|
250
|
if (objs[i].off_x > 0) {
|
|
@@ -239,10 +265,13 @@ int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *
|
239
|
265
|
break;
|
240
|
266
|
|
241
|
267
|
case SPR_LIGHT:
|
|
268
|
+#ifdef DESPAWN_RANGE
|
242
|
269
|
if ((abs_off_x >= DESPAWN_RANGE) || (abs_off_y >= DESPAWN_RANGE)) {
|
243
|
|
- // TODO find new (random) position
|
244
|
|
- //objs[i].active = 0;
|
|
270
|
+ objs[i].active = 0;
|
|
271
|
+ obj_cnt[objs[i].sprite]--;
|
|
272
|
+ obj_respawn(RESPAWN_DISTANCE);
|
245
|
273
|
}
|
|
274
|
+#endif // DESPAWN_RANGE
|
246
|
275
|
|
247
|
276
|
if ((abs_off_x <= GRAVITY_RANGE) && (abs_off_y <= GRAVITY_RANGE)) {
|
248
|
277
|
if (objs[i].off_x > 0) {
|
|
@@ -263,26 +292,36 @@ int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *
|
263
|
292
|
break;
|
264
|
293
|
|
265
|
294
|
case SPR_SHOT_DARK:
|
|
295
|
+#ifdef DESPAWN_RANGE
|
266
|
296
|
if ((abs_off_x >= DESPAWN_RANGE) || (abs_off_y >= DESPAWN_RANGE)) {
|
267
|
|
- // TODO find new (random) position
|
268
|
|
- //objs[i].active = 0;
|
|
297
|
+ objs[i].active = 0;
|
|
298
|
+ obj_cnt[objs[i].sprite]--;
|
|
299
|
+ obj_respawn(RESPAWN_DISTANCE);
|
269
|
300
|
}
|
|
301
|
+#endif // DESPAWN_RANGE
|
270
|
302
|
|
271
|
303
|
if ((abs_off_x <= PICKUP_SMALL_RANGE) && (abs_off_y <= PICKUP_SMALL_RANGE)) {
|
272
|
304
|
(*score) -= SCORE_SMALL;
|
273
|
305
|
objs[i].active = 0;
|
|
306
|
+ obj_cnt[objs[i].sprite]--;
|
|
307
|
+ obj_respawn(RESPAWN_DISTANCE);
|
274
|
308
|
}
|
275
|
309
|
break;
|
276
|
310
|
|
277
|
311
|
case SPR_SHOT_LIGHT:
|
|
312
|
+#ifdef DESPAWN_RANGE
|
278
|
313
|
if ((abs_off_x >= DESPAWN_RANGE) || (abs_off_y >= DESPAWN_RANGE)) {
|
279
|
|
- // TODO find new (random) position
|
280
|
|
- //objs[i].active = 0;
|
|
314
|
+ objs[i].active = 0;
|
|
315
|
+ obj_cnt[objs[i].sprite]--;
|
|
316
|
+ obj_respawn(RESPAWN_DISTANCE);
|
281
|
317
|
}
|
|
318
|
+#endif // DESPAWN_RANGE
|
282
|
319
|
|
283
|
320
|
if ((abs_off_x <= PICKUP_SMALL_RANGE) && (abs_off_y <= PICKUP_SMALL_RANGE)) {
|
284
|
321
|
(*score) += SCORE_SMALL;
|
285
|
322
|
objs[i].active = 0;
|
|
323
|
+ obj_cnt[objs[i].sprite]--;
|
|
324
|
+ obj_respawn(RESPAWN_DISTANCE);
|
286
|
325
|
}
|
287
|
326
|
break;
|
288
|
327
|
|
|
@@ -297,6 +336,13 @@ int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *
|
297
|
336
|
objs[i].active = 0;
|
298
|
337
|
objs[j].active = 0;
|
299
|
338
|
|
|
339
|
+ obj_cnt[objs[i].sprite]--;
|
|
340
|
+ obj_cnt[objs[j].sprite]--;
|
|
341
|
+
|
|
342
|
+ if (!is_splash) {
|
|
343
|
+ obj_respawn(RESPAWN_DISTANCE);
|
|
344
|
+ }
|
|
345
|
+
|
300
|
346
|
if (objs[j].sprite == SPR_LIGHT) {
|
301
|
347
|
(*score) += SCORE_LARGE;
|
302
|
348
|
} else {
|