From 1a58d58104a54911cb4229f20c18e9f68308331f Mon Sep 17 00:00:00 2001 From: Joao Paulo Oliveira Fernandes Date: Mon, 12 Feb 2024 21:34:07 -0300 Subject: [PATCH] rolling pillars to consider entire collision body as contact point --- base/Map.ts | 9 ++- base/game_events/GameEvent.ts | 2 +- base/interactable_objects/RollingPillar.ts | 79 ++++++++++++++++++---- 3 files changed, 73 insertions(+), 17 deletions(-) diff --git a/base/Map.ts b/base/Map.ts index c35669da51..a560d1c467 100644 --- a/base/Map.ts +++ b/base/Map.ts @@ -1419,8 +1419,9 @@ export class Map { * If no bounding box found, will fit map bounds to world size. * @param tile_x_pos the x tile position. * @param tile_y_pos the y tile position. + * @param apply_on_camera_view if true, will apply the bounds to camera. */ - set_map_bounds(tile_x_pos: number, tile_y_pos: number) { + set_map_bounds(tile_x_pos: number, tile_y_pos: number, apply_on_camera_view: boolean = true) { const x = get_px_position(tile_x_pos, this.tile_width); const y = get_px_position(tile_y_pos, this.tile_height); for (let i = 0; i < this.bounding_boxes.length; ++i) { @@ -1430,7 +1431,9 @@ export class Map { break; } } - this.change_camera_bounds(); + if (apply_on_camera_view) { + this.change_camera_bounds(); + } } /** @@ -2068,7 +2071,7 @@ export class Map { this.process_tiled_layers(); - this.set_map_bounds(hero_dest.x, hero_dest.y); + this.set_map_bounds(hero_dest.x, hero_dest.y, false); this.pre_processor_polygons(); diff --git a/base/game_events/GameEvent.ts b/base/game_events/GameEvent.ts index 4c6a0cd8f6..b63aa117c9 100644 --- a/base/game_events/GameEvent.ts +++ b/base/game_events/GameEvent.ts @@ -210,7 +210,7 @@ export abstract class GameEvent { /** Check if "Reveal" is currently active. If yes, then cancel it. */ check_reveal() { - if (this.data.hero.on_reveal && !this.keep_reveal) { + if (this.data.hero?.on_reveal && !this.keep_reveal) { (this.data.info.field_abilities_list.reveal as RevealFieldPsynergy).finish(false, false); } } diff --git a/base/interactable_objects/RollingPillar.ts b/base/interactable_objects/RollingPillar.ts index 1ec9b9b721..7ae0dfc90a 100644 --- a/base/interactable_objects/RollingPillar.ts +++ b/base/interactable_objects/RollingPillar.ts @@ -1,6 +1,12 @@ import {ControllableChar} from "../ControllableChar"; import {Map} from "../Map"; -import {base_actions, directions, get_centered_pos_in_px, get_distance, get_sqr_distance} from "../utils"; +import { + base_actions, + directions, + get_centered_pos_in_px, + get_distance, + get_tile_position, +} from "../utils"; import {InteractableObjects} from "./InteractableObjects"; import * as _ from "lodash"; import {GameEvent, game_event_origin} from "../game_events/GameEvent"; @@ -152,6 +158,18 @@ export class RollablePillar extends InteractableObjects { char.trying_to_push = true; if (char.push_timer === null) { char.set_trying_to_push_direction(char.current_direction); + if ( + [directions.down, directions.up].includes(char.trying_to_push_direction) && + this._pillar_direction === pillar_directions.VERTICAL + ) { + return false; + } + if ( + [directions.left, directions.right].includes(char.trying_to_push_direction) && + this._pillar_direction === pillar_directions.HORIZONTAL + ) { + return false; + } char.set_push_timer(() => { if (!this.data.main_menu.open && !this.data.save_menu.open) { this.define_pillar_direction(char); @@ -186,10 +204,16 @@ export class RollablePillar extends InteractableObjects { return; } - const get_extreme = (index: number, init: number, func: "max" | "min", axis: "x" | "y") => { + const get_extreme = ( + io: InteractableObjects, + index: number, + init: number, + func: "max" | "min", + axis: "x" | "y" + ) => { return ( - this.body.world.mpx( - this.body.data.shapes.reduce((acc, cur) => { + io.body.world.mpx( + io.body.data.shapes.reduce((acc, cur) => { return Math[func]( acc, cur.vertices.reduce((acc, cur) => { @@ -197,13 +221,15 @@ export class RollablePillar extends InteractableObjects { }, init) ); }, init) - ) + this[axis] + ) + io[axis] ); }; - const min_x = get_extreme(0, Infinity, "min", "x"); - const max_x = get_extreme(0, -Infinity, "max", "x"); - const min_y = get_extreme(1, Infinity, "min", "y"); - const max_y = get_extreme(1, -Infinity, "max", "y"); + const min_x = get_extreme(this, 0, Infinity, "min", "x"); + const max_x = get_extreme(this, 0, -Infinity, "max", "x"); + const min_y = get_extreme(this, 1, Infinity, "min", "y"); + const max_y = get_extreme(this, 1, -Infinity, "max", "y"); + + const cartesian = (...a) => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat()))); let next_contact: RollablePillar["_contact_points"][0] = null; let last_distance = Infinity; @@ -216,11 +242,38 @@ export class RollablePillar extends InteractableObjects { !io.allow_jumping_over_it && !io.allow_jumping_through_it && io.shapes_collision_active && - io.base_collision_layer === this.base_collision_layer && - ((this._pillar_direction === pillar_directions.VERTICAL && io.y >= min_y && io.y <= max_y) || - (this._pillar_direction === pillar_directions.HORIZONTAL && io.x >= min_x && io.x <= max_x)) + io.base_collision_layer === this.base_collision_layer ) { - return [io.tile_pos]; + const bounds = { + min_x: get_extreme(io, 0, Infinity, "min", "x"), + max_x: get_extreme(io, 0, -Infinity, "max", "x"), + min_y: get_extreme(io, 1, Infinity, "min", "y"), + max_y: get_extreme(io, 1, -Infinity, "max", "y"), + }; + if ( + (this._pillar_direction === pillar_directions.VERTICAL && + bounds.max_y >= min_y && + bounds.min_y <= max_y) || + (this._pillar_direction === pillar_directions.HORIZONTAL && + bounds.max_x >= min_x && + bounds.min_x <= max_x) + ) { + bounds.min_x = get_tile_position(bounds.min_x | 0, this.data.map.tile_width); + bounds.max_x = get_tile_position(bounds.max_x | 0, this.data.map.tile_width); + bounds.min_y = get_tile_position(bounds.min_y | 0, this.data.map.tile_height); + bounds.max_y = get_tile_position(bounds.max_y | 0, this.data.map.tile_height); + return cartesian( + _.range(bounds.min_x, bounds.max_x + 1), + _.range(bounds.min_y, bounds.max_y + 1) + ).map(pos => { + return { + x: pos[0], + y: pos[1], + }; + }); + } else { + return []; + } } else { return []; }