123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- /*
- * obj.c
- * Duality
- *
- * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * See <http://www.gnu.org/licenses/>.
- */
-
- #include <gbdk/platform.h>
- #include <string.h>
- #include <stdlib.h>
-
- #include "gb/hardware.h"
- #include "sprites.h"
- #include "game.h"
- #include "obj.h"
-
- /*
- * sprite budget:
- *
- * fixed:
- * ship: 4
- * thruster: 1
- * health: 4
- * power: 4
- * --> 13 fixed
- *
- * hardware tiles: 40 - 13 = 27
- *
- * dynamic:
- * shot: 1
- * light: 4
- * dark: 4
- * --> 2x dark & 2x light = 16
- * --> 5x shot & 6x small = 11
- * --> 16 + 11 = 27
- */
- #define MAX_DARK 2
- #define MAX_LIGHT 2
- #define MAX_SHOT 5
- #define MAX_SHOT_DARK 3
- #define MAX_SHOT_LIGHT 3
- #define MAX_OBJ ((4 * MAX_DARK) + (4 * MAX_LIGHT) + MAX_SHOT + MAX_SHOT_DARK + MAX_SHOT_LIGHT)
-
- #define MAX_TRAVEL 32
-
- struct obj {
- uint8_t active;
- enum SPRITES sprite;
- int16_t off_x;
- int16_t off_y;
- int16_t spd_x;
- int16_t spd_y;
- uint8_t travel;
- };
-
- static struct obj objs[MAX_OBJ];
-
- void obj_init(void) {
- memset(objs, 0, sizeof(objs));
- }
-
- static uint8_t cnt_sprite(enum SPRITES sprite) {
- uint8_t cnt = 0;
- for (uint8_t i = 0; i < MAX_OBJ; i++) {
- if (!objs[i].active) {
- continue;
- }
- if (objs[i].sprite == sprite) {
- cnt++;
- }
- }
- return cnt;
- }
-
- enum OBJ_STATE obj_add(enum SPRITES sprite, int16_t off_x, int16_t off_y, int16_t spd_x, int16_t spd_y) {
- uint8_t obj_cnt = 0xFF;
- for (uint8_t i = 0; i < MAX_OBJ; i++) {
- if (!objs[i].active) {
- obj_cnt = i;
- break;
- }
- }
- if (obj_cnt >= MAX_OBJ) {
- return OBJ_LIST_FULL;
- }
-
- if (((sprite == SPR_DARK) && (cnt_sprite(sprite) >= MAX_DARK))
- || ((sprite == SPR_LIGHT) && (cnt_sprite(sprite) >= MAX_LIGHT))
- || ((sprite == SPR_SHOT) && (cnt_sprite(sprite) >= MAX_SHOT))
- || ((sprite == SPR_SHOT_DARK) && (cnt_sprite(sprite) >= MAX_SHOT_DARK))
- || ((sprite == SPR_SHOT_LIGHT) && (cnt_sprite(sprite) >= MAX_SHOT_LIGHT))) {
- return OBJ_TYPE_FULL;
- }
-
- objs[obj_cnt].active = 1;
- objs[obj_cnt].sprite = sprite;
- objs[obj_cnt].off_x = off_x << POS_SCALE_OBJS;
- objs[obj_cnt].off_y = off_y << POS_SCALE_OBJS;
- objs[obj_cnt].spd_x = spd_x;
- objs[obj_cnt].spd_y = spd_y;
- objs[obj_cnt].travel = 0;
-
- obj_cnt += 1;
- return OBJ_ADDED;
- }
-
- void obj_act(int16_t pos_x, int16_t pos_y, int16_t *spd_off_x, int16_t *spd_off_y) {
- pos_x += DEVICE_SPRITE_PX_OFFSET_X + (DEVICE_SCREEN_PX_WIDTH / 2) - 16;
- pos_y += DEVICE_SPRITE_PX_OFFSET_Y + (DEVICE_SCREEN_PX_HEIGHT / 2);
-
- for (uint8_t i = 0; i < MAX_OBJ; i++) {
- if (!objs[i].active) {
- continue;
- }
-
- switch (objs[i].sprite) {
- case SPR_DARK: {
- *spd_off_x += (objs[i].off_x - pos_x) >> 8;
- *spd_off_y += (objs[i].off_y - pos_y) >> 8;
- } break;
-
- default:
- break;
- }
- }
- }
-
- void obj_draw(int16_t spd_x, int16_t spd_y, uint8_t *hiwater) {
- for (uint8_t i = 0; i < MAX_OBJ; i++) {
- if (!objs[i].active) {
- continue;
- }
-
- // move objects by their speed and compensate for movement of the background / ship
- objs[i].off_x += objs[i].spd_x - spd_x;
- objs[i].off_y += objs[i].spd_y - spd_y;
-
- // only update travel time if we're actually moving
- if ((objs[i].spd_x != 0) || (objs[i].spd_y != 0)) {
- objs[i].travel += 1;
- }
-
- // remove objects that have traveled for too long
- if (objs[i].travel >= MAX_TRAVEL) {
- objs[i].active = 0;
- }
-
- spr_draw(objs[i].sprite, FLIP_NONE, objs[i].off_x >> POS_SCALE_OBJS, objs[i].off_y >> POS_SCALE_OBJS, hiwater);
- }
- }
|