diff --git a/assets/levels/COMMON/OBJ.TIM b/assets/levels/COMMON/OBJ.TIM index 1933596..e0e464c 100644 Binary files a/assets/levels/COMMON/OBJ.TIM and b/assets/levels/COMMON/OBJ.TIM differ diff --git a/assets/levels/COMMON/obj.png b/assets/levels/COMMON/obj.png index 727e581..6e6b47f 100644 Binary files a/assets/levels/COMMON/obj.png and b/assets/levels/COMMON/obj.png differ diff --git a/assets/levels/COMMON/obj_common_designtiles.png b/assets/levels/COMMON/obj_common_designtiles.png index b0e90c4..378e9de 100644 Binary files a/assets/levels/COMMON/obj_common_designtiles.png and b/assets/levels/COMMON/obj_common_designtiles.png differ diff --git a/assets/levels/COMMON/objects_common.toml b/assets/levels/COMMON/objects_common.toml index b1e0aa8..3e22b11 100644 --- a/assets/levels/COMMON/objects_common.toml +++ b/assets/levels/COMMON/objects_common.toml @@ -308,6 +308,37 @@ duration = 0 frames = [[144, 72, 32, 8]] loopback = 0 + +# ============ + +[explosion] + +[[explosion.animations]] +name = "small" +id = 0 +duration = 4 +frames = [ + [48, 136, 32, 32], + [80, 136, 32, 32], + [112, 136, 32, 32], + [144, 136, 48, 48], + [192, 136, 48, 48], +] +loopback = -1 + +[[explosion.animations]] +name = "big" +id = 0 +duration = 4 +frames = [ + [48, 136, 32, 32], + [80, 168, 32, 32], + [112, 168, 32, 32], + [144, 136, 48, 48], + [192, 136, 48, 48], +] +loopback = -1 + # ============ # Dummy objects # ============ diff --git a/assets/levels/COMMON/objects_common.tsx b/assets/levels/COMMON/objects_common.tsx index 4f57b71..9c8956c 100644 --- a/assets/levels/COMMON/objects_common.tsx +++ b/assets/levels/COMMON/objects_common.tsx @@ -49,4 +49,5 @@ + diff --git a/assets/levels/COMMON/objs_common_texture.xcf b/assets/levels/COMMON/objs_common_texture.xcf index 6f9e8f2..e6319a4 100644 Binary files a/assets/levels/COMMON/objs_common_texture.xcf and b/assets/levels/COMMON/objs_common_texture.xcf differ diff --git a/include/object.h b/include/object.h index 15c71c0..b620bab 100644 --- a/include/object.h +++ b/include/object.h @@ -24,6 +24,7 @@ typedef enum { OBJ_SPRING_RED_DIAGONAL = 0x07, OBJ_SWITCH = 0x08, OBJ_GOAL_SIGN = 0x09, + OBJ_EXPLOSION = 0x0a, } ObjectType; #define MASK_FLIP_FLIPX 0x1 // Flip on X axis diff --git a/src/main.c b/src/main.c index 7761f1e..44a8542 100644 --- a/src/main.c +++ b/src/main.c @@ -26,7 +26,7 @@ Locations of common textures on frame buffer: ================================================ Player 1: 320x0; CLUT: 0x480 - Common objects: 576x0; CLUT: 0x481 + Common objects: 576x0; CLUT: 0x481 (8-bit only) Level tiles: 448x0; CLUT: 0x482 (if exists) Level BG0: 448x256; CLUT: 0x483 (4-bit only) Level BG1: 512x256; CLUT: 0x484 (4-bit only) diff --git a/src/object.c b/src/object.c index acec051..83ddf6f 100644 --- a/src/object.c +++ b/src/object.c @@ -60,6 +60,7 @@ load_object_table(const char *filename, ObjectTable *tbl) // Entry ID, always sequential; discarded for now uint8_t _id = get_byte(bytes, &b); (void)(_id); + /* printf("Load object 0x%04x\n", _id); */ uint8_t has_fragment = get_byte(bytes, &b); entry->num_animations = get_short_be(bytes, &b); diff --git a/src/object_state.c b/src/object_state.c index b61417d..0a8b5ff 100644 --- a/src/object_state.c +++ b/src/object_state.c @@ -272,7 +272,7 @@ begin_render_routine: // Sprites: 576x0 // CLUT: 0x481 - poly->tpage = getTPage(0, 0, 576, 0); + poly->tpage = getTPage(1, 0, 576, 0); poly->clut = getClut(0, 481); sort_prim(poly, state->id == OBJ_RING ? OTZ_LAYER_OBJECTS : OTZ_LAYER_PLAYER); diff --git a/src/object_state_update.c b/src/object_state_update.c index b6033b0..7e4a621 100644 --- a/src/object_state_update.c +++ b/src/object_state_update.c @@ -42,6 +42,7 @@ static void _spring_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos, static void _spring_diagonal_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos, uint8_t is_red); static void _checkpoint_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos); static void _spikes_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos); +static void _explosion_update(ObjectState *state, ObjectTableEntry *, VECTOR *); // Player hitbox information. Calculated once per frame. static int32_t player_vx, player_vy; // Top left corner of player hitbox @@ -100,6 +101,7 @@ object_update(ObjectState *state, ObjectTableEntry *typedata, VECTOR *pos) case OBJ_SPRING_RED_DIAGONAL: _spring_diagonal_update(state, typedata, pos, 1); break; case OBJ_CHECKPOINT: _checkpoint_update(state, typedata, pos); break; case OBJ_SPIKES: _spikes_update(state, typedata, pos); break; + case OBJ_EXPLOSION: _explosion_update(state, typedata, pos); break; } } @@ -247,6 +249,12 @@ _monitor_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos) level_score_count += 10; sound_play_vag(sfx_pop, 0); + // Create explosion effect + PoolObject *explosion = object_pool_create(OBJ_EXPLOSION); + explosion->freepos.vx = (pos->vx << 12); + explosion->freepos.vy = (pos->vy << 12); + explosion->state.anim_state.animation = 0; // Small explosion + // TODO: This should be the behaviour of our monitor particles switch(((MonitorExtra *)state->extra)->kind) { case MONITOR_KIND_RING: @@ -495,3 +503,13 @@ _spikes_update(ObjectState *state, ObjectTableEntry *, VECTOR *pos) } } } + + +static void +_explosion_update(ObjectState *state, ObjectTableEntry *, VECTOR *) +{ + // Explosions are simple particles: their animation is finished? + // If so, destroy. + if(state->anim_state.animation == OBJ_ANIMATION_NO_ANIMATION) + state->props |= OBJ_FLAG_DESTROYED; +} diff --git a/src/screen_level.c b/src/screen_level.c index 8f779a5..76b57bd 100644 --- a/src/screen_level.c +++ b/src/screen_level.c @@ -262,8 +262,8 @@ screen_level_draw(void *d) /* render_model(&data->ring); */ - render_lvl(&leveldata, &map128, &map16, &obj_table_common, camera.pos.vx, camera.pos.vy); object_pool_render(&obj_table_common, camera.pos.vx, camera.pos.vy); + render_lvl(&leveldata, &map128, &map16, &obj_table_common, camera.pos.vx, camera.pos.vy); parallax_draw(&data->parallax, &camera); // Gouraud-shaded cube diff --git a/tools/cookobj/datatypes.py b/tools/cookobj/datatypes.py index aff876c..1c3448d 100644 --- a/tools/cookobj/datatypes.py +++ b/tools/cookobj/datatypes.py @@ -26,16 +26,21 @@ class DummyObjectId(Enum): class ObjectId(Enum): - RING = 0 - MONITOR = 1 - SPIKES = 2 - CHECKPOINT = 3 - SPRING_YELLOW = 4 - SPRING_RED = 5 - SPRING_YELLOW_DIAGONAL = 6 - SPRING_RED_DIAGONAL = 7 - SWITCH = 8 - GOAL_SIGN = 9 + RING = 0x00 + MONITOR = 0x01 + SPIKES = 0x02 + CHECKPOINT = 0x03 + SPRING_YELLOW = 0x04 + SPRING_RED = 0x05 + SPRING_YELLOW_DIAGONAL = 0x06 + SPRING_RED_DIAGONAL = 0x07 + SWITCH = 0x08 + GOAL_SIGN = 0x09 + + # Certain objects simply cannot be placed. + # This happens when the object in question is a particle + # or effect. + EXPLOSION = 0x0a @staticmethod def get(name): @@ -50,6 +55,7 @@ class ObjectId(Enum): "spring_red_diagonal": ObjectId.SPRING_RED_DIAGONAL, "goal_sign": ObjectId.GOAL_SIGN, "switch": ObjectId.SWITCH, + "explosion": ObjectId.EXPLOSION, } result = switch.get(name.lower()) assert result is not None, f"Unknown common object {name}" diff --git a/tools/layouts/otd.hexpat b/tools/layouts/otd.hexpat index 69399ab..e9faf18 100644 --- a/tools/layouts/otd.hexpat +++ b/tools/layouts/otd.hexpat @@ -11,6 +11,7 @@ enum CommonId: s8 { SPRING_RED_DIAGONAL = 7, GOAL_SIGN = 8, SWITCH = 9, + EXPLOSION = 10, }; bitfield FlipMask {