09-11-2025, 05:42 PM
(This post was last modified: 09-11-2025, 07:12 PM by 5Brainplay.)
@A.I. Topical Post. Tag.
I upgraded FPLE Ace Using Claude.AI, Integrated a 4-Side & 6-Side box comment, which can create buildings/grass boxes/objects.
6 Side had type2+d1 & type1+d1)) but changed it to a type 0 to save FPS, you can add it back if you want.
For below/Above, type 0 objects you want to walk over add, 1-Side, to them.
I added code the following code so these player facing objects without 1-Side push forward, for NPCs.
if dy == 0 && dx == 0 && surface.character.fple_type == 0 && surface.character.fple_one_side == false.
(Fit,Type1,D1,1Side,V2) objects have a side profile added to them, but should always be, same not below/above.
you can jump over these with a moveset thuf-on/step forward step forward thur-off, they are a type of ledge.
You may have to code in your own. (Fit,Type2,D1,1Side,V2), I'm not currently tested to check its same function.
I've worked out a fix for rotation letting you see events thur walls briefly, here is the 1st rough draft of the script.
I would have posted a few days sooner, but was having issues with strafing crashing the game for some reason.
The resolution is also no longer Default, it's 608x417, you can place it back with the original script, or pick Res 2.
The Enhanced Script requires Background Addon to function properly, I've not worked out the private call issue.
I upgraded FPLE Ace Using Claude.AI, Integrated a 4-Side & 6-Side box comment, which can create buildings/grass boxes/objects.
6 Side had type2+d1 & type1+d1)) but changed it to a type 0 to save FPS, you can add it back if you want.
For below/Above, type 0 objects you want to walk over add, 1-Side, to them.
I added code the following code so these player facing objects without 1-Side push forward, for NPCs.
if dy == 0 && dx == 0 && surface.character.fple_type == 0 && surface.character.fple_one_side == false.
(Fit,Type1,D1,1Side,V2) objects have a side profile added to them, but should always be, same not below/above.
you can jump over these with a moveset thuf-on/step forward step forward thur-off, they are a type of ledge.
You may have to code in your own. (Fit,Type2,D1,1Side,V2), I'm not currently tested to check its same function.
I've worked out a fix for rotation letting you see events thur walls briefly, here is the 1st rough draft of the script.
I would have posted a few days sooner, but was having issues with strafing crashing the game for some reason.
The resolution is also no longer Default, it's 608x417, you can place it back with the original script, or pick Res 2.
The Enhanced Script requires Background Addon to function properly, I've not worked out the private call issue.
Code:
#========================Author: MGC=============================
# First Person Labyrinth Explorer (FPLE) Engine - VX Ace version.
# v.1.5 old, now upgraded to v.1.8 using Claude.AI by 5Brainplay.
#================================================================
# This script allows the map to be displayed in first-person view,
# while maintaining tile-by-tile movement, similar to the
# Etrian Odyssey series (Nintendo DS/3DS). # THIS IS NOT A SCRIPT FOR MAKING AN FPS, BUT AN FPRPG.
#
# This is a port of version 1.5 of the FPLE for RPG Maker XP, with
# a few small additions.
#
# Features:
# - Can only be enabled on certain maps in the project
# - Forward/backward movement, left/right movement
# and 90° rotation
# - Ability to lower quality while moving to reduce lag
# - Translucency and blend type support
# for events
#
# Limitations:
# - Not really suitable for moving events from one tile to another.
# This should work, but use sparingly. # - Animations are displayed above everything
# - The player cannot jump or move diagonally
# - The resolution must be the default, i.e., 544px x 416px
# - No transparency for walls
# - No different heights: a single level for the floor and ceiling
#
# Instructions:
# This script must be placed below the original scripts but above "Main"
# It requires the MGC_FPLE_Ace_1_1.dll file
#
# - Map Creation
# Maps must be exported into the project from the dedicated editor,
# present in the Marta project starting with version 1.0.0
#
# - Events
# Events with a graphical representation are displayed
# vertically (like walls), centered, and always facing the
# player. The "Comment..." command allows you to control this display:
# "Type 0": Always faces the player (default)
# "Type 1": Horizontally oriented in the RM editor view (top view)
# "Type 2": Vertically oriented in the RM editor view (top view)
# "Stretch": The image is stretched to the dimensions of a wall (square)
# "Fit": The image is stretched to fit within the dimensions of a wall, the
# aspect ratio is maintained. Automatically applied if
# the dimensions exceed those of a wall (new in VX Ace)
# "Zoom X.X": zoom the image (new in VX Ace), for example, to double
# the dimensions, write: "Zoom 2.0"
# "V-Align 0": vertical alignment at the top (at ceiling level)
# "V-Align 1": vertical alignment in the center (default)
# "V-Align 2": vertical alignment at the bottom (at floor level)
# "D-Align 0": depth alignment in front/left, for types 1 and 2
# "D-Align 1": depth alignment in the center, for types 1 and 2 (default)
# "D-Align 2": depth alignment in the back/right, for types 1 and 2
# "1-Side": texture applied to one side only => appears mirrored behind
# "2-Side": texture applied to two side only => appears mirrored behind #Extra Unused Call To Code#
# "4-Side": texture applied to four sides to create the illusion of box
# "6-Side": texture applied to four sides to create the illusion of grass.
# - Technical Parameters
# In the CONFIGURATION section at the beginning of the script, you will find the
# following constants whose values can be modified:
# - VIEW_DISTANCE: "Surfaces" (textured square polygons of fixed
# dimensions representing tiles and events) are only
# displayed within a certain distance around
# the player. This constant represents this distance,
# expressed in tiles (default value: 6). The higher
# this value, the greater the risk of lag.
# - RESOLUTION: Drawing the entire screen every frame requires
# a lot of resources. During movement, it is
# possible to use a lower screen resolution and the
# Render will then be zoomed to fit 544px x 416px.
# 0: Maximum resolution (544px*416px) Changed to (840px*560px)
# 1: Medium resolution (408px*312px) Changed to (608px*417px)
# 2: Low resolution (272px*208px) Changed to (544px*417px)
# 3: Minimum resolution (204px*156px) Changed to (408px*278px)
# 4: Test resolution (204px*156px) Changed to (332px*222px)
# - ALWAYS_SAME_RES: If true, the same resolution will be used when stationary
# as when moving (see RESOLUTION)
# If false, the maximum resolution will be used when stationary
# (default value)
# - LIGHT_DISTANCE: To prevent surfaces from suddenly appearing on the screen,
# this constant represents the distance in tiles beyond
# which the opacity of the surfaces will be zero.
# The opacity change is gradual. If there is
# no parallax, the screen background is black and the
# surfaces will become increasingly darker with distance.
# A value of 0 disables this feature.
#
# - Commands that can be used in scripts (possible via the "Script..."
# command of an event):
# - $game_temp.set_view(new_view_distance)
# - $game_temp.set_light(new_light_distance)
# - $game_temp.increase_light
# - $game_temp.decrease_light
#============================
module FPLE
#-----------------------------
# * CONFIGURATION
#-----------------------------
VIEW_DISTANCE = 22 # in tiles, > 0
LIGHT_DISTANCE = 11 # in tiles, >=0, 0=deactivated
RESOLUTION = 1 # quality when moving, 0=max, 1=medium, 2=low, 3=ugly
ALWAYS_SAME_RES = true # if true, quality at stand = quality when moving
# if false, quality at stand = quality max
SKIP_DISTANT_CHARS = true # Skip character updates beyond view distance
BATCH_SURFACE_UPDATES = true # Update surfaces in batches
AGGRESSIVE_CULLING = true # More aggressive visibility culling
end
#==============================
# ** FPLE Core
#==============================
module FPLE
#-----------------------------
# * Constantes
#-----------------------------
MAP_SIDES = [4, 3, 5, 2]
MAP_SIDES_LEFT = [5, 4, 2, 3]
MAP_SIDES_RIGHT = [3, 2, 4, 5]
PLAYER_MOVE_FORWARD = [[0, 1], [-1, 0], [1, 0], [0, -1]]
PLAYER_MOVE_SPEED = [0, 1, 2, 4, 6, 8, 12]
TURN_LEFT = [6, 2, 8, 4]
COS_TABLE = [4096, 4095, 4094, 4090, 4086,
4080, 4074, 4065, 4056, 4046, 4034, 4021, 4006, 3991, 3974,
3956, 3937, 3917, 3896, 3873, 3849, 3824, 3798, 3770, 3742,
3712, 3681, 3650, 3617, 3582, 3547, 3511, 3474, 3435, 3396,
3355, 3314, 3271, 3228, 3183, 3138, 3091, 3044, 2996, 2946,
2896, 2845, 2793, 2741, 2687, 2633, 2578, 2522, 2465, 2408,
2349, 2290, 2231, 2171, 2110, 2048, 1986, 1923, 1860, 1796,
1731, 1666, 1600, 1534, 1468, 1401, 1334, 1266, 1198, 1129,
1060, 991, 921, 852, 782, 711, 641, 570, 499, 428,
357, 286, 214, 143, 71, 0]
RENDER = Win32API.new("MGC_FPLE_Ace_1_2", "RenderFPLE", "lll", "l") # [1.5]
RENDER_ROT = Win32API.new("MGC_FPLE_Ace_1_2", "RenderFPLErot", "lll", "l") # [1.5]
#-----------------------------
# * Retourne l'angle d'orientation
# return Integer
#-----------------------------
def self.angle
return @angle
end
#-----------------------------
# * Retourne le décalage horizontal
# return Integer
#-----------------------------
def self.offset_x
return @offset_x
end
#-----------------------------
# * Retourne le décalage en profondeur
# return Integer
#-----------------------------
def self.offset_y
return @offset_y
end
#-----------------------------
# * Initialisation
# param spriteset : FPLE::Spriteset_Map
# param viewport : Viewport
#-----------------------------
def self.initialize_fple(spriteset, viewport)
@spriteset = spriteset
@sprite_screen = Sprite.new(viewport)
@sprite_move = Sprite.new(viewport)
self.initialize_bitmaps
@offset_x = 0
@offset_y = 0
@sprite_move.visible = false
@lux_distance = $game_system.fple_light_distance << 5
@angle = 0
@trig = 0
self.refresh_trig
@count = 0
$game_temp.force_render = true
self.update
end
#-----------------------------
# * Création des objets Bitmap devant contenir le rendu 3D
#-----------------------------
def self.initialize_bitmaps
case $game_system.fple_resolution
when 0
width = 840
height = 560
coefficient_resolution = 0.75
when 1
width = 608
height = 417
coefficient_resolution = 1
when 2
width = 544
height = 417
coefficient_resolution = 1.133
when 3
width = 408
height = 278
coefficient_resolution = 1.5
when 4
width = 332
height = 222
coefficient_resolution = 2
end
if $game_system.fple_always_same_res
@sprite_screen.bitmap = Bitmap.new(width, height)
@sprite_screen.zoom_x = coefficient_resolution
@sprite_screen.zoom_y = coefficient_resolution
else
@sprite_screen.bitmap = Bitmap.new(608, 417)
end
@sprite_move.bitmap = Bitmap.new(width, height)
@sprite_move.zoom_x = coefficient_resolution
@sprite_move.zoom_y = coefficient_resolution
end
#-----------------------------
# * Cherche les valeurs de sinus et cosinus en focntion de l'angle
#-----------------------------
def self.refresh_trig
@cos = FPLE::COS_TABLE[@angle]
@sin = FPLE::COS_TABLE[91 - @angle]
end
#-----------------------------
# * Dispose
#-----------------------------
def self.dispose
@sprite_screen.dispose
@sprite_move.dispose
end
#-----------------------------
# * Frame Update
#-----------------------------
# Modify the update method to use a more complete background fill
def self.update
# Run garbage collection periodically during non-movement to reduce memory spikes.
if !$game_temp.movement && Graphics.frame_count % 120 == 0
GC.start
end
# Check if the player is actively moving or changing the view.
if $game_temp.movement
case $game_temp.movement_dir
when 0 # fading distance + 1
self.increase_fading_distance
when 1 # fading distance - 1
self.decrease_fading_distance
when 3 # set fading distance
self.set_fading_distance
when 2 # Move backward
self.move_backward
when 4 # Strafe left
self.strafe_left
when 6 # Strafe right
self.strafe_right
when 8 # Move forward
self.move_forward
when 9 # Turn right
self.turn_right
when 10 # turn left
self.turn_left
end
# Apply method 2 refactoring for sprite and rendering logic
sprite_moving = $game_temp.movement
active_sprite = sprite_moving ? @sprite_move : @sprite_screen
inactive_sprite = sprite_moving ? @sprite_screen : @sprite_move
active_sprite.visible = true
inactive_sprite.visible = false
if @angle != 0
# Use lighter background color during rotation to prevent bleeding
bg_color = Color.new(115, 190, 215, 255) # Much lighter sky blue background
active_sprite.bitmap.fill_rect(0, 0, active_sprite.bitmap.width,
active_sprite.bitmap.height, bg_color)
end
# Clear the active sprite bitmap
active_sprite.bitmap.clear unless $game_temp.movement_dir == 9 || $game_temp.movement_dir == 10
# Determine if we should use rotation (only during movement and when angle != 0)
use_rotation = sprite_moving && @angle != 0
if use_rotation
params = [@offset_y, @offset_x, @lux_distance, $game_player.direction, @trig, @cos, @sin, $game_map.fple_map.texturesets]
FPLE::RENDER_ROT.call(active_sprite.bitmap.__id__, $game_map.surfaces.__id__, params.__id__)
else
params = [@offset_y, @offset_x, @lux_distance, $game_player.direction, $game_map.fple_map.texturesets]
FPLE::RENDER.call(active_sprite.bitmap.__id__, $game_map.surfaces.__id__, params.__id__)
end
# Handle post-movement logic
unless sprite_moving
$game_player.update_nonmoving($game_temp.last_moving) if $game_temp.last_moving
end
# This block handles rendering when the player is not moving, but other
# events or conditions (like character surfaces) need updating.
elsif $game_player.moving? || $game_temp.force_render
# Process updates for characters and events.
$game_map.refresh_surfaces
# Extract common character update logic to avoid duplication
update_character = lambda do |event|
# Only process if SKIP_DISTANT_CHARS is enabled
return unless FPLE::SKIP_DISTANT_CHARS
dist_x = ($game_player.real_x / 32) - (event.x)
dist_y = ($game_player.real_y / 32) - (event.y)
distance = Math.sqrt(dist_x**2 + dist_y**2)
return if distance > FPLE::VIEW_DISTANCE
event.update_fple_surface
end
# === START OF BATCH AND CULLING FIX ===
# Updates characters in batches to avoid lag spikes, with optional distance skipping.
if FPLE::BATCH_SURFACE_UPDATES
$game_map.events.values.each_with_index do |event, i|
# Only update a fraction of the events each frame.
if @count % 5 == i % 5
update_character.call(event)
end
end
else
# Fallback for no batching.
$game_map.events.each_value(&update_character)
end
# === END OF BATCH AND CULLING FIX ===
$game_map.refresh_character_surfaces(@spriteset.character_surfaces)
@sprite_screen.bitmap.clear
# Use consistent parameter structure
params = [@offset_y, @offset_x, @lux_distance, $game_player.direction, $game_map.fple_map.texturesets]
FPLE::RENDER.call(@sprite_screen.bitmap.__id__, $game_map.surfaces.__id__, params.__id__)
$game_temp.force_render = false
@count += 1
end
end
#-----------------------------
# * Frame Update - Augmentation de la distance d'éclairage
#-----------------------------
def self.increase_fading_distance
@count += 2
@lux_distance += 2
if @count == 32
@count = 0
$game_temp.movement = false
end
end
#-----------------------------
# * Frame Update - Diminution de la distance d'éclairage
#-----------------------------
def self.decrease_fading_distance
if @lux_distance == 0
@count = 0
$game_temp.movement = false
else
@count += 2
@lux_distance -= 2
if @count == 32
@count = 0
$game_temp.movement = false
end
end
end
#-----------------------------
# * Frame Update - Définition d'une nouvelle distance d'éclairage
#-----------------------------
def self.set_fading_distance
@lux_distance = $game_system.fple_light_distance << 5
$game_temp.movement = false
end
#-----------------------------
# * Frame Update - Déplacement en arrière
#-----------------------------
def self.move_backward
unless $game_temp.movement_init
$game_map.refresh_surfaces
$game_map.refresh_character_surfaces(@spriteset.character_surfaces)
$game_temp.movement_init = true
@offset_y = 128
end
@offset_y -= $game_player.move_speed_fple
if @offset_y <= 0
@offset_y = 0
$game_temp.movement = false
$game_temp.last_moving = true
$game_map.refresh_surfaces
$game_map.refresh_character_surfaces(@spriteset.character_surfaces)
end
end
#-----------------------------
# * Frame Update - Déplacement latéral vers la gauche
#-----------------------------
def self.strafe_left
unless $game_temp.movement_init
$game_map.refresh_surfaces
$game_map.refresh_surfaces_strafe(0)
$game_map.refresh_character_surfaces(@spriteset.character_surfaces)
$game_temp.movement_init = true
@offset_x = 128
end
@offset_x -= $game_player.move_speed_fple
if @offset_x <= 0
@offset_x = 0
$game_temp.movement = false
$game_temp.last_moving = true
$game_map.refresh_surfaces
$game_map.refresh_character_surfaces(@spriteset.character_surfaces)
end
end
#-----------------------------
# * Frame Update - Déplacement latéral vers la droite
#-----------------------------
def self.strafe_right
unless $game_temp.movement_init
$game_map.refresh_surfaces_strafe(-1)
$game_temp.movement_init = true
end
@offset_x += $game_player.move_speed_fple
if @offset_x >= 128
@offset_x = 0
$game_temp.movement = false
$game_temp.last_moving = true
$game_map.refresh_surfaces
$game_map.refresh_character_surfaces(@spriteset.character_surfaces)
end
end
#-----------------------------
# * Frame Update - Déplacement en avant
#-----------------------------
def self.move_forward
@offset_y += $game_player.move_speed_fple
if @offset_y >= 128
@offset_y = 0
$game_temp.movement = false
$game_temp.last_moving = true
$game_map.refresh_surfaces
$game_map.refresh_character_surfaces(@spriteset.character_surfaces)
end
end
#-----------------------------
# * Frame Update - Rotation vers la droite
#-----------------------------
def self.turn_right
unless $game_temp.movement_init
$game_map.refresh_surfaces_turn_right(@spriteset.character_surfaces)
$game_temp.movement_init = true
end
@angle += 5
@trig = 1
refresh_trig
if @angle == 90
@angle = 0
$game_temp.movement = false
$game_map.refresh_surfaces
$game_map.refresh_character_surfaces(@spriteset.character_surfaces)
end
end
#-----------------------------
# * Frame Update - Rotation vers la gauche
#-----------------------------
def self.turn_left
unless $game_temp.movement_init
$game_map.refresh_surfaces_turn_left(@spriteset.character_surfaces)
$game_temp.movement_init = true
@angle = 90
end
@angle -= 5
@trig = 0
refresh_trig
if @angle == 0
$game_temp.movement = false
$game_map.refresh_surfaces
$game_map.refresh_character_surfaces(@spriteset.character_surfaces)
end
end
end
#==============================
# ** DataManager
#==============================
module DataManager
#-----------------------------
# * Aliased methods (F12 compatibility)
#-----------------------------
class << self
unless @already_aliased_fple
alias save_game_without_rescue_fple save_game_without_rescue
@already_aliased_fple = true
end
end
#-----------------------------
# * Execute Save (No Exception Processing)
#-----------------------------
def self.save_game_without_rescue(index)
if $game_map.fple_map # [1.2]
textureset = $game_map.fple_map.textureset
texturesets = $game_map.fple_map.texturesets
$game_map.fple_map.textureset = nil
$game_map.fple_map.texturesets = nil
end
rc = save_game_without_rescue_fple(index)
if $game_map.fple_map # [1.2]
$game_map.fple_map.texturesets = texturesets
$game_map.fple_map.textureset = textureset
end
return rc
end
end
#============================
# ** Game_System
#============================
class Game_System
#-----------------------------
# * Aliased methods (F12 compatibility)
#-----------------------------
unless @already_aliased_fple
alias initialize_fple initialize
@already_aliased_fple = true
end
#-----------------------------
# * Public Instance Variables
#-----------------------------
attr_accessor :fple # Boolean
attr_accessor :fple_view_distance # Integer (>0)
attr_accessor :fple_light_distance # Integer (>=0, 0:deactivated)
attr_accessor :fple_resolution # Integer (0:max, 1:medium, 2:low, 3:ugly)
attr_accessor :fple_always_same_res # Boolean
#-----------------------------
# * Object Initialization
#-----------------------------
def initialize
initialize_fple
self.fple = false
self.fple_view_distance = FPLE::VIEW_DISTANCE
self.fple_light_distance = FPLE::LIGHT_DISTANCE
self.fple_resolution = FPLE::RESOLUTION
self.fple_always_same_res = FPLE::ALWAYS_SAME_RES
end
end
#==============================
# ** Game_Temp
#==============================
class Game_Temp
#-----------------------------
# * Aliased methods (F12 compatibility)
#-----------------------------
unless @already_aliased_fple
alias initialize_fple initialize
@already_aliased_fple = true
end
#-----------------------------
# * Public Instance Variables
#-----------------------------
attr_accessor :movement_init # Boolean
attr_accessor :movement # Boolean
attr_accessor :movement_dir # Integer {2, 4, 6, 8}
attr_accessor :last_moving # Boolean
attr_accessor :force_render # Boolean
#-----------------------------
# * Object Initialization
#-----------------------------
def initialize
initialize_fple
self.movement_init = false
self.movement = false
self.movement_dir = 8
self.last_moving = false
self.force_render = false
end
#-----------------------------
# * Set view distance
# param distance : Integer
#-----------------------------
def set_view(distance)
if distance < 0 then distance = 0 end
$game_system.fple_view_distance = distance
self.force_render = true
end
#-----------------------------
# * Set light distance
# param distance : Integer
#-----------------------------
def set_light(distance)
if distance < 0 then distance = 0 end
$game_system.fple_light_distance = distance
self.movement = true
self.movement_dir = 3
end
#-----------------------------
# * Increase light distance
#-----------------------------
def increase_light
$game_system.fple_light_distance += 1
self.movement = true
self.movement_dir = 0
end
#-----------------------------
# * Decrease light distance
#-----------------------------
def decrease_light
if $game_system.fple_light_distance > 0
$game_system.fple_light_distance -= 1
end
self.movement = true
self.movement_dir = 1
end
end
#============================
# ** Game_Map
#============================
class Game_Map
public
#-----------------------------
# * Aliased methods (F12 compatibility)
#-----------------------------
unless @already_aliased_fple
alias initialize_fple initialize
alias setup_fple setup
alias refresh_fple refresh
@already_aliased_fple = true
end
#-----------------------------
# * Public Instance Variables
#-----------------------------
attr_accessor :surfaces # Array<Array<Integer>>
#-----------------------------
# * Object Initialization
#-----------------------------
def initialize
initialize_fple
self.surfaces = []
@x_ref = 0
@y_ref = 0
@distance_cache = {}
@last_player_pos = [0, 0]
end
#-----------------------------
# * Setup
# param map_id : Integer
#-----------------------------
def setup(map_id)
@map_id = map_id
@map = load_data(sprintf("Data/Map%03d.rvdata2", @map_id))
if is_fple?
load_fple_map
$game_system.fple = true
elsif $game_system.fple
$game_system.fple = false
end
setup_fple(map_id)
end
#-----------------------------
# * Refresh
#-----------------------------
def refresh
refresh_fple
if is_fple?
unless @fple_map.textureset
load_fple_map
end
end
end
#-----------------------------
# * Vérifie s'il s'agit d'une carte FPLE
# return String
#-----------------------------
def is_fple?
return @map.note[/\[fple:\w+\]/]
end
#-----------------------------
# * Charge la carte FPLE associée
#-----------------------------
def load_fple_map
if @fple_map then @fple_map.dispose end
@map.note[/\[fple:(\w+)\]/]
File.open('Data_FPLE/' + $1 + '.fple', "rb") {|file|
map_data = Marshal.load(file)
@fple_map = FPLE::Map.new(map_data.width, map_data.height,
map_data.map_name, map_data.tileset_name, map_data.data,
map_data.subsets_mapping, map_data.textureset_data)
}
end
#-----------------------------
# * Retourne la carte FPLE associée
# return FPLE::Map
#-----------------------------
def fple_map
@fple_map
end
#-----------------------------
# * Retourne le nom du tileset
# return String
#-----------------------------
def tileset_name
if $game_system.fple
return @fple_map.tileset_name
else
return ""
end
end
end
#-----------------------------
def cached_distance(event_id, event_x, event_y)
player_pos = [$game_player.x, $game_player.y]
# Clear cache if player moved
if @last_player_pos != player_pos
@distance_cache.clear
@last_player_pos = player_pos
end
cache_key = [event_id, event_x, event_y]
return @distance_cache[cache_key] if @distance_cache.has_key?(cache_key)
dist_x = (player_pos[0] - event_x).abs
dist_y = (player_pos[1] - event_y).abs
distance = Math.sqrt(dist_x * dist_x + dist_y * dist_y)
@distance_cache[cache_key] = distance
return distance
end
#-----------------------------
# * Recherche les surfaces visibles de la carte en fonction de
# l'orientation du joueur
#-----------------------------
def refresh_surfaces
@current_dir = $game_player.direction
self.surfaces = []
@x_ref = $game_player.x
@y_ref = $game_player.y
case $game_player.direction
when 2
surfaces_temp = refresh_surfaces_down
when 4
surfaces_temp = refresh_surfaces_left
when 6
surfaces_temp = refresh_surfaces_right
when 8
surfaces_temp = refresh_surfaces_up
end
# set surfaces z attributes with z-fighting prevention
surfaces_temp.each {|surface| set_surface_z(surface)}
surfaces.concat(surfaces_temp)
# Enhanced sorting with z-fighting prevention
if @last_surface_count != surfaces.length || $game_temp.force_render
surfaces.sort! { |a, b|
z_diff = b[5] - a[5]
if z_diff.abs < 0.001 # Very close z-values
# Use additional criteria for stable sorting
secondary = (b[1].abs + b[2].abs) - (a[1].abs + a[2].abs)
secondary.zero? ? b.object_id <=> a.object_id : secondary
else
z_diff <=> 0
end
}
@last_surface_count = surfaces.length
end
end
def add_character_surfaces_down_with_rotation_fix(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each do |surface|
next if surface.displayed # Skip if already processed
dy = surface.dy - ($game_player.y << 7)
dx = ($game_player.x << 7) - surface.dx
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 2)
end
return surfaces_temp
end
def add_character_surfaces_up_with_rotation_fix(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each do |surface|
next if surface.displayed # Skip if already processed
dy = ($game_player.y << 7) - surface.dy
dx = surface.dx - ($game_player.x << 7)
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 8)
end
return surfaces_temp
end
def add_character_surfaces_left_with_rotation_fix(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each do |surface|
next if surface.displayed # Skip if already processed
dy = ($game_player.x << 7) - surface.dx
dx = ($game_player.y << 7) - surface.dy
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 4)
end
return surfaces_temp
end
def add_character_surfaces_right_with_rotation_fix(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each do |surface|
next if surface.displayed # Skip if already processed
dy = surface.dx - ($game_player.x << 7)
dx = surface.dy - ($game_player.y << 7)
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 6)
end
return surfaces_temp
end
#-----------------------------
# * Add surfaces for single-sided events only during rotation
#-----------------------------
def add_character_surfaces_down_single_only(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each do |surface|
next if surface.displayed # Skip if already processed
# Only process single-sided events
#next if surface.character.fple_four_side || surface.character.fple_six_side || surface.character.fple_two_side
dy = surface.dy - ($game_player.y << 7)
dx = ($game_player.x << 7) - surface.dx
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 2)
end
return surfaces_temp
end
def add_character_surfaces_up_single_only(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each do |surface|
next if surface.displayed # Skip if already processed
# Only process single-sided events
#next if surface.character.fple_four_side || surface.character.fple_six_side || surface.character.fple_two_side
dy = ($game_player.y << 7) - surface.dy
dx = surface.dx - ($game_player.x << 7)
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 8)
end
return surfaces_temp
end
def add_character_surfaces_left_single_only(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each do |surface|
next if surface.displayed # Skip if already processed
# Only process single-sided events
#next if surface.character.fple_four_side || surface.character.fple_six_side || surface.character.fple_two_side
dy = ($game_player.x << 7) - surface.dx
dx = ($game_player.y << 7) - surface.dy
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 4)
end
return surfaces_temp
end
def add_character_surfaces_right_single_only(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each do |surface|
next if surface.displayed # Skip if already processed
# Only process single-sided events
#next if surface.character.fple_four_side || surface.character.fple_six_side || surface.character.fple_two_side
dy = surface.dx - ($game_player.x << 7)
dx = surface.dy - ($game_player.y << 7)
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 6)
end
return surfaces_temp
end
def add_two_sided_surfaces(surface, dy, dx, surfaces_temp, i, dir)
# Handle special case where player is at same position as box
j = i << 7
if dy.between?(128, j) && dx.between?(-j, j)
event_id = surface.character.id rescue 0
base_z_offset = (event_id % 1000) * 0.0001
distance = Math.sqrt(dy * dy + dx * dx)
# Determine visible faces based on position
faces_to_render = []
# Front face (player looking at object)
if dy > 32
faces_to_render << {type: 1, d_align: 0, z_priority: 5, name: :front}
end
# Back face
if dy < -32
faces_to_render << {type: 1, d_align: 2, z_priority: 0, name: :back}
end
# Left face - FIXED: Use proper alignment values
if dx < -32
faces_to_render << {type: 2, d_align: 0, z_priority: 4, name: :left}
end
# Right face - FIXED: Use proper alignment values
if dx > 32
faces_to_render << {type: 2, d_align: 2, z_priority: 1, name: :right}
end
# For very close viewing, always show some faces
if distance < 96
if faces_to_render.empty?
faces_to_render << {type: 1, d_align: 0, z_priority: 5, name: :front}
faces_to_render << {type: 2, d_align: 0, z_priority: 4, name: :left}
end
end
# Render at least one face
if faces_to_render.empty?
faces_to_render << {type: 1, d_align: 0, z_priority: 5, name: :front}
end
end
# Render the faces
faces_to_render.each_with_index do |face_config, face_index|
side_dy = dy
side_dx = dx
# FIXED: Apply position adjustments with proper bounds checking
if face_config[:type] == 1 # Horizontal face
if face_config[:d_align] == 0 # Front
side_dy -= 64
elsif face_config[:d_align] == 2 # Back
side_dy += 64
end
elsif face_config[:type] == 2 # Vertical face
if face_config[:d_align] == 0 # Left
side_dx -= 64
elsif face_config[:d_align] == 2 # Right
side_dx += 64
end
end
# Calculate z-modifier
z_modifier = base_z_offset + (face_config[:z_priority] * 0.008) + (face_index * 0.001)
surface_data = [0, side_dy, side_dx, 5, 0, 0,
surface.bitmap.__id__, face_config[:type],
surface.character.fple_v_align, surface.character.fple_stretch,
surface.opacity, surface.blend_type,
surface.fit, surface.zoom, 0, z_modifier]
surfaces_temp.push(surface_data)
end
surface.displayed = true
end
#-----------------------------
# * FIXED: Four-sided surfaces - ensure proper type assignment
#-----------------------------
def add_four_sided_surfaces(surface, dy, dx, surfaces_temp, i, dir)
# Handle special case where player is at same position as box
j = i << 7
if dy.between?(128, j) && dx.between?(-j, j)
event_id = surface.character.id rescue 0
base_z_offset = (event_id % 1000) * 0.0001
# Always render all 4 sides for 4-sided boxes
faces_to_render = [
{type: 1, d_align: 0, z_priority: 3, name: :front}, # Front
{type: 1, d_align: 2, z_priority: 0, name: :back}, # Back
{type: 2, d_align: 0, z_priority: 3, name: :left}, # Left
{type: 2, d_align: 2, z_priority: 1, name: :right}, # Right
]
# Render all faces with strafe-safe positioning
faces_to_render.each_with_index do |face_config, face_index|
side_dy = dy
side_dx = dx
# FIXED: Apply position adjustments with bounds checking and strafe compensation
if face_config[:type] == 1 # Horizontal face
if face_config[:d_align] == 0 # Front
side_dy -= 64
elsif face_config[:d_align] == 2 # Back
side_dy += 64
end
elsif face_config[:type] == 2 # Vertical face
if face_config[:d_align] == 0 # Left
side_dx -= 64
elsif face_config[:d_align] == 2 # Right
side_dx += 64
end
end
# Calculate z-modifier
z_modifier = base_z_offset + (face_config[:z_priority] * 0.01) + (face_index * 0.001)
surface_data = [0, side_dy, side_dx, 5, 0, 0,
surface.bitmap.__id__, face_config[:type],
surface.character.fple_v_align, surface.character.fple_stretch,
surface.opacity, surface.blend_type,
surface.fit, surface.zoom, 0, z_modifier]
surfaces_temp.push(surface_data)
end
surface.displayed = true
end
end
#-----------------------------
# * FIXED: Six-sided surfaces - ensure proper type assignment
#-----------------------------
def add_six_sided_surfaces(surface, dy, dx, surfaces_temp, i, dir)
j = i << 7
if dy.between?(128, j) && dx.between?(-j, j)
event_id = surface.character.id rescue 0
base_z_offset = (event_id % 1000) * 0.0001
# Render all 6 sides for maximum visibility
faces_to_render = [
{type: 0, d_align: 1, z_priority: 2, name: :center_h}, # Center horizontal
{type: 1, d_align: 0, z_priority: 4, name: :front}, # Front
{type: 1, d_align: 2, z_priority: 0, name: :back}, # Back
{type: 2, d_align: 0, z_priority: 3, name: :left}, # Left
{type: 2, d_align: 2, z_priority: 1, name: :right}, # Right
]
# Render all faces with strafe protection
faces_to_render.each_with_index do |face_config, face_index|
side_dy = dy
side_dx = dx
# FIXED: Apply position adjustments with strafe-aware bounds checking
if face_config[:type] == 1 # Horizontal face
if face_config[:d_align] == 0 # Front
side_dy -= 64
elsif face_config[:d_align] == 2 # Back
side_dy += 64
end
elsif face_config[:type] == 2 # Vertical face
if face_config[:d_align] == 0 # Left
side_dx -= 64
elsif face_config[:d_align] == 2 # Right
side_dx += 64
end
end
# Calculate z-modifier
z_modifier = base_z_offset + (face_config[:z_priority] * 0.008) + (face_index * 0.001)
surface_data = [0, side_dy, side_dx, 5, 0, 0,
surface.bitmap.__id__, face_config[:type],
surface.character.fple_v_align, surface.character.fple_stretch,
surface.opacity, surface.blend_type,
surface.fit, surface.zoom, 0, z_modifier]
surfaces_temp.push(surface_data)
end
surface.displayed = true
end
end
# Render all 6 sides for maximum visibility
#-----------------------------
# * Calcul de la priorité d'affichage d'une surface
# param surface : Array<Integer>
#-----------------------------
def set_surface_z(surface)
if surface[3] < 5 # map surfaces
base_z = (surface[1].abs << 5) + surface[2].abs
# Apply rotation compensation for map surfaces
if FPLE.angle > 0
rotation_factor = FPLE.angle / 90.0
# Increase z-depth for surfaces during rotation to prevent bleeding
base_z += (rotation_factor * 1000).to_i
end
surface[5] = base_z
else # character surfaces
base_z = (surface[1].abs >> 1) + (surface[2].abs >> 6) - 2
# Check if surface has z-modifier (from multi-sided rendering)
z_modifier = surface[15] || 0
# Enhanced rotation compensation for character surfaces
if FPLE.angle > 0
rotation_factor = FPLE.angle / 90.0
# Push character surfaces further back during rotation
rotation_penalty = rotation_factor * 500
# Additional penalty based on distance from player
distance_penalty = Math.sqrt(surface[1] * surface[1] + surface[2] * surface[2]) * 0.1
base_z += (rotation_penalty + distance_penalty).to_i
end
# Surface type and alignment offsets
type_offset = surface[7] || 0
align_offset = surface[8] || 0
z_offset = case type_offset
when 1 # Horizontal walls
case surface[2] <=> 0
when -1 then 0.4 # Left side
when 0 then 0.2 # Center
when 1 then 0.0 # Right side
end
when 2 # Vertical walls
case surface[1] <=> 0
when -1 then 0.3 # Front
when 0 then 0.1 # Center
when 1 then -0.1 # Back
end
else
0 # Default for type 0
end
# Vertical alignment offset
v_align_offset = case align_offset
when 0 then 0.03 # Top
when 1 then 0.01 # Middle
when 2 then -32.01 # Bottom
else 0
end
if @angle == 0 && $game_temp.movement_dir == 9 || $game_temp.movement_dir == 10
surface[5] = base_z.to_f + z_offset + z_modifier
else
surface[5] = base_z.to_f + z_offset + v_align_offset + z_modifier
end
end
end
#-----------------------------
# * Recherche les surfaces visibles des évènements en fonction de
# l'orientation du joueur
# param character_surfaces : Array<FPLE::Surface_Characters>
#-----------------------------
# This method updates the list of character surfaces based on visibility and player direction.
public
def refresh_character_surfaces(character_surfaces)
return if character_surfaces.empty?
max_dist = ($game_system.fple_view_distance || 10) + 3 # Large buffer
visible_surfaces = character_surfaces.select do |surface|
next false unless surface.character && surface.visible && surface.opacity > 0
# Very generous distance-based filtering
char = surface.character
dist_x = ($game_player.x - char.x).abs
dist_y = ($game_player.y - char.y).abs
dist_x <= max_dist && dist_y <= max_dist
end
visible_surfaces = character_surfaces.select { |s|
s.character && s.visible && s.opacity > 0
}
clear_character_surfaces(visible_surfaces)
# During rotation, we need to render from multiple directions
if FPLE.angle > 0
# For multi-sided events during rotation, only render once from current direction
# to prevent duplicate/rotating surfaces
current_surfaces = case $game_player.direction
when 2 then add_character_surfaces_down_with_rotation_fix(visible_surfaces)
when 4 then add_character_surfaces_left_with_rotation_fix(visible_surfaces)
when 6 then add_character_surfaces_right_with_rotation_fix(visible_surfaces)
when 8 then add_character_surfaces_up_with_rotation_fix(visible_surfaces)
end
# Only add next direction surfaces for single-sided events
clear_character_surfaces_for_single_sided(visible_surfaces)
next_surfaces = case $game_player.direction
when 2 then add_character_surfaces_right_single_only(visible_surfaces)
when 4 then add_character_surfaces_down_single_only(visible_surfaces)
when 6 then add_character_surfaces_up_single_only(visible_surfaces)
when 8 then add_character_surfaces_left_single_only(visible_surfaces)
end
surfaces_temp = current_surfaces + next_surfaces
else
# Normal rendering - single direction
surfaces_temp = case $game_player.direction
when 2 then add_character_surfaces_down(visible_surfaces)
when 4 then add_character_surfaces_left(visible_surfaces)
when 6 then add_character_surfaces_right(visible_surfaces)
when 8 then add_character_surfaces_up(visible_surfaces)
else []
end
end
surfaces_temp.each { |surface| set_surface_z(surface) }
@surfaces.concat(surfaces_temp)
#Old#@surfaces.sort! { |a, b| b[5] - a[5] }
# Enhanced sorting
@surfaces.sort! do |a, b|
z_diff = b[5] - a[5]
if z_diff.abs < 0.0001
(b[1].abs + b[2].abs) - (a[1].abs + a[2].abs)
else
z_diff <=> 0
end
end
end
#-----------------------------
# * Réinitialise l'indicateur d'affichage des surfaces liées aux évènements
# param character_surfaces : Array<FPLE::Surface_Characters>
#-----------------------------
def clear_character_surfaces(character_surfaces)
character_surfaces.each {|surface| surface.displayed = false}
end
def clear_character_surfaces_for_single_sided(character_surfaces)
character_surfaces.each do |surface|
# Only clear single-sided events - keep multi-sided events as displayed
unless surface.character.fple_four_side || surface.character.fple_six_side || surface.character.fple_two_side
surface.displayed = false
end
end
end
def cleanup_distant_surfaces
return unless @surfaces
# Only cleanup if we have a lot of surfaces
max_surfaces = 300 # Very generous limit
if @surfaces.length > max_surfaces
# Keep only the closest surfaces
@surfaces.sort_by! { |s| s[1].abs + s[2].abs }
@surfaces = @surfaces.first(max_surfaces)
end
end
#-----------------------------
# * Vérifie la visibilité d'une surface liée à un évènement et l'ajoute
# à la liste des surfaces à afficher le cas échéant
# param surface : FPLE::Surface_Characters
# param dy : Integer
# param dx : Integer
# param surfaces_temp : Array<Array<integer>>
# param i : Integer
# param dir : Integer
#-----------------------------
# This method adds a character surface to the list for rendering if it is visible.
# `surface`: The FPLE surface object for the character.
# `dy`: The change in y-coordinate from the player.
# `dx`: The change in x-coordinate from the player.
# `surfaces_temp`: The array to which the new surface will be added.
# `i`: The view distance index used for calculation.
# `dir`: The player's direction.
def add_character_surfaces(surface, dy, dx, surfaces_temp, i, dir)
return unless surface.character && surface.character.fple_type
# Distance culling - more generous for multi-sided events
distance_sq = dy * dy + dx * dx
max_distance = $game_system.fple_view_distance || 10
# Use larger buffer for multi-sided events to prevent edge clipping
if surface.character.fple_four_side || surface.character.fple_six_side || surface.character.fple_two_side
rotation_buffer = FPLE.angle > 0 ? 1.5 : 1.3
else
rotation_buffer = FPLE.angle > 0 ? 2.0 : 1.0
end
max_distance_sq = (max_distance * 96 * rotation_buffer) ** 2
return if distance_sq > max_distance_sq
# Early opacity check
return if surface.opacity <= 0
# Handle multi-sided boxes
if surface.character.fple_two_side
add_two_sided_surfaces(surface, dy, dx, surfaces_temp, i, dir)
return
elsif surface.character.fple_four_side
add_four_sided_surfaces(surface, dy, dx, surfaces_temp, i, dir)
return
elsif surface.character.fple_six_side
add_six_sided_surfaces(surface, dy, dx, surfaces_temp, i, dir)
return
end
# Original single-surface logic for regular events
j = i << 7
if dy == 0 && dx == 0 && surface.character.fple_type == 0 && surface.character.fple_one_side == false
surface.set_relative_attributes(dir)
safe_dy = 128
surface_data = [0, safe_dy, 0, 5, 0, 0,
surface.bitmap.__id__,
0, # Keep type 0 for face-player events at same position
surface.character.fple_v_align,
surface.character.fple_stretch,
surface.opacity,
surface.blend_type,
surface.fit,
surface.zoom,
surface.mirror]
surfaces_temp.push(surface_data)
surface.displayed = true
elsif dy.between?(128, j) && dx.between?(-j, j)
# Position adjustments for wall types
if surface.v_align == 2
dy -= 16 unless surface.fit == 1
end
surface.set_relative_attributes(dir)
if surface.type == 1
if surface.d_align == 0
dy -= 64
elsif surface.d_align == 2
dy += 64
elsif surface.d_align == 1 && surface.v_align == 2
dy -= 16 unless $game_player.moving?
end
elsif surface.type == 2
if surface.d_align == 0
dx -= 64
elsif surface.d_align == 2
dx += 64
elsif surface.d_align == 1 && surface.v_align == 2
dx -= 16 unless $game_player.moving?
end
end
surface_data = [0, dy, dx, 5, 0, 0,
surface.bitmap.__id__, surface.type,
surface.v_align, surface.character.fple_stretch,
surface.opacity, surface.blend_type,
surface.fit, surface.zoom, surface.mirror]
surfaces_temp.push(surface_data)
surface.displayed = true
end
end
#-----------------------------
def should_render_one_side_event(character, player_dir)
return true unless character.fple_one_side
# Get the event's original type
original_type = character.fple_type
case original_type
when 0 # Always face player - render from all directions
return true
when 1 # Horizontal wall in editor view
# Only render when looking from north or south
return [2, 8].include?(player_dir)
when 2 # Vertical wall in editor view
# Only render when looking from east or west
return [4, 6].include?(player_dir)
end
return true
end
#-----------------------------
def should_render_two_side_event(character, player_dir)
return true unless character.fple_two_side
# Get the event's original type
original_type = character.fple_type
case original_type
when 0 # Always face player - render from all directions
return true
when 1 # Horizontal wall in editor view
# Only render when looking from north or south
return [2, 8].include?(player_dir)
when 2 # Vertical wall in editor view
# Only render when looking from east or west
return [4, 6].include?(player_dir)
end
return true
end
#-----------------------------
# * Recherche les surfaces liées à un évènement visibles quand le joueur est
# orienté vers le bas
# param character_surfaces : Array<FPLE::Surface_Characters>
# return Array<Array<Integer>>
#----------------------------z
#-----------------------------
# * Recherche les surfaces liées à un évènement visibles quand le joueur est
# orienté vers le haut
# param character_surfaces : Array<FPLE::Surface_Characters>
# return Array<Array<Integer>>
#-----------------------------
def add_character_surfaces_up(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each {|surface|
if surface.displayed then next end
# Check directional visibility for 2-side events
next unless should_render_two_side_event(surface.character, 8)
dy = ($game_player.y << 7) - surface.dy
dx = surface.dx - ($game_player.x << 7)
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 8)
}
return surfaces_temp
end
#-----------------------------
# * Recherche les surfaces liées à un évènement visibles quand le joueur est
# orienté vers le bas
# param character_surfaces : Array<FPLE::Surface_Characters>
# return Array<Array<Integer>>
#-----------------------------
def add_character_surfaces_down(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each {|surface|
if surface.displayed then next end
# Check directional visibility for 2-side events
next unless should_render_two_side_event(surface.character, 2)
dy = surface.dy - ($game_player.y << 7)
dx = ($game_player.x << 7) - surface.dx
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 2)
}
return surfaces_temp
end
#-----------------------------
# * Recherche les surfaces liées à un évènement visibles quand le joueur est
# orienté vers la gauche
# param character_surfaces : Array<FPLE::Surface_Characters>
# return Array<Array<Integer>>
#-----------------------------
def add_character_surfaces_left(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each {|surface|
if surface.displayed then next end
# Check directional visibility for 2-side events
next unless should_render_two_side_event(surface.character, 4)
dy = ($game_player.x << 7) - surface.dx
dx = ($game_player.y << 7) - surface.dy
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 4)
}
return surfaces_temp
end
#-----------------------------
# * Recherche les surfaces liées à un évènement visibles quand le joueur est
# orienté vers la droite
# param character_surfaces : Array<FPLE::Surface_Characters>
# return Array<Array<Integer>>
#-----------------------------
def add_character_surfaces_right(character_surfaces)
surfaces_temp = []
i = $game_system.fple_view_distance
character_surfaces.each {|surface|
if surface.displayed then next end
# Check directional visibility for 2-side events
next unless should_render_two_side_event(surface.character, 6)
dy = surface.dx - ($game_player.x << 7)
dx = surface.dy - ($game_player.y << 7)
add_character_surfaces(surface, dy, dx, surfaces_temp, i, 6)
}
return surfaces_temp
end
#-----------------------------
# * Recherche les surfaces visibles quand le joueur tourne vers la droite
# param character_surfaces : Array<FPLE::Surface_Characters>
#-----------------------------
def position_occluded_during_rotation?(x, y, player_x, player_y, check_direction)
# Calculate the path from player to target position
dx = x - player_x
dy = y - player_y
if @fple_map.get_data(x, y)[0] > 0 && $game_temp.movement_dir == 9 || $game_temp.movement_dir == 10
return false unless $game_map.region_id($game_player.x, $game_player.y) == 7
else
end
# Don't occlude events that are directly adjacent (doors on walls)
if dx.abs <= 1 && dy.abs <= 1 && (dx.abs + dy.abs) == 1
return false
end
# For single-tile distances, check adjacent walls
if dx.abs <= 1 && dy.abs <= 1
case check_direction
when 2 # Down
# Check for walls between player and target going down
return @fple_map.get_data(player_x, player_y + 1)[0] > 0 if dy > 0
when 4 # Left
# Check for walls between player and target going left
return @fple_map.get_data(player_x - 1, player_y)[0] > 0 if dx < 0
when 6 # Right
# Check for walls between player and target going right
return @fple_map.get_data(player_x + 1, player_y)[0] > 0 if dx > 0
when 8 # Up
# Check for walls between player and target going up
return @fple_map.get_data(player_x, player_y - 1)[0] > 0 if dy < 0
end
end
# For longer distances, use line-of-sight checking
return line_of_sight_blocked?(player_x, player_y, x, y)
end
#-----------------------------
# * Check if line of sight is blocked by walls
# param x1, y1 : Integer - start coordinates
# param x2, y2 : Integer - end coordinates
# return Boolean - true if blocked
#-----------------------------
def line_of_sight_blocked?(x1, y1, x2, y2)
# Simple bresenham-like algorithm to check for wall blocking
dx = (x2 - x1).abs
dy = (y2 - y1).abs
return false if dx == 0 && dy == 0
x_step = x1 < x2 ? 1 : -1
y_step = y1 < y2 ? 1 : -1
# Check key points along the path
if dx > dy
# More horizontal movement
(1..dx).each do |i|
check_x = x1 + (i * x_step)
check_y = y1 + ((i * dy * y_step) / dx)
return true if @fple_map.get_data(check_x, check_y)[0] > 0
end
else
# More vertical movement
(1..dy).each do |i|
check_x = x1 + ((i * dx * x_step) / dy)
check_y = y1 + (i * y_step)
return true if @fple_map.get_data(check_x, check_y)[0] > 0
end
end
false
end
#-----------------------------
# * Enhanced character surface filtering with occlusion
# param character_surfaces : Array<FPLE::Surface_Characters>
# param player_dir : Integer - current player direction
# param rotation_dir : Integer - direction of rotation (next direction)
# return Array<FPLE::Surface_Characters> - filtered surfaces
#-----------------------------
def filter_character_surfaces_with_occlusion(character_surfaces, player_dir, rotation_dir = nil)
return [] if character_surfaces.empty?
player_x = $game_player.x
player_y = $game_player.y
filtered_surfaces = []
character_surfaces.each do |surface|
next unless surface.character && surface.visible && surface.opacity > 0
char_x = surface.character.x
char_y = surface.character.y
# Skip if too distant
dist_x = (player_x - char_x).abs
dist_y = (player_y - char_y).abs
max_dist = $game_system.fple_view_distance + 2
next if dist_x > max_dist || dist_y > max_dist
# Check occlusion for current direction
current_occluded = position_occluded_during_rotation?(char_x, char_y, player_x, player_y, player_dir)
# Check occlusion for rotation direction if specified
rotation_occluded = rotation_dir ?
position_occluded_during_rotation?(char_x, char_y, player_x, player_y, rotation_dir) : false
# Include surface if visible from either direction
unless current_occluded && rotation_occluded
filtered_surfaces << surface
end
end
filtered_surfaces
end
#-----------------------------
# * Recherche les surfaces visibles quand le joueur tourne vers la droite
# param character_surfaces : Array<FPLE::Surface_Characters>
#-----------------------------
def refresh_surfaces_turn_right(character_surfaces)
@current_dir = $game_player.direction
self.surfaces = []
@x_ref = $game_player.x
@y_ref = $game_player.y
surfaces_temp = refresh_current_surface
# Filter character surfaces with occlusion checking
filtered_surfaces = filter_character_surfaces_with_occlusion(character_surfaces, @current_dir,
case @current_dir
when 2 then 6 # Down -> Right
when 4 then 2 # Left -> Down
when 6 then 8 # Right -> Up
when 8 then 4 # Up -> Left
end)
clear_character_surfaces(filtered_surfaces)
case $game_player.direction
when 2
surfaces_temp1 = refresh_surfaces_down
@current_dir = 6
surfaces_temp2 = refresh_surfaces_right(false)
@current_dir = 2
surfaces_temp1 += add_character_surfaces_down(filtered_surfaces)
surfaces_temp2 += add_character_surfaces_right(filtered_surfaces)
when 4
surfaces_temp1 = refresh_surfaces_left
@current_dir = 2
surfaces_temp2 = refresh_surfaces_down(false)
@current_dir = 4
surfaces_temp1 += add_character_surfaces_left(filtered_surfaces)
surfaces_temp2 += add_character_surfaces_down(filtered_surfaces)
when 6
surfaces_temp1 = refresh_surfaces_right
@current_dir = 8
surfaces_temp2 = refresh_surfaces_up(false)
@current_dir = 6
surfaces_temp1 += add_character_surfaces_right(filtered_surfaces)
surfaces_temp2 += add_character_surfaces_up(filtered_surfaces)
when 8
surfaces_temp1 = refresh_surfaces_up
@current_dir = 4
surfaces_temp2 = refresh_surfaces_left(false)
@current_dir = 8
surfaces_temp1 += add_character_surfaces_up(filtered_surfaces)
surfaces_temp2 += add_character_surfaces_left(filtered_surfaces)
end
surfaces_temp1.each {|surface| adjust_surface_for_rotation(surface)}
# set surfaces z attributes
(surfaces_temp + surfaces_temp1 + surfaces_temp2).each {|surface|
set_surface_z(surface)
}
surfaces.concat(surfaces_temp + surfaces_temp1 + surfaces_temp2)
surfaces.sort! {|a, b| b[5] - a[5]}
end
#-----------------------------
# * Recherche les surfaces visibles quand le joueur tourne vers la gauche
# param character_surfaces : Array<FPLE::Surface_Characters>
#-----------------------------
def refresh_surfaces_turn_left(character_surfaces)
@current_dir = $game_player.direction
self.surfaces = []
@x_ref = $game_player.x
@y_ref = $game_player.y
surfaces_temp = refresh_current_surface
# Filter character surfaces with occlusion checking
filtered_surfaces = filter_character_surfaces_with_occlusion(character_surfaces, @current_dir,
case @current_dir
when 2 then 4 # Down -> Left
when 4 then 8 # Left -> Up
when 6 then 2 # Right -> Down
when 8 then 6 # Up -> Right
end)
clear_character_surfaces(filtered_surfaces)
case $game_player.direction
when 2
@current_dir = 4
surfaces_temp1 = refresh_surfaces_left
@current_dir = 2
surfaces_temp2 = refresh_surfaces_down(false)
surfaces_temp1 += add_character_surfaces_left(filtered_surfaces)
surfaces_temp2 += add_character_surfaces_down(filtered_surfaces)
when 4
@current_dir = 8
surfaces_temp1 = refresh_surfaces_up
@current_dir = 4
surfaces_temp2 = refresh_surfaces_left(false)
surfaces_temp1 += add_character_surfaces_up(filtered_surfaces)
surfaces_temp2 += add_character_surfaces_left(filtered_surfaces)
when 6
@current_dir = 2
surfaces_temp1 = refresh_surfaces_down
@current_dir = 6
surfaces_temp2 = refresh_surfaces_right(false)
surfaces_temp1 += add_character_surfaces_down(filtered_surfaces)
surfaces_temp2 += add_character_surfaces_right(filtered_surfaces)
when 8
@current_dir = 6
surfaces_temp1 = refresh_surfaces_right
@current_dir = 8
surfaces_temp2 = refresh_surfaces_up(false)
surfaces_temp1 += add_character_surfaces_right(filtered_surfaces)
surfaces_temp2 += add_character_surfaces_up(filtered_surfaces)
end
surfaces_temp1.each {|surface| adjust_surface_for_rotation(surface)}
# set surfaces z attributes
(surfaces_temp + surfaces_temp1 + surfaces_temp2).each {|surface|
set_surface_z(surface)
}
surfaces.concat(surfaces_temp + surfaces_temp1 + surfaces_temp2)
surfaces.sort! {|a, b| b[5] - a[5]}
end
#-----------------------------
# * Enhanced turn up method (if needed for your system)
# param character_surfaces : Array<FPLE::Surface_Characters>
#-----------------------------
def refresh_surfaces_turn_up(character_surfaces)
@current_dir = $game_player.direction
self.surfaces = []
@x_ref = $game_player.x
@y_ref = $game_player.y
surfaces_temp = refresh_current_surface
# Filter character surfaces with occlusion checking
filtered_surfaces = filter_character_surfaces_with_occlusion(character_surfaces, @current_dir, 8)
clear_character_surfaces(filtered_surfaces)
# Render current direction surfaces
surfaces_temp1 = case $game_player.direction
when 2 then refresh_surfaces_down
when 4 then refresh_surfaces_left
when 6 then refresh_surfaces_right
when 8 then refresh_surfaces_up
else []
end
# Render up direction surfaces
@current_dir = 8
surfaces_temp2 = refresh_surfaces_up(false)
@current_dir = $game_player.direction
# Add character surfaces
surfaces_temp1 += case $game_player.direction
when 2 then add_character_surfaces_down(filtered_surfaces)
when 4 then add_character_surfaces_left(filtered_surfaces)
when 6 then add_character_surfaces_right(filtered_surfaces)
when 8 then add_character_surfaces_up(filtered_surfaces)
else []
end
surfaces_temp2 += add_character_surfaces_up(filtered_surfaces)
surfaces_temp1.each {|surface| adjust_surface_for_rotation(surface)} unless $game_player.direction == 8
# set surfaces z attributes
(surfaces_temp + surfaces_temp1 + surfaces_temp2).each {|surface|
set_surface_z(surface)
}
surfaces.concat(surfaces_temp + surfaces_temp1 + surfaces_temp2)
surfaces.sort! {|a, b| b[5] - a[5]}
end
#-----------------------------
# * Enhanced turn down method (if needed for your system)
# param character_surfaces : Array<FPLE::Surface_Characters>
#-----------------------------
def refresh_surfaces_turn_down(character_surfaces)
@current_dir = $game_player.direction
self.surfaces = []
@x_ref = $game_player.x
@y_ref = $game_player.y
surfaces_temp = refresh_current_surface
# Filter character surfaces with occlusion checking
filtered_surfaces = filter_character_surfaces_with_occlusion(character_surfaces, @current_dir, 2)
clear_character_surfaces(filtered_surfaces)
# Render current direction surfaces
surfaces_temp1 = case $game_player.direction
when 2 then refresh_surfaces_down
when 4 then refresh_surfaces_left
when 6 then refresh_surfaces_right
when 8 then refresh_surfaces_up
else []
end
# Render down direction surfaces
@current_dir = 2
surfaces_temp2 = refresh_surfaces_down(false)
@current_dir = $game_player.direction
# Add character surfaces
surfaces_temp1 += case $game_player.direction
when 2 then add_character_surfaces_down(filtered_surfaces)
when 4 then add_character_surfaces_left(filtered_surfaces)
when 6 then add_character_surfaces_right(filtered_surfaces)
when 8 then add_character_surfaces_up(filtered_surfaces)
else []
end
surfaces_temp2 += add_character_surfaces_down(filtered_surfaces)
surfaces_temp1.each {|surface| adjust_surface_for_rotation(surface)} unless $game_player.direction == 2
# set surfaces z attributes
(surfaces_temp + surfaces_temp1 + surfaces_temp2).each {|surface|
set_surface_z(surface)
}
surfaces.concat(surfaces_temp + surfaces_temp1 + surfaces_temp2)
surfaces.sort! {|a, b| b[5] - a[5]}
end
#-----------------------------
# * Correction des attributs d'une surface visible pendant une rotation
# param surface : Array<Integer>
#-----------------------------
def adjust_surface_for_rotation(surface)
if surface[3] < 5
dy = surface[1]
surface[1] = -surface[2]
surface[2] = dy
if surface[3] < 2
surface[3] = 1 - surface[3]
end
else
if surface[7] > 0
surface[7] = 3 - surface[7]
end
dy = surface[1]
surface[1] = -surface[2]
surface[2] = dy
end
end
#-----------------------------
# * Recherche des surfaces visibles en déplacement latéral
# param offset : Integer
#-----------------------------
def refresh_surfaces_strafe(offset)
@current_dir = $game_player.direction
@x_ref = $game_player.x
@y_ref = $game_player.y
case $game_player.direction
when 2
@x_ref -= offset
surfaces_temp = refresh_surfaces_down_strafe
when 4
@y_ref -= offset
surfaces_temp = refresh_surfaces_left_strafe
when 6
@y_ref += offset
surfaces_temp = refresh_surfaces_right_strafe
when 8
@x_ref += offset
surfaces_temp = refresh_surfaces_up_strafe
end
# set surfaces z attributes
surfaces_temp.each {|surface| set_surface_z(surface)}
surfaces.concat(surfaces_temp)
surfaces.sort! {|a, b| b[5] - a[5]}
end
#-----------------------------
# * Rafraîchit la surface à la position du joueur
# return Array<Array<integer>>
#-----------------------------
def refresh_current_surface
surfaces_temp = []
get_surface_ground(surfaces_temp, @x_ref, @y_ref, 0, 0)
return surfaces_temp
end
#-----------------------------
# * Recherche les surfaces visibles de la carte quand le joueur est
# orienté vers le haut
# param right_ground : Boolean
# return Array<Array<integer>>
#-----------------------------
def refresh_surfaces_up(right_ground = true)
surfaces_temp = []
base_distance = $game_system.fple_view_distance
# Add extra tiles during rotation
i = FPLE.angle > 0 ? base_distance + 1 : base_distance
while i > 0
# peripherical ground/ceiling sprites
get_surface_ground(surfaces_temp, @x_ref - i, @y_ref - i, i << 1, -i << 1)
if right_ground
get_surface_ground(surfaces_temp, @x_ref + i, @y_ref - i, i << 1, i << 1)
end
klim = i - 1
(-klim..klim).each {|k|
add_surfaces(surfaces_temp, @x_ref + k, @y_ref - i, i << 1, k << 1, 0, 1)
}
i -= 1
end
return surfaces_temp
end
def refresh_surfaces_down(right_ground = true)
surfaces_temp = []
base_distance = $game_system.fple_view_distance
# Add extra tiles during rotation
i = FPLE.angle > 0 ? base_distance + 1 : base_distance
while i > 0
# peripherical ground sprites
get_surface_ground(surfaces_temp, @x_ref + i, @y_ref + i, i << 1, -i << 1)
if right_ground
get_surface_ground(surfaces_temp, @x_ref - i, @y_ref + i, i << 1, i << 1)
end
klim = i - 1
(-klim..klim).each {|k|
add_surfaces(surfaces_temp, @x_ref - k, @y_ref + i, i << 1, k << 1, 0, -1)
}
i -= 1
end
return surfaces_temp
end
def refresh_surfaces_left(right_ground = true)
surfaces_temp = []
base_distance = $game_system.fple_view_distance
# Add extra tiles during rotation
i = FPLE.angle > 0 ? base_distance + 1 : base_distance
while i > 0
# peripherical ground sprites
get_surface_ground(surfaces_temp, @x_ref - i, @y_ref + i, i << 1, -i << 1)
if right_ground
get_surface_ground(surfaces_temp, @x_ref - i, @y_ref - i, i << 1, i << 1)
end
klim = i - 1
(-klim..klim).each {|k|
add_surfaces(surfaces_temp, @x_ref - i, @y_ref - k, i << 1, k << 1, 1, 0)
}
i -= 1
end
return surfaces_temp
end
def refresh_surfaces_right(right_ground = true)
surfaces_temp = []
base_distance = $game_system.fple_view_distance
# Add extra tiles during rotation
i = FPLE.angle > 0 ? base_distance + 1 : base_distance
while i > 0
# peripherical ground sprites
get_surface_ground(surfaces_temp, @x_ref + i, @y_ref - i, i << 1, -i << 1)
if right_ground
get_surface_ground(surfaces_temp, @x_ref + i, @y_ref + i, i << 1, i << 1)
end
klim = i - 1
(-klim..klim).each {|k|
add_surfaces(surfaces_temp, @x_ref + i, @y_ref + k, i << 1, k << 1, -1, 0)
}
i -= 1
end
return surfaces_temp
end
#-----------------------------
# * Vérifie si un sol ou un plafond doit être affiché
# param surfaces_temp : Array<Array<Integer>>
# param x : Integer
# param y : Integer
# param dy : Integer
# param dx : Integer
#-----------------------------
def get_surface_ground(surfaces_temp, x, y, dy, dx)
if @fple_map.get_data(x, y)[0] == 0 # no wall tile
add_surface_ground(surfaces_temp, x, y, dy, dx)
end
end
#-----------------------------
# * Ajoute une surface de sol ou de plafond qui doit être affichée
# param surfaces_temp : Array<Array<Integer>>
# param x : Integer
# param y : Integer
# param dy : Integer
# param dx : Integer
#-----------------------------
def add_surface_ground(surfaces_temp, x, y, dy, dx)
g_texture_id = @fple_map.get_data(x, y)[1]
c_texture_id = @fple_map.get_data(x, y)[19]
if @fple_map.is_texture_id_valid?(g_texture_id)
if @fple_map.is_texture_id_valid?(c_texture_id)
surfaces_temp.push([g_texture_id, dy, dx, 4, c_texture_id, 0,
@fple_map.get_textureset_id(g_texture_id),
@fple_map.get_textureset_width(g_texture_id),
@fple_map.get_textureset_id(c_texture_id),
@fple_map.get_textureset_width(c_texture_id)])
else
surfaces_temp.push([g_texture_id, dy, dx, 2, 0, 0,
@fple_map.get_textureset_id(g_texture_id),
@fple_map.get_textureset_width(g_texture_id), 0, 8])
end
elsif @fple_map.is_texture_id_valid?(c_texture_id)
surfaces_temp.push([c_texture_id, dy, dx, 3, 0, 0,
@fple_map.get_textureset_id(c_texture_id),
@fple_map.get_textureset_width(c_texture_id), 0, 8])
end
end
#-----------------------------
# * Recherche des surfaces visibles
# param surfaces_temp : Array<Array<Integer>>
# param x : Integer
# param y : Integer
# param dy : Integer
# param dx : Integer
# param oy : Integer
# param ox : Integer
#-----------------------------
def add_surfaces(surfaces_temp, x, y, dy, dx, ox, oy)
if @fple_map.get_data(x, y)[0] > 0 # wall tile
if @fple_map.get_data(x + ox, y + oy)[0] == 0 # --> visible !
texture_id = @fple_map.get_data(x, y)[
FPLE::MAP_SIDES[@current_dir - 1 >> 1]]
if @fple_map.is_texture_id_valid?(texture_id)
surfaces_temp.push([texture_id, dy - 1, dx, 1, 0, 0,
@fple_map.get_textureset_id(texture_id),
@fple_map.get_textureset_width(texture_id), 0, 8])
end
end
else
# ground/ceiling sprite
add_surface_ground(surfaces_temp, x, y, dy, dx)
# side walls
if dx <= 0 # left
if @fple_map.get_data(x - oy, y + ox)[0] > 0 # side wall tile
texture_id = @fple_map.get_data(x - oy, y + ox)[
FPLE::MAP_SIDES_LEFT[@current_dir - 1 >> 1]]
if @fple_map.is_texture_id_valid?(texture_id)
surfaces_temp.push([texture_id, dy, dx - 1, 0, 0, 0,
@fple_map.get_textureset_id(texture_id),
@fple_map.get_textureset_width(texture_id), 0, 8])
end
end
end
if dx >= 0 # right
if @fple_map.get_data(x + oy, y - ox)[0] > 0 # side wall tile
texture_id = @fple_map.get_data(x + oy, y - ox)[
FPLE::MAP_SIDES_RIGHT[@current_dir - 1 >> 1]]
if @fple_map.is_texture_id_valid?(texture_id)
surfaces_temp.push([texture_id, dy, dx + 1, 0, 0, 0,
@fple_map.get_textureset_id(texture_id),
@fple_map.get_textureset_width(texture_id), 0, 8])
end
end
end
end
end
#-----------------------------
# * Recherche des surfaces visibles en déplacement latéral quand le
# joueur est orienté vers le haut
# return Array<Array<Integer>>
#-----------------------------
def refresh_surfaces_up_strafe
surfaces_temp = []
i = $game_system.fple_view_distance
while i > 0
get_surface_ground(surfaces_temp, @x_ref + i + 1, @y_ref - i, i << 1,
i + 1 << 1)
add_surfaces_strafe(surfaces_temp, @x_ref + i, @y_ref - i, i << 1, 0, 1)
# middle side wall
if @fple_map.get_data(@x_ref + 1, @y_ref - i)[0] == 0 # no wall tile
if @fple_map.get_data(@x_ref, @y_ref - i)[0] > 0 # side wall tile (Left)
texture_id = @fple_map.get_data(@x_ref, @y_ref - i)[
FPLE::MAP_SIDES_LEFT[@current_dir - 1 >> 1]]
if @fple_map.is_texture_id_valid?(texture_id)
surfaces_temp.push([texture_id, i << 1, 1, 0, 0, 0,
@fple_map.get_textureset_id(texture_id),
@fple_map.get_textureset_width(texture_id), 0, 8])
end
end
end
i -= 1
end
return surfaces_temp
end
#-----------------------------
# * Recherche des surfaces visibles en déplacement latéral quand le
# joueur est orienté vers le bas
# return Array<Array<Integer>>
#-----------------------------
def refresh_surfaces_down_strafe
surfaces_temp = []
i = $game_system.fple_view_distance
while i > 0
get_surface_ground(surfaces_temp, @x_ref - i - 1, @y_ref + i, i << 1,
i + 1 << 1)
add_surfaces_strafe(surfaces_temp, @x_ref - i, @y_ref + i, i << 1, 0, -1)
# middle side wall
if @fple_map.get_data(@x_ref - 1, @y_ref + i)[0] == 0 # no wall tile
if @fple_map.get_data(@x_ref, @y_ref + i)[0] > 0 # side wall tile (Left)
texture_id = @fple_map.get_data(@x_ref, @y_ref + i)[
FPLE::MAP_SIDES_LEFT[@current_dir - 1 >> 1]]
if @fple_map.is_texture_id_valid?(texture_id)
surfaces_temp.push([texture_id, i << 1, 1, 0, 0, 0,
@fple_map.get_textureset_id(texture_id),
@fple_map.get_textureset_width(texture_id), 0, 8])
end
end
end
i -= 1
end
return surfaces_temp
end
#-----------------------------
# * Recherche des surfaces visibles en déplacement latéral quand le
# joueur est orienté vers la gauche
# return Array<Array<Integer>>
#-----------------------------
def refresh_surfaces_left_strafe
surfaces_temp = []
i = $game_system.fple_view_distance
while i > 0
get_surface_ground(surfaces_temp, @x_ref - i, @y_ref - i - 1, i << 1,
i + 1 << 1)
add_surfaces_strafe(surfaces_temp, @x_ref - i, @y_ref - i, i << 1, 1, 0)
# middle side wall
if @fple_map.get_data(@x_ref - i, @y_ref - 1)[0] == 0 # no wall tile
if @fple_map.get_data(@x_ref - i, @y_ref)[0] > 0 # side wall tile (Left)
texture_id = @fple_map.get_data(@x_ref - i, @y_ref)[
FPLE::MAP_SIDES_LEFT[@current_dir - 1 >> 1]]
if @fple_map.is_texture_id_valid?(texture_id)
surfaces_temp.push([texture_id, i << 1, 1, 0, 0, 0,
@fple_map.get_textureset_id(texture_id),
@fple_map.get_textureset_width(texture_id), 0, 8])
end
end
end
i -= 1
end
return surfaces_temp
end
#-----------------------------
# * Recherche des surfaces visibles en déplacement latéral quand le
# joueur est orienté vers la droite
# return Array<Array<Integer>>
#-----------------------------
def refresh_surfaces_right_strafe
surfaces_temp = []
i = $game_system.fple_view_distance
while i > 0
get_surface_ground(surfaces_temp, @x_ref + i, @y_ref + i + 1, i << 1,
i + 1 << 1)
add_surfaces_strafe(surfaces_temp, @x_ref + i, @y_ref + i, i << 1, -1, 0)
# middle side wall
if @fple_map.get_data(@x_ref + i, @y_ref + 1)[0] == 0 # no wall tile
if @fple_map.get_data(@x_ref + i, @y_ref)[0] > 0 # side wall tile (Left)
texture_id = @fple_map.get_data(@x_ref + i, @y_ref)[
FPLE::MAP_SIDES_LEFT[@current_dir - 1 >> 1]]
if @fple_map.is_texture_id_valid?(texture_id)
surfaces_temp.push([texture_id, i << 1, 1, 0, 0, 0,
@fple_map.get_textureset_id(texture_id),
@fple_map.get_textureset_width(texture_id), 0, 8])
end
end
end
i -= 1
end
return surfaces_temp
end
#-----------------------------
# * Recherche des surfaces visibles en déplacement latéral
# param surfaces_temp : Array<Array<Integer>>
# param x : Integer
# param y : Integer
# param dxy : Integer
# param oy : Integer
# param ox : Integer
#-----------------------------
def add_surfaces_strafe(surfaces_temp, x, y, dxy, ox, oy)
if @fple_map.get_data(x, y)[0] > 0 # wall tile
if @fple_map.get_data(x + ox, y + oy)[0] == 0 # --> visible !
texture_id = @fple_map.get_data(x, y)[
FPLE::MAP_SIDES[@current_dir - 1 >> 1]]
if @fple_map.is_texture_id_valid?(texture_id)
surfaces_temp.push([texture_id, dxy - 1, dxy, 1, 0, 0,
@fple_map.get_textureset_id(texture_id),
@fple_map.get_textureset_width(texture_id), 0, 8])
end
end
else
# side wall (Right)
if @fple_map.get_data(x + oy, y - ox)[0] > 0 # side wall tile
texture_id = @fple_map.get_data(x + oy, y - ox)[
FPLE::MAP_SIDES_RIGHT[@current_dir - 1 >> 1]]
if @fple_map.is_texture_id_valid?(texture_id)
surfaces_temp.push([texture_id, dxy, dxy + 1, 0, 0, 0,
@fple_map.get_textureset_id(texture_id),
@fple_map.get_textureset_width(texture_id), 0, 8])
end
end
end
end
#==============================
# ** Game_Character
#==============================
class Game_Character < Game_CharacterBase
#-----------------------------
# * Aliased methods (F12 compatibility)
#-----------------------------
unless @already_aliased_fple
alias moving_fple_game_character? moving?
@already_aliased_fple = true
end
#-----------------------------
# * Determine if Moving
# return Boolean
#-----------------------------
def moving?
if $game_system.fple
return $game_temp.movement || moving_fple_game_character?
else
return moving_fple_game_character?
end
end
end
#==============================
# ** Game_Player
#==============================
class Game_Player < Game_Character
#-----------------------------
# * Aliased methods (F12 compatibility) - mod [1.1]
#-----------------------------
unless @already_aliased_fple
alias move_straight_fple_game_player move_straight
alias move_diagonal_fple_game_player move_diagonal
alias turn_right_90_fple_game_player turn_right_90
alias turn_left_90_fple_game_player turn_left_90
alias move_by_input_fple_game_player move_by_input
alias update_nonmoving_fple_game_player update_nonmoving
@already_aliased_fple = true
end
#-----------------------------
# * Initialize Public Member Variables
#-----------------------------
def init_public_members
super
@direction = 8
end
#-----------------------------
# * Move Straight
# param d : Integer
# param turn_ok : Boolean
#-----------------------------
def move_straight(d, turn_ok = true)
if $game_system.fple
case d
when 2
case $game_player.direction
when 2
go_forward
when 4
strafe_left
when 6
strafe_right
when 8
go_backward
end
when 4
case $game_player.direction
when 2
strafe_right
when 4
go_forward
when 6
go_backward
when 8
strafe_left
end
when 6
case $game_player.direction
when 2
strafe_left
when 4
go_backward
when 6
go_forward
when 8
strafe_right
end
when 8
case $game_player.direction
when 2
go_backward
when 4
strafe_right
when 6
strafe_left
when 8
go_forward
end
end
else
move_straight_fple_game_player(d, turn_ok)
end
end
#-----------------------------
# * Move Diagonally
# param horz : Integer
# param vert : Integer
#-----------------------------
def move_diagonal(horz, vert)
unless $game_system.fple
move_diagonal_fple_game_player(horz, vert)
end
end
#-----------------------------
# * Jump
# param x_plus : Integer
# param y_plus : Integer
#-----------------------------
def jump(x_plus, y_plus)
unless $game_system.fple
super(x_plus, y_plus) # [1.1]
end
end
#-----------------------------
# * Turn 90° Right
#-----------------------------
def turn_right_90
turn_right_90_fple_game_player
if $game_system.fple && !@direction_fix
$game_temp.movement_init = false
$game_temp.movement = true
$game_temp.movement_dir = 9
end
end
#-----------------------------
# * Turn 90° Left
#-----------------------------
def turn_left_90
turn_left_90_fple_game_player
if $game_system.fple && !@direction_fix
$game_temp.movement_init = false
$game_temp.movement = true
$game_temp.movement_dir = 10
end
end
#-----------------------------
# * Go Forward
#-----------------------------
def go_forward
mvt_data = FPLE::PLAYER_MOVE_FORWARD[(@direction >> 1) - 1]
if passable?(@x, @y, @direction)
@x += mvt_data[0]
@y += mvt_data[1]
increase_steps
$game_temp.movement = true
$game_temp.movement_dir = 8
else
check_event_trigger_touch(@x + mvt_data[0], @y + mvt_data[1])
end
end
#-----------------------------
# * Go Backward
#-----------------------------
def go_backward
target_dir = 10 - @direction
mvt_data = FPLE::PLAYER_MOVE_FORWARD[(target_dir >> 1) - 1]
if passable?(@x, @y, target_dir)
@x += mvt_data[0]
@y += mvt_data[1]
increase_steps
$game_temp.movement_init = false
$game_temp.movement = true
$game_temp.movement_dir = 2
else
check_event_trigger_touch(@x + mvt_data[0], @y + mvt_data[1])
end
end
#-----------------------------
# * Strafe Left
#-----------------------------
def strafe_left
target_dir = FPLE::TURN_LEFT[(@direction >> 1) - 1]
mvt_data = FPLE::PLAYER_MOVE_FORWARD[(target_dir >> 1) - 1]
if passable?(@x, @y, target_dir)
@x += mvt_data[0]
@y += mvt_data[1]
increase_steps
$game_temp.movement_init = false
$game_temp.movement = true
$game_temp.movement_dir = 4
else
check_event_trigger_touch(@x + mvt_data[0], @y + mvt_data[1])
end
end
#-----------------------------
# * Strafe Right
#-----------------------------
def strafe_right
target_dir = 10 - FPLE::TURN_LEFT[(@direction >> 1) - 1]
mvt_data = FPLE::PLAYER_MOVE_FORWARD[(target_dir >> 1) - 1]
if passable?(@x, @y, target_dir)
@x += mvt_data[0]
@y += mvt_data[1]
increase_steps
$game_temp.movement_init = false
$game_temp.movement = true
$game_temp.movement_dir = 6
else
check_event_trigger_touch(@x + mvt_data[0], @y + mvt_data[1])
end
end
#-----------------------------
# * Processing of Movement via input from the Directional Buttons
#-----------------------------
def move_by_input
if $game_system.fple
if !movable? || $game_map.interpreter.running? then return end
if Input.press?(:L)
strafe_left
elsif Input.press?(:R)
strafe_right
else
case Input.dir4
when 2; go_backward
when 4; turn_left_90
when 6; turn_right_90
when 8; go_forward
end
end
else
move_by_input_fple_game_player
end
end
#-----------------------------
# * Processing when not moving
# param last_moving : Boolean
#-----------------------------
def update_nonmoving(last_moving)
if $game_map.interpreter.running? then return end
update_nonmoving_fple_game_player(last_moving)
if last_moving then $game_temp.last_moving = false end
end
#-----------------------------
# * Move speed in FPLE mode
# return Integer
#-----------------------------
def move_speed_fple
return FPLE::PLAYER_MOVE_SPEED[real_move_speed]
end
end
#==============================
# ** Game_Event
#==============================
class Game_Event < Game_Character
#-----------------------------
# * Aliased methods (F12 compatibility)
#-----------------------------
unless @already_aliased_fple
alias refresh_fple_game_character refresh
@already_aliased_fple = true
end
#-----------------------------
# * Public Instance Variables
#-----------------------------
attr_reader :fple_type # Integer 0:face the player
# 1:horizontal wall in the RMXP editor view
# 2:vertical wall in the RMXP editor view
# 3:4-sided box (NEW)
# 4:6-sided box (NEW)
attr_reader :fple_v_align # Integer - Vertical align {0:up, 1:middle, 2:down}
attr_reader :fple_d_align # Integer - Depth align {0:front/left, 1:middle, 2:back/right}
attr_reader :fple_stretch # Integer (0/1)
attr_reader :fple_fit # Integer (0/1)
attr_reader :fple_zoom # Integer (1024 <=> zoom = 1.0)
attr_reader :fple_one_side # Boolean (0/1)
attr_reader :fple_two_side # Boolean - NEW: indicates 6-sided box mode
attr_reader :fple_four_side # Boolean - NEW: indicates 4-sided box mode
attr_reader :fple_six_side # Boolean - NEW: indicates 6-sided box mode
#-----------------------------
# * Scan the event's commands list
# param page : RPG::Event::Page
#-----------------------------
def check_commands(page)
@fple_type = 0
@fple_v_align = 1
@fple_d_align = 1
@fple_stretch = 0
@fple_fit = 0
@fple_zoom = 1024
@fple_one_side = false # [1.5]
@fple_two_side = false # NEW
@fple_four_side = false # NEW
@fple_six_side = false # NEW
command_list = page.list
(0..command_list.length - 2).each {|k|
command = command_list[k]
if command.code == 108
comments = command.parameters[0]
if comments[/Type/]
@fple_type = comments[/\d+/].to_i
if @fple_type < 0 || @fple_type > 2 then @fple_type = 0 end
end
if comments[/V-Align/]
@fple_v_align = comments[/\d+/].to_i
if @fple_v_align < 0 || @fple_v_align > 2 then @fple_v_align = 1 end
end
if comments[/D-Align/]
@fple_d_align = comments[/\d+/].to_i
if @fple_d_align < 0 || @fple_d_align > 2 then @fple_d_align = 1 end
end
if comments[/Stretch/]
@fple_stretch = 1
end
if comments[/Fit/]
@fple_fit = 1
end
if comments[/Zoom/]
@fple_zoom = (comments[/\d+\.\d+/].to_f * 1024).round
end
if comments[/1-Side/] # [1.5]
@fple_one_side = true
end
if comments[/2-Side/] # NEW
@fple_four_side = true
end
if comments[/4-Side/] # NEW
@fple_four_side = true
end
if comments[/6-Side/] # NEW
@fple_six_side = true
end
end
}
if @fple_type == 0 then @fple_d_align = 1 end
if @fple_stretch == 1 then @fple_v_align = 1 end
if @fple_two_side
elsif @fple_four_side
@fple_type = 3 # Special type for 4-sided boxes
@fple_d_align = 1 # Center alignment makes most sense
elsif @fple_six_side
@fple_type = 4 # Special type for 6-sided boxes
@fple_d_align = 1 # Center alignment makes most sense
end
end
#-----------------------------
# * Refresh
#-----------------------------
def refresh
refresh_fple_game_character
if @page then check_commands(@page) end
end
end
#==============================
# ** FPLE::Map_Data
#==============================
module FPLE
class Map_Data
#-----------------------------
# * Public Instance Variables
#-----------------------------
attr_accessor :data, :tileset_name, :map_name
attr_accessor :used_tiles_map, :textureset_data, :subsets_mapping
attr_reader :map_id, :width, :height
end
end
#==============================
# ** FPLE::Map
#==============================
module FPLE
class Map
#-----------------------------
# * Public Instance Variables
#-----------------------------
attr_accessor :data, :tileset_name, :map_name
attr_reader :map_id, :width, :height
attr_accessor :textureset
attr_accessor :texturesets
#-----------------------------
# * Initialisation
# param width : integer (largeur de la carte, donc égal à $game_map.width)
# param height : integer (hauteur de la carte, donc égal à $game_map.height)
# param name : String (nom du fichier de la carte FPLE)
# param tileset_name : String (nom du tileset utilisé)
# param map_data : Array[width * height]<Array<integer>>
# param subsets_mapping : Hash<Integer,String> {texture_id=>subset_name}
# param textureset_data : Array<Array> données de création du textureset
#-----------------------------
def initialize(width, height, name, tileset_name, map_data = nil,
subsets_mapping = nil, textureset_data = nil)
@width = width
@height = height
self.map_name = name
self.data = Array.new(width * height)
data.each_index {|index| data[index] = map_data[index]}
self.tileset_name = tileset_name
@subsets_mapping = subsets_mapping
create_textureset_from_data(textureset_data)
end
#-----------------------------
# * Retourne les données d'un tile par ses coordonées
# param x : integer ([0, width[)
# param y : integer ([0, height[)
# return Array[10]<integer> (map_Data)
#-----------------------------
def get_data(x, y)
ret = data[get_index(x, y)]
ret = [-1] unless ret
return ret
end
#-----------------------------
# * Retourne l'index d'un tile par ses coordonées
# param x : integer ([0, width[)
# param y : integer ([0, height[)
# return integer (> 0)
#-----------------------------
def get_index(x, y)
return x + y * width
end
#-----------------------------
# * Retourne l'abscisse d'un tile par son index
# return integer ([0, width[)
#-----------------------------
def get_x(index)
return index - width * (index / width)
end
#-----------------------------
# * Retourne l'ordonnée d'un tile par son index
# return integer ([0, height[)
#-----------------------------
def get_y(index)
return index / width
end
#-----------------------------
# * Création du textureset
# param textureset_data : Array<Array> données de création du textureset
#-----------------------------
def get_texture_lazy(texture_id)
@texture_cache ||= {}
return @texture_cache[texture_id] if @texture_cache.has_key?(texture_id)
# Only load texture if it will be used
if is_texture_id_valid?(texture_id)
@texture_cache[texture_id] = load_texture(texture_id)
else
@texture_cache[texture_id] = nil
end
return @texture_cache[texture_id]
end
#-----------------------------
def create_textureset_from_data(textureset_data)
rect = Rect.new(0, 0, 32, 32)
textureset_height = 1 + (textureset_data.size >> 3) << 5
self.textureset = Bitmap.new(256, textureset_height)
src = Cache.tileset(tileset_name)
textureset_data.each_index {|texture_id|
t_dat = textureset_data[texture_id]
if t_dat
x_trg = texture_id - (texture_id >> 3 << 3) << 5
y_trg = texture_id >> 3 << 5
rect.x = t_dat[0]
rect.y = t_dat[1]
if t_dat[0] == 0 && t_dat[1] == 0
@texture_id_nil = texture_id
end
textureset.blt(x_trg, y_trg, src, rect)
end
}
@texturesets = [textureset]
@texturesets_widths = [8]
@texturesets_mapping_ids = {}
subsets_names_list = []
if @subsets_mapping
@subsets_mapping.each {|texture_id, subset_name|
if subsets_names_list.include?(subset_name)
@texturesets_mapping_ids[texture_id] =
subsets_names_list.index(subset_name) + 1
else
subsets_names_list << subset_name
subset = Cache.tileset(subset_name)
texturesets << subset
for k in 5..9
if subset.width >> k == 1
@texturesets_widths << k
break
end
end
@texturesets_mapping_ids[texture_id] = subsets_names_list.size
end
}
end
end
#-----------------------------
# * Retourne l'index du textureset pour une texture
# param textureset_data : Integer
# return Integer
#-----------------------------
def get_textureset_id(texture_id)
if @texturesets_mapping_ids.has_key?(texture_id)
return @texturesets_mapping_ids[texture_id]
else
return 0
end
end
#-----------------------------
# * Retourne la largeur du textureset pour une texture
# param textureset_data : Integer
# return Integer
#-----------------------------
def get_textureset_width(texture_id)
return @texturesets_widths[get_textureset_id(texture_id)]
end
#-----------------------------
# * Dispose
#-----------------------------
def dispose
if textureset then textureset.dispose end
end
#-----------------------------
# * Is texture valid
# param texture_id : Integer
# return Boolean
#-----------------------------
def is_texture_id_valid?(texture_id)
return texture_id && texture_id != @texture_id_nil
end
end
end
#==============================
# ** Spriteset_Weather
#==============================
class Spriteset_Weather
#-----------------------------
# * Modification of sprites coordinates when moving forward and backward
#-----------------------------
def update_fple
@sprites.each {|sprite|
if $game_temp.movement_dir == 8
sprite.x += (sprite.x + @ox - 272) / 8
sprite.y += (sprite.y + @oy - 208) / 8
sprite.opacity += 8
elsif $game_temp.movement_dir == 2
sprite.x -= (sprite.x + @ox - 272) / 8
sprite.y -= (sprite.y + @oy - 139) / 8
sprite.opacity -= 8
end
}
end
end
#==============================
# ** FPLE::Spriteset_Map
#==============================
module FPLE
class Spriteset_Map < ::Spriteset_Map
#-----------------------------
# * Public Instance Variables
#-----------------------------
attr_reader :character_surfaces # Array<FPLE::Surface_Characters>
attr_reader :viewport1 # Viewport
#-----------------------------
# * Create Tilemap
#-----------------------------
def create_tilemap
# do nothing
end
#-----------------------------
# * Create Character Surfaces
#-----------------------------
def create_characters
@character_surfaces = []
$game_map.events.values.each {|event|
character_surfaces << FPLE::Surface_Character.new(self, event)
}
@map_id = $game_map.map_id
initialize_fple_rendering
end
#-----------------------------
# * Create Airship Shadow Sprite
#-----------------------------
def create_shadow
# do nothing
end
#-----------------------------
# * Initialize FPLE rendering
#-----------------------------
def initialize_fple_rendering
FPLE.initialize_fple(self, @viewport1)
end
#-----------------------------
# * Dispose
#-----------------------------
def dispose
dispose_fple_rendering
super
end
#-----------------------------
# * Dispose of FPLE rendering
#-----------------------------
def dispose_fple_rendering
FPLE.dispose
end
#-----------------------------
# * Free Tilemap
#-----------------------------
def dispose_tilemap
# do nothing
end
#-----------------------------
# * Dispose of Character Surfaces
#-----------------------------
def dispose_characters
@character_surfaces.each {|surface| surface.dispose}
end
#-----------------------------
# * Free Airship Shadow Sprite
#-----------------------------
def dispose_shadow
# do nothing
end
#-----------------------------
# * Update Tileset
#-----------------------------
def update_tileset
# do nothing
end
#-----------------------------
# * Update Tilemap
#-----------------------------
def update_tilemap
# do nothing
end
#-----------------------------
# * Update Parallax
#-----------------------------
def update_parallax
super
if @parallax.bitmap
@parallax.ox += (@parallax.bitmap.width * FPLE.angle) / 90
end
end
#-----------------------------
# * Update Character Sprite
#-----------------------------
def update_characters
unless @map_id == $game_map.map_id then refresh_characters end
character_surfaces.each {|surface| surface.update}
update_fple_rendering
end
#-----------------------------
# * Update FPLE Rendering
#-----------------------------
def update_fple_rendering
FPLE.update
end
#-----------------------------
# * Update Airship Shadow Sprite
#-----------------------------
def update_shadow
# do nothing
end
#-----------------------------
# * Update Weather
#-----------------------------
def update_weather
@weather.type = $game_map.screen.weather_type
@weather.power = $game_map.screen.weather_power
@weather.ox = $game_map.display_x * 32 +
(Graphics.width * FPLE.angle) / 90 +
(Graphics.width * FPLE.offset_x >> 5)
@weather.oy = $game_map.display_y * 32
@weather.update
if FPLE.offset_y > 0 then @weather.update_fple end
end
end
end
#==============================
# ** FPLE::Surface_Character
#==============================
module FPLE
class Surface_Character
#-----------------------------
# * Public Instance Variables
#-----------------------------
attr_accessor :character # Game_Event
attr_accessor :bitmap_set # Bitmap
attr_accessor :bitmap # Bitmap
attr_accessor :visible # Boolean
attr_accessor :opacity # Integer
attr_accessor :blend_type # Integer
attr_accessor :dx # Integer
attr_accessor :dy # Integer
attr_accessor :displayed # Boolean
attr_reader :spriteset # FPLE::Spriteset_Map
attr_reader :type # Integer
attr_reader :v_align # Integer
attr_reader :d_align # Integer
attr_reader :fit # Integer (0/1)
attr_reader :zoom # Integer (1024 <=> zoom = 1.0)
attr_reader :mirror # Integer (0/1) # [1.5]
#-----------------------------
# * Object Initialization
# param spriteset : FPLE::Spriteset_Map
# param character : Game_Event
#-----------------------------
def initialize(spriteset, character = nil)
@spriteset = spriteset
self.character = character
self.displayed = false
@need_refresh = false
@dx_old = 0
@dy_old = 0
@sx_old = -1
@sy_old = -1
@visible_old
@opacity_old
@blend_type_old
@sprite_temp = nil
@balloon_duration = 0
if character
@fit = character.fple_fit
@zoom = character.fple_zoom
else
@fit = 0
@zoom = 1024
end
@mirror = 0 # [1.5]
update
end
#-----------------------------
# * Dispose
#-----------------------------
def dispose
if @sprite_temp
@sprite_temp.dispose
@sprite_temp = nil
end
if bitmap_set then self.bitmap_set.dispose end
if bitmap then self.bitmap.dispose end
end
#-----------------------------
# * Get tile set image that includes the designated tile
# param tile_id : Integer
#-----------------------------
def tileset_bitmap(tile_id)
set_number = tile_id / 256
return Cache.system("TileB") if set_number == 0
return Cache.system("TileC") if set_number == 1
return Cache.system("TileD") if set_number == 2
return Cache.system("TileE") if set_number == 3
return nil
end
#-----------------------------
# * Frame Update
#-----------------------------
def update
update_bitmap
update_src_rect
update_position
update_other
update_balloon
setup_new_effect
if need_refresh? then force_render end
end
#-----------------------------
# * Update Transfer Origin Bitmap
#-----------------------------
def update_bitmap
if graphic_changed?
@tile_id = @character.tile_id
@character_name = @character.character_name
@character_index = @character.character_index
if @tile_id > 0
set_tile_bitmap
else
set_character_bitmap
end
@need_refresh = true
end
end
#-----------------------------
# * Determine if Graphic Changed
#-----------------------------
def graphic_changed?
@tile_id != character.tile_id ||
@character_name != character.character_name ||
@character_index != character.character_index
end
#-----------------------------
# * Set Tile Bitmap
#-----------------------------
def set_tile_bitmap
@sx = (@tile_id / 128 % 2 * 8 + @tile_id % 8) * 32;
@sy = @tile_id % 256 / 8 % 16 * 32;
self.bitmap_set = tileset_bitmap(@tile_id)
@cw = 32
@ch = 32
self.bitmap = Bitmap.new(@cw, @ch)
end
#-----------------------------
# * Set Character Bitmap
#-----------------------------
def set_character_bitmap
self.bitmap_set = Cache.character(@character_name)
sign = @character_name[/^[\!\$]./]
if sign && sign.include?('$')
@cw = bitmap_set.width / 3
@ch = bitmap_set.height / 4
else
@cw = bitmap_set.width / 12
@ch = bitmap_set.height / 8
end
self.bitmap = Bitmap.new(@cw, @ch)
end
#-----------------------------
# * Update Transfer Origin Rectangle
#-----------------------------
def update_src_rect
if @tile_id == 0
index = character.character_index
pattern = character.pattern < 3 ? character.pattern : 1
@sx = (index % 4 * 3 + pattern) * @cw
unless character.direction_fix
case $game_player.direction
when 2
direction = 10 - character.direction
when 4
direction = 10 - FPLE::TURN_LEFT[(character.direction >> 1) - 1]
when 6
direction = FPLE::TURN_LEFT[(character.direction >> 1) - 1]
when 8
direction = character.direction
end
else
direction = character.direction
end
@sy = ((index >> 2 << 2) + (direction - 2 >> 1)) * @ch
end
if @sx_old != @sx || @sy_old != @sy
return if @sx == @sx_old && @sy == @sy_old && !@bitmap_dirty
self.bitmap.clear
self.bitmap.blt(0, 0, bitmap_set, Rect.new(@sx, @sy, @cw, @ch))
@sx_old = @sx
@sy_old = @sy
@bitmap_dirty = false
end
end
#-----------------------------
# * Update Position
#-----------------------------
def update_position
self.dx = (128 * character.real_x).to_i
self.dy = (128 * character.real_y).to_i
end
#-----------------------------
# * Update Other
#-----------------------------
def update_other
self.opacity = character.opacity
self.blend_type = character.blend_type
self.visible = !character.transparent
end
#-----------------------------
# * Set New Effect
#-----------------------------
def setup_new_effect
if character.animation_id > 0
if displayed
unless @sprite_temp
# create a temporary sprite to launch animation
@sprite_temp = Sprite_Base.new(spriteset.viewport1)
end
coordinates = find_coordinates
if coordinates
@sprite_temp.x = coordinates[0]
@sprite_temp.y = coordinates[1]
animation = $data_animations[character.animation_id]
@sprite_temp.start_animation(animation)
else
@sprite_temp.dispose
@sprite_temp = nil
end
end
character.animation_id = 0
end
if @sprite_temp
@sprite_temp.update
unless @sprite_temp.animation?
@sprite_temp.dispose
@sprite_temp = nil
end
end
if !@balloon_sprite && character.balloon_id != 0
@balloon_id = character.balloon_id
start_balloon
end
end
#-----------------------------
# * Determine if Changed
#-----------------------------
def need_refresh?
@need_refresh || @dx_old != dx || @dy_old != dy ||
@sx_old != @sx || @sy_old != @sy ||
@visible_old != visible || @opacity_old != opacity ||
@blend_type_old != blend_type
end
#-----------------------------
# * Force Render
#-----------------------------
def force_render
if displayed then $game_temp.force_render = true end
@dx_old = dx
@dy_old = dy
@sx_old = @sx
@sy_old = @sy
@visible_old = visible
@opacity_old = opacity
@blend_type_old = blend_type
@need_refresh = false
end
#-----------------------------
# * Refresh FPLE attributes sepending on the relative frame of reference
# param direction : Integer
#-----------------------------
def set_relative_attributes(direction)
# For 4-sided and 6-sided surfaces, we don't need to change attributes
# since all sides are rendered automatically
if character.fple_four_side
@type = 3 # Special identifier for 4-sided
@d_align = character.fple_d_align
@v_align = character.fple_v_align
@mirror = 0 # Could add logic for different mirror states per side if needed
return
elsif character.fple_six_side
@type = 4 # Special identifier for 6-sided
@d_align = character.fple_d_align
@v_align = character.fple_v_align
@mirror = 0 # Could add logic for different mirror states per side if needed
return
end
# Original logic for single surfaces
case direction
when 2
@type = character.fple_type
@d_align = 2 - character.fple_d_align
if character.fple_one_side
@mirror = 1
if type == 2 && ($game_player.x << 7) - dx <= 0
@mirror = 0
end
end
when 4
if character.fple_type > 0
@type = 3 - character.fple_type
else
@type = 0
end
if character.fple_type < 2
@d_align = character.fple_d_align
elsif character.fple_type == 2
@d_align = 2 - character.fple_d_align
end
if character.fple_one_side
@mirror = 1
if type == 2 && ($game_player.y << 7) - dy > 0
@mirror = 0
end
end
when 6
if character.fple_type > 0
@type = 3 - character.fple_type
else
@type = 0
end
if character.fple_type < 2
@d_align = 2 - character.fple_d_align
elsif character.fple_type == 2
@d_align = character.fple_d_align
end
if character.fple_one_side
@mirror = 0
if type == 2 && ($game_player.y << 7) - dy < 0
@mirror = 1
end
end
when 8
@type = character.fple_type
@d_align = character.fple_d_align
if character.fple_one_side
@mirror = 0
if type == 2 && ($game_player.x << 7) - dx >= 0
@mirror = 1
end
end
end
@v_align = character.fple_v_align
end
#-----------------------------
# * Calculate screen coordinates to display animations
# return Array[2]<Integer>
#-----------------------------
def find_coordinates
direction = $game_player.direction
case direction
when 2
y = dy - ($game_player.y << 7)
x = ($game_player.x << 7) - dx
when 4
y = ($game_player.x << 7) - dx
x = ($game_player.y << 7) - dy
when 6
y = dx - ($game_player.x << 7)
x = dy - ($game_player.y << 7)
when 8
y = ($game_player.y << 7) - dy
x = dx - ($game_player.x << 7)
end
if y == 0 then return nil end
offset_x = 0
offset_y = 0
if character.fple_v_align != 1
x1_proj = 272 + (272 * x - (136 << 7)) / y
x2_proj = 272 + (272 * x + (136 << 7)) / y
offset_x = x2_proj - x1_proj >> 1
offset_y = offset_x
if bitmap
offset_x -= (bitmap.width >> 1)
offset_y -= (bitmap.height >> 1)
end
end
x_proj = 272 + (272 * x) / y
y_proj = ((544 * y) - (272 << 7)) / (y << 1)
if character.fple_v_align == 0
y_proj -= offset_y
elsif character.fple_v_align == 2
y_proj += offset_y
end
return [x_proj, y_proj]
end
#-----------------------------
# * Start Balloon Icon Display
#-----------------------------
def start_balloon
dispose_balloon
@balloon_duration = 8 * balloon_speed + balloon_wait
@balloon_sprite = ::Sprite.new(spriteset.viewport1)
@balloon_sprite.bitmap = Cache.system("Balloon")
@balloon_sprite.ox = -16
@balloon_sprite.oy = +128
update_balloon
end
#-----------------------------
# * Dispose of Balloon Icon
#-----------------------------
def dispose_balloon
if @balloon_sprite
@balloon_sprite.dispose
@balloon_sprite = nil
end
end
#-----------------------------
# * Update Balloon Icon
#-----------------------------
def update_balloon
if @balloon_duration > 0
@balloon_duration -= 1
if @balloon_duration > 0
coordinates = find_coordinates
if coordinates
@balloon_sprite.x = coordinates[0]
@balloon_sprite.y = coordinates[1]
@balloon_sprite.z = 9999
sx = balloon_frame_index * 32
sy = (@balloon_id - 1) * 32
@balloon_sprite.src_rect.set(sx, sy, 32, 32)
else
end_balloon
end
else
end_balloon
end
end
end
#-----------------------------
# * End Balloon Icon
#-----------------------------
def end_balloon
dispose_balloon
character.balloon_id = 0
end
#-----------------------------
# * Balloon Icon Display Speed
#-----------------------------
def balloon_speed
return 8
end
#-----------------------------
# * Wait Time for Last Frame of Balloon
#-----------------------------
def balloon_wait
return 12
end
#-----------------------------
# * Frame Number of Balloon Icon
#-----------------------------
def balloon_frame_index
return 7 - [(@balloon_duration - balloon_wait) / balloon_speed, 0].max
end
end
end
#==============================
# ** Scene_Map
#==============================
class Scene_Map < Scene_Base
#-----------------------------
# * Aliased methods (F12 compatibility)
#-----------------------------
unless @already_aliased_fple
alias create_spriteset_fple create_spriteset
alias perform_transfer_fple perform_transfer
alias post_transfer_fple post_transfer
@already_aliased_fple = true
end
#-----------------------------
# * Create Sprite Set
#-----------------------------
def create_spriteset
if $game_system.fple
@spriteset = FPLE::Spriteset_Map.new
else
create_spriteset_fple
end
end
#-----------------------------
# * Player Transfer Processing
#-----------------------------
def perform_transfer
@exec_transfer = $game_player.transfer?
@fple_old = $game_system.fple
perform_transfer_fple
end
#-----------------------------
# * Post Processing for Transferring Player
#-----------------------------
def post_transfer
if @exec_transfer && @fple_old != $game_system.fple
@spriteset.dispose
create_spriteset
end
if $game_system.fple
$game_temp.force_render = true
end
post_transfer_fple
end
end
Code:
#==============================================================================
# ** FPLE Background Picture Addon - Enhanced
#v.1.5 old, now upgraded to v.1.8 using Claude.AI by 5Brainplay.
#==============================================================================
# This addon creates a background picture that renders behind all FPLE surfaces
# but in front of the engine's default background to prevent color bleeding.
# The background now positions itself at VIEW_DISTANCE + 1 for proper depth.
#==============================================================================
module FPLE
#--------------------------------------------------------------------------
# * Background Picture Configuration
#--------------------------------------------------------------------------
BACKGROUND_ENABLED = false # Enable/disable background picture
BACKGROUND_COLOR = Color.new(115, 190, 215, 255) # Default color (R,G,B,A)
BACKGROUND_PICTURE_FILE = nil # Optional: use "filename" for custom image
BACKGROUND_Z_DEPTH = -999 # Z-depth (negative = behind everything)
end
#==============================================================================
# ** FPLE Core - Modified
#==============================================================================
module FPLE
#--------------------------------------------------------------------------
# * Aliased initialization method
#--------------------------------------------------------------------------
class << self
unless @background_addon_aliased
alias initialize_fple_background initialize_fple
@background_addon_aliased = true
end
end
#--------------------------------------------------------------------------
# * Initialize with background
#--------------------------------------------------------------------------
def self.initialize_fple(spriteset, viewport)
initialize_fple_background(spriteset, viewport)
if BACKGROUND_ENABLED
create_background_picture(viewport)
end
end
#--------------------------------------------------------------------------
# * Create background picture with view distance integration
#--------------------------------------------------------------------------
def self.create_background_picture(viewport)
@background_sprite = Sprite.new(viewport)
@background_sprite.z = BACKGROUND_Z_DEPTH
if BACKGROUND_PICTURE_FILE && FileTest.exist?("Graphics/Pictures/#{BACKGROUND_PICTURE_FILE}.png")
# Use custom image file
@background_sprite.bitmap = Cache.picture(BACKGROUND_PICTURE_FILE)
else
# Create solid color background
@background_sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)
@background_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, BACKGROUND_COLOR)
end
# Position behind everything but visible
@background_sprite.x = 0
@background_sprite.y = 0
# Add background surface to the surfaces array for proper depth rendering
create_background_surface
end
#--------------------------------------------------------------------------
# * Create background surface at VIEW_DISTANCE + 1
#--------------------------------------------------------------------------
def self.create_background_surface
# Calculate the distance to render the background at (VIEW_DISTANCE + 1)
background_distance = ($game_system.fple_view_distance + 1) << 7
# Create a background surface that will be processed by the 3D engine
@background_surface = [
0, # texture_id (0 = no texture, use solid color)
background_distance, # dy (depth distance)
0, # dx (horizontal offset)
6, # type (6 = background plane, custom type)
0, # secondary texture
0, # z-order placeholder
0, # textureset_id
8, # textureset_width
BACKGROUND_COLOR.red, # red component
BACKGROUND_COLOR.green, # green component
BACKGROUND_COLOR.blue, # blue component
BACKGROUND_COLOR.alpha # alpha component
]
end
#--------------------------------------------------------------------------
# * Add background surface to game map surfaces
#--------------------------------------------------------------------------
def self.add_background_to_surfaces
return unless BACKGROUND_ENABLED && @background_surface
# Calculate proper z-depth for background
distance = ($game_system.fple_view_distance) << 1
@background_surface[5] = distance << 5 # Set z-order
# Add background surface to the main surfaces array if not already present
unless $game_map.surfaces.any? { |surface| surface[3] == 6 }
$game_map.surfaces.push(@background_surface.dup)
end
end
#--------------------------------------------------------------------------
# * Aliased dispose method
#--------------------------------------------------------------------------
class << self
unless @dispose_background_aliased
alias dispose_background dispose
@dispose_background_aliased = true
end
end
#--------------------------------------------------------------------------
# * Dispose with background cleanup
#--------------------------------------------------------------------------
def self.dispose
dispose_background
if @background_sprite
@background_sprite.dispose
@background_sprite = nil
end
@background_surface = nil
end
#--------------------------------------------------------------------------
# * Update background (called during movement/rotation)
#--------------------------------------------------------------------------
def self.update_background
return unless @background_surface && BACKGROUND_ENABLED
# Update the background distance based on current view distance
background_distance = ($game_system.fple_view_distance) << 7
@background_surface[1] = background_distance
# Update z-order
distance = ($game_system.fple_view_distance) << 1
@background_surface[5] = distance << 5
# Add parallax effects if desired
if @angle != 0
# Slight horizontal shift based on rotation
@background_surface[2] = (@angle * 2) # Adjust multiplier as needed
else
@background_surface[2] = 0
end
# Adjust for movement offsets if desired (subtle parallax)
# @background_surface[2] += @offset_x / 8
end
#--------------------------------------------------------------------------
# * Aliased update method
#--------------------------------------------------------------------------
class << self
unless @update_background_aliased
alias update_fple_background update
@update_background_aliased = true
end
end
#--------------------------------------------------------------------------
# * Update with background
#--------------------------------------------------------------------------
def self.update
update_fple_background
if BACKGROUND_ENABLED
update_background
add_background_to_surfaces
end
end
end
#==============================================================================
# ** Game_Map - Background Integration
#==============================================================================
class Game_Map
#--------------------------------------------------------------------------
# * Aliased refresh_surfaces method
#--------------------------------------------------------------------------
unless @background_surfaces_aliased
alias refresh_surfaces_background refresh_surfaces
@background_surfaces_aliased = true
end
#--------------------------------------------------------------------------
# * Refresh surfaces with background integration
#--------------------------------------------------------------------------
def refresh_surfaces
refresh_surfaces_background
surfaces.sort! { |a, b| b[5] - a[5] } if surfaces.any? { |s| s[3] == 6 }
end
end
#==============================================================================
# ** Game_Interpreter - Script Commands
#==============================================================================
class Game_Interpreter
#--------------------------------------------------------------------------
# * Change FPLE Background Color
#--------------------------------------------------------------------------
def change_fple_background_color(red, green, blue, alpha = 255)
return unless $game_system.fple && FPLE::BACKGROUND_ENABLED
# Update the background surface color
if FPLE.instance_variable_get(:@background_surface)
surface = FPLE.instance_variable_get(:@background_surface)
surface[8] = red
surface[9] = green
surface[10] = blue
surface[11] = alpha
end
# Also update the sprite for immediate visual feedback
if FPLE.instance_variable_get(:@background_sprite)
sprite = FPLE.instance_variable_get(:@background_sprite)
color = Color.new(red, green, blue, alpha)
sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, color)
end
$game_temp.force_render = true
end
#--------------------------------------------------------------------------
# * Change FPLE Background Picture
#--------------------------------------------------------------------------
def change_fple_background_picture(filename)
return unless $game_system.fple && FPLE::BACKGROUND_ENABLED
if FPLE.instance_variable_get(:@background_sprite)
sprite = FPLE.instance_variable_get(:@background_sprite)
sprite.bitmap.dispose if sprite.bitmap
if filename && FileTest.exist?("Graphics/Pictures/#{filename}.png")
sprite.bitmap = Cache.picture(filename)
# When using a picture, set surface type to use texture instead of color
if FPLE.instance_variable_get(:@background_surface)
surface = FPLE.instance_variable_get(:@background_surface)
surface[0] = 1 # Enable texture rendering
end
else
# Fallback to solid color
sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)
sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, FPLE::BACKGROUND_COLOR)
# Reset to color mode
if FPLE.instance_variable_get(:@background_surface)
surface = FPLE.instance_variable_get(:@background_surface)
surface[0] = 0 # Disable texture, use color
end
end
end
$game_temp.force_render = true
end
#--------------------------------------------------------------------------
# * Toggle FPLE Background
#--------------------------------------------------------------------------
def toggle_fple_background(enabled)
return unless $game_system.fple
if FPLE.instance_variable_get(:@background_sprite)
sprite = FPLE.instance_variable_get(:@background_sprite)
sprite.visible = enabled
end
# Remove or add background surface based on enabled state
if enabled
FPLE.add_background_to_surfaces
else
$game_map.surfaces.reject! { |surface| surface[3] == 6 }
end
$game_temp.force_render = true
end
#--------------------------------------------------------------------------
# * Update Background Distance (call when VIEW_DISTANCE changes)
#--------------------------------------------------------------------------
def update_background_distance
return unless $game_system.fple && FPLE::BACKGROUND_ENABLED
if FPLE.instance_variable_get(:@background_surface)
FPLE.update_background
$game_temp.force_render = true
end
end
end
#==============================================================================
# ** Game_Temp - Background Integration
#==============================================================================
class Game_Temp
#--------------------------------------------------------------------------
# * Aliased set_view method to update background distance
#--------------------------------------------------------------------------
unless @background_view_aliased
alias set_view_background set_view
@background_view_aliased = true
end
#--------------------------------------------------------------------------
# * Set view distance with background update
#--------------------------------------------------------------------------
def set_view(distance)
set_view_background(distance)
# Update background distance when view distance changes
if $game_system.fple && FPLE::BACKGROUND_ENABLED
FPLE.update_background
end
end
end
#==============================================================================
# ** Usage Instructions
#==============================================================================
# Place this script below the main FPLE script but above Main.
#
# Configuration:
# - BACKGROUND_ENABLED: Set to true/false to enable/disable
# - BACKGROUND_COLOR: Set the RGB color (0-255 for each value)
# - BACKGROUND_PICTURE_FILE: Optional - use a picture file instead of solid color
# - BACKGROUND_Z_DEPTH: Z-depth value (negative = behind surfaces)
#
# The background will automatically render at VIEW_DISTANCE + 1, providing
# a backdrop that appears behind all game surfaces but maintains proper depth.
#
# Script Commands (use in events):
# - change_fple_background_color(255, 0, 0) # Change to red
# - change_fple_background_picture("sunset") # Use Graphics/Pictures/sunset.png
# - toggle_fple_background(false) # Hide background
# - toggle_fple_background(true) # Show background
# - update_background_distance # Refresh after VIEW_DISTANCE changes
#==============================================================================
Code:
#===============================================================================
# FPLE Ground Tile Swap Addon v1.1
# v.1.5 old, now upgraded to v.1.8 using Claude.AI by 5Brainplay.
# Author: Assistant
#===============================================================================
# This addon allows swapping ground tiles in FPLE maps during gameplay.
# Place this script below the main FPLE script but above "Main"
#
# Features:
# - Swap ground tiles at specific coordinates
# - Batch swap multiple tiles
# - Restore original tiles
# - Event-based tile swapping
# - Animated tile transitions (optional)
# - Region-based ground tile swapping
# - Animated region tiles
#
# Usage Examples:
# $game_map.swap_ground_tile(x, y, new_texture_id)
# $game_map.restore_ground_tile(x, y)
# $game_map.batch_swap_ground_tiles([[x1, y1, texture1], [x2, y2, texture2]])
# $game_map.swap_region_ground_tiles(region_id, texture_id)
#
# Event Commands:
# In event "Script..." command:
# swap_ground(x, y, texture_id)
# restore_ground(x, y)
# swap_region_ground(region_id, texture_id)
# animate_region_ground(region_id, base_texture_id)
#===============================================================================
#==============================================================================
# ** Game_Map - Ground Tile Swapping Extensions
#==============================================================================
class Game_Map
#--------------------------------------------------------------------------
# * Aliased methods
#--------------------------------------------------------------------------
unless @already_aliased_ground_swap
alias initialize_ground_swap initialize
alias setup_ground_swap setup
@already_aliased_ground_swap = true
end
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :original_ground_tiles # Hash to store original tile data
attr_accessor :swapped_ground_tiles # Hash to track swapped tiles
attr_accessor :animated_ground_tiles # Hash to store animation data
attr_accessor :ground_animation_timer # Integer for frame counting
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
initialize_ground_swap
@original_ground_tiles = {}
@swapped_ground_tiles = {}
@animated_ground_tiles = {}
@ground_animation_timer = 0
end
#--------------------------------------------------------------------------
# * Setup
#--------------------------------------------------------------------------
def setup(map_id)
setup_ground_swap(map_id)
@original_ground_tiles = {}
@swapped_ground_tiles = {}
@animated_ground_tiles = {}
@ground_animation_timer = 0
end
#--------------------------------------------------------------------------
# * Swap Ground Tile at Specific Coordinates
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# param new_texture_id : Integer - New ground texture ID
# param animate : Boolean - Whether to animate the transition (optional)
#--------------------------------------------------------------------------
def swap_ground_tile(x, y, new_texture_id, animate = false)
return unless is_fple? && @fple_map
return unless valid_coordinates?(x, y)
key = [x, y]
# Store original tile data if not already stored
unless @original_ground_tiles.has_key?(key)
original_data = @fple_map.get_data(x, y).dup
@original_ground_tiles[key] = original_data
end
# Use FPLE's proper method to change ground texture
if @fple_map.respond_to?(:change_ground)
@fple_map.change_ground(x, y, new_texture_id)
elsif @fple_map.respond_to?(:set_ground_tile)
@fple_map.set_ground_tile(x, y, new_texture_id)
else
# Fallback: try to modify the data structure directly
current_data = @fple_map.get_data(x, y)
if current_data && current_data.size > 1
current_data[1] = new_texture_id
else
return false
end
end
@swapped_ground_tiles[key] = new_texture_id
# Remove from animated tiles when doing a simple swap
@animated_ground_tiles.delete(key)
# Trigger visual update
if animate
animate_tile_swap(x, y)
else
force_surface_refresh
end
return true
end
#--------------------------------------------------------------------------
# * Create Animated Ground Tile (cycles through next 3 tiles)
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# param base_texture_id : Integer - Base texture ID (will use this +1, +2, +3)
# param frame_duration : Integer - Frames to wait between texture changes
# param animate : Boolean - Whether to animate the initial transition
#--------------------------------------------------------------------------
def create_animated_ground_tile(x, y, base_texture_id, frame_duration = 30, animate = false)
return unless is_fple? && @fple_map
return unless valid_coordinates?(x, y)
key = [x, y]
# Store original tile data if not already stored
unless @original_ground_tiles.has_key?(key)
original_data = @fple_map.get_data(x, y).dup
@original_ground_tiles[key] = original_data
end
# Setup animation data
animation_data = {
:frames => [base_texture_id, base_texture_id + 1, base_texture_id + 2],
:current_frame => 0,
:frame_duration => frame_duration,
:frame_counter => 0
}
@animated_ground_tiles[key] = animation_data
@swapped_ground_tiles[key] = base_texture_id
# Set initial texture
current_data = @fple_map.get_data(x, y)
if current_data && current_data.size > 1
current_data[1] = base_texture_id
# Trigger visual update
if animate
animate_tile_swap(x, y)
else
force_surface_refresh
end
return true
end
return false
end
#--------------------------------------------------------------------------
# * Restore Original Ground Tile
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
#--------------------------------------------------------------------------
def restore_ground_tile(x, y)
return unless is_fple? && @fple_map
return unless valid_coordinates?(x, y)
key = [x, y]
if @original_ground_tiles.has_key?(key)
# Restore original data
original_data = @original_ground_tiles[key]
current_data = @fple_map.get_data(x, y)
if current_data && original_data
current_data[1] = original_data[1] # Restore ground texture
@swapped_ground_tiles.delete(key)
@animated_ground_tiles.delete(key) # Remove animation data
force_surface_refresh
return true
end
end
return false
end
#--------------------------------------------------------------------------
# * Batch Swap Multiple Ground Tiles
# param tile_data : Array<Array> - [[x, y, texture_id], ...]
#--------------------------------------------------------------------------
def batch_swap_ground_tiles(tile_data)
return unless is_fple? && tile_data.is_a?(Array)
success_count = 0
tile_data.each do |data|
next unless data.is_a?(Array) && data.size >= 3
x, y, texture_id = data[0], data[1], data[2]
success_count += 1 if swap_ground_tile(x, y, texture_id, false)
end
force_surface_refresh if success_count > 0
return success_count
end
#--------------------------------------------------------------------------
# * Restore All Swapped Ground Tiles
#--------------------------------------------------------------------------
def restore_all_ground_tiles
return unless is_fple? && @fple_map
restored_count = 0
@swapped_ground_tiles.keys.each do |key|
x, y = key[0], key[1]
restored_count += 1 if restore_ground_tile(x, y)
end
force_surface_refresh if restored_count > 0
return restored_count
end
#--------------------------------------------------------------------------
# * Swap All Ground Tiles in a Specific Region
# param region_id : Integer - Region ID to target (1-63, or 0 for no region)
# param new_texture_id : Integer - New ground texture ID for all tiles in region
# param animate : Boolean - Whether to animate the transitions (optional)
# param exclude_events : Boolean - Whether to skip tiles with events (optional)
#--------------------------------------------------------------------------
def swap_region_ground_tiles(region_id, new_texture_id, animate = false, exclude_events = false)
return unless is_fple? && @fple_map
return unless region_id >= 0 && region_id <= 63
success_count = 0
# Loop through all tiles in the map
(0...width).each do |x|
(0...height).each do |y|
# Check if this tile has the target region ID
if region_id(x, y) == region_id
# Skip tiles with events if requested
if exclude_events && events_xy(x, y).any?
next
end
# Swap the ground tile
if swap_ground_tile(x, y, new_texture_id, false)
success_count += 1
end
end
end
end
# Handle animation/refresh after all swaps are done
if success_count > 0
if animate
# Create a region-wide flash effect
$game_map.screen.start_flash(Color.new(255, 255, 255, 80), 15)
end
force_surface_refresh
end
return success_count
end
#--------------------------------------------------------------------------
# * Create Animated Ground Tiles for Entire Region
# param region_id : Integer - Region ID to target (1-63, or 0 for no region)
# param base_texture_id : Integer - Base texture ID (will use this +1, +2)
# param frame_duration : Integer - Frames to wait between texture changes
# param animate : Boolean - Whether to animate the initial transition
# param exclude_events : Boolean - Whether to skip tiles with events (optional)
#--------------------------------------------------------------------------
def animate_region_ground_tiles(region_id, base_texture_id, frame_duration = 30, animate = false, exclude_events = false)
return unless is_fple? && @fple_map
return unless region_id >= 0 && region_id <= 63
success_count = 0
# Loop through all tiles in the map
(0...width).each do |x|
(0...height).each do |y|
# Check if this tile has the target region ID
if region_id(x, y) == region_id
# Skip tiles with events if requested
if exclude_events && events_xy(x, y).any?
next
end
# Create animated ground tile
if create_animated_ground_tile(x, y, base_texture_id, frame_duration, false)
success_count += 1
end
end
end
end
# Handle animation/refresh after all animations are set up
if success_count > 0
if animate
# Create a region-wide flash effect
$game_map.screen.start_flash(Color.new(200, 255, 200, 100), 20)
end
force_surface_refresh
end
return success_count
end
#--------------------------------------------------------------------------
# * Restore All Ground Tiles in a Specific Region
# param region_id : Integer - Region ID to target (1-63, or 0 for no region)
# param exclude_events : Boolean - Whether to skip tiles with events (optional)
#--------------------------------------------------------------------------
def restore_region_ground_tiles(region_id, exclude_events = false)
return unless is_fple? && @fple_map
return unless region_id >= 0 && region_id <= 63
restored_count = 0
# Loop through all swapped tiles and restore those in the target region
@swapped_ground_tiles.keys.each do |key|
x, y = key[0], key[1]
# Check if this tile is in the target region
if region_id(x, y) == region_id
# Skip tiles with events if requested
if exclude_events && events_xy(x, y).any?
next
end
# Restore the ground tile
if restore_ground_tile(x, y)
restored_count += 1
end
end
end
force_surface_refresh if restored_count > 0
return restored_count
end
#--------------------------------------------------------------------------
# * Check if Ground Tile is Swapped
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# return Boolean
#--------------------------------------------------------------------------
def ground_tile_swapped?(x, y)
return @swapped_ground_tiles.has_key?([x, y])
end
#--------------------------------------------------------------------------
# * Check if Ground Tile is Animated
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# return Boolean
#--------------------------------------------------------------------------
def ground_tile_animated?(x, y)
return @animated_ground_tiles.has_key?([x, y])
end
#--------------------------------------------------------------------------
# * Update Ground Tile Animations (call this from Scene_Map update)
#--------------------------------------------------------------------------
def update_ground_animations
return unless is_fple? && @fple_map
return if @animated_ground_tiles.empty?
@ground_animation_timer += 1
needs_refresh = false
@animated_ground_tiles.each do |key, animation_data|
animation_data[:frame_counter] += 1
if animation_data[:frame_counter] >= animation_data[:frame_duration]
# Reset counter and advance frame
animation_data[:frame_counter] = 0
animation_data[:current_frame] = (animation_data[:current_frame] + 1) % animation_data[:frames].size
# Update the tile texture using proper FPLE methods
x, y = key[0], key[1]
new_texture_id = animation_data[:frames][animation_data[:current_frame]]
# Use FPLE's proper method to change ground texture
success = false
if @fple_map.respond_to?(:change_ground)
@fple_map.change_ground(x, y, new_texture_id)
success = true
elsif @fple_map.respond_to?(:set_ground_tile)
@fple_map.set_ground_tile(x, y, new_texture_id)
success = true
else
# Fallback: try to modify the data structure directly
current_data = @fple_map.get_data(x, y)
if current_data && current_data.is_a?(Array) && current_data.size > 1
current_data[1] = new_texture_id
success = true
end
end
if success
@swapped_ground_tiles[key] = new_texture_id
needs_refresh = true
end
end
end
force_surface_refresh if needs_refresh
end
#--------------------------------------------------------------------------
# * Get Current Ground Texture ID
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# return Integer
#--------------------------------------------------------------------------
def get_ground_texture_id(x, y)
return nil unless valid_coordinates?(x, y) && @fple_map
tile_data = @fple_map.get_data(x, y)
return tile_data ? tile_data[1] : nil
end
#--------------------------------------------------------------------------
# * Get Original Ground Texture ID
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# return Integer
#--------------------------------------------------------------------------
def get_original_ground_texture_id(x, y)
key = [x, y]
if @original_ground_tiles.has_key?(key)
return @original_ground_tiles[key][1]
else
return get_ground_texture_id(x, y)
end
end
#--------------------------------------------------------------------------
# * Animate Tile Swap (Simple fade effect)
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
#--------------------------------------------------------------------------
def animate_tile_swap(x, y)
# This is a placeholder for animation
# In a full implementation, you might want to:
# - Create temporary sprites for transition effects
# - Use screen flashes or particle effects
# - Gradually fade between old and new textures
$game_map.screen.start_flash(Color.new(255, 255, 255, 60), 10)
force_surface_refresh
end
private
#--------------------------------------------------------------------------
# * Validate Coordinates
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# return Boolean
#--------------------------------------------------------------------------
def valid_coordinates?(x, y)
return x >= 0 && x < width && y >= 0 && y < height
end
#--------------------------------------------------------------------------
# * Force Surface Refresh
#--------------------------------------------------------------------------
def force_surface_refresh
$game_temp.force_render = true if $game_temp
end
end
#==============================================================================
# ** Game_Interpreter - Event Commands for Ground Swapping
#==============================================================================
class Game_Interpreter
#--------------------------------------------------------------------------
# * Swap Ground Tile (Event Command)
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# param texture_id : Integer - New ground texture ID
#--------------------------------------------------------------------------
def swap_ground(x, y, texture_id)
$game_map.swap_ground_tile(x, y, texture_id, true)
end
#--------------------------------------------------------------------------
# * Create Animated Ground Tile (Event Command)
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# param base_texture_id : Integer - Base texture ID (uses this +1, +2)
# param frame_duration : Integer - Frames between animation changes (default: 30)
#--------------------------------------------------------------------------
def animate_ground(x, y, base_texture_id, frame_duration = 30)
$game_map.create_animated_ground_tile(x, y, base_texture_id, frame_duration, true)
end
#--------------------------------------------------------------------------
# * Restore Ground Tile (Event Command)
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
#--------------------------------------------------------------------------
def restore_ground(x, y)
$game_map.restore_ground_tile(x, y)
end
#--------------------------------------------------------------------------
# * Batch Swap Ground Tiles (Event Command)
# param tile_array : Array<Array> - [[x, y, texture_id], ...]
#--------------------------------------------------------------------------
def batch_swap_ground(tile_array)
$game_map.batch_swap_ground_tiles(tile_array)
end
#--------------------------------------------------------------------------
# * Restore All Ground Tiles (Event Command)
#--------------------------------------------------------------------------
def restore_all_ground
$game_map.restore_all_ground_tiles
end
#--------------------------------------------------------------------------
# * Swap All Ground Tiles in Region (Event Command)
# param region_id : Integer - Region ID to target (1-63, or 0 for no region)
# param texture_id : Integer - New ground texture ID
# param exclude_events : Boolean - Skip tiles with events (optional)
#--------------------------------------------------------------------------
def swap_region_ground(region_id, texture_id, exclude_events = false)
$game_map.swap_region_ground_tiles(region_id, texture_id, true, exclude_events)
end
#--------------------------------------------------------------------------
# * Create Animated Ground Tiles for Region (Event Command)
# param region_id : Integer - Region ID to target
# param base_texture_id : Integer - Base texture ID (uses this +1, +2)
# param frame_duration : Integer - Frames between animation changes (default: 30)
# param exclude_events : Boolean - Skip tiles with events (optional)
#--------------------------------------------------------------------------
def animate_region_ground(region_id, base_texture_id, frame_duration = 30, exclude_events = false)
$game_map.animate_region_ground_tiles(region_id, base_texture_id, frame_duration, true, exclude_events)
end
#--------------------------------------------------------------------------
# * Restore All Ground Tiles in Region (Event Command)
# param region_id : Integer - Region ID to target
# param exclude_events : Boolean - Skip tiles with events (optional)
#--------------------------------------------------------------------------
def restore_region_ground(region_id, exclude_events = false)
$game_map.restore_region_ground_tiles(region_id, exclude_events)
end
#--------------------------------------------------------------------------
# * Check if Ground Tile is Swapped (Event Command)
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# return Boolean
#--------------------------------------------------------------------------
def ground_swapped?(x, y)
return $game_map.ground_tile_swapped?(x, y)
end
#--------------------------------------------------------------------------
# * Check if Ground Tile is Animated (Event Command)
# param x : Integer - X coordinate
# param y : Integer - Y coordinate
# return Boolean
#--------------------------------------------------------------------------
def ground_animated?(x, y)
return $game_map.ground_tile_animated?(x, y)
end
end
#==============================================================================
# ** Game_Temp - Additional Switches and Variables
#==============================================================================
class Game_Temp
#--------------------------------------------------------------------------
# * Aliased methods
#--------------------------------------------------------------------------
unless @already_aliased_ground_swap_temp
alias initialize_ground_swap_temp initialize
@already_aliased_ground_swap_temp = true
end
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :ground_swap_animation # Boolean - Enable swap animations
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
initialize_ground_swap_temp
@ground_swap_animation = true
end
#--------------------------------------------------------------------------
# * Enable/Disable Ground Swap Animations
# param enabled : Boolean
#--------------------------------------------------------------------------
def set_ground_swap_animation(enabled)
@ground_swap_animation = enabled
end
end
#==============================================================================
# ** DataManager - Save/Load Support
#==============================================================================
module DataManager
#--------------------------------------------------------------------------
# * Aliased methods
#--------------------------------------------------------------------------
class << self
unless @already_aliased_ground_swap_data
alias make_save_contents_ground_swap make_save_contents
alias extract_save_contents_ground_swap extract_save_contents
@already_aliased_ground_swap_data = true
end
end
#--------------------------------------------------------------------------
# * Create Save Contents
#--------------------------------------------------------------------------
def self.make_save_contents
contents = make_save_contents_ground_swap
contents[:ground_swaps] = {
:original_tiles => $game_map.original_ground_tiles,
:swapped_tiles => $game_map.swapped_ground_tiles,
:animated_tiles => $game_map.animated_ground_tiles
}
contents
end
#--------------------------------------------------------------------------
# * Extract Save Contents
#--------------------------------------------------------------------------
def self.extract_save_contents(contents)
extract_save_contents_ground_swap(contents)
if contents[:ground_swaps]
$game_map.original_ground_tiles = contents[:ground_swaps][:original_tiles] || {}
$game_map.swapped_ground_tiles = contents[:ground_swaps][:swapped_tiles] || {}
$game_map.animated_ground_tiles = contents[:ground_swaps][:animated_tiles] || {}
end
end
end
#==============================================================================
# ** Scene_Map - Animation Updates
#==============================================================================
class Scene_Map < Scene_Base
#--------------------------------------------------------------------------
# * Aliased methods
#--------------------------------------------------------------------------
unless @already_aliased_ground_swap_scene
alias update_ground_swap_scene update
@already_aliased_ground_swap_scene = true
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
update_ground_swap_scene
$game_map.update_ground_animations if $game_system.fple
end
end
#==============================================================================
# ** Usage Examples and Helper Methods
#==============================================================================
# Example usage in events:
#
# Script Command Examples:
# swap_ground(5, 3, 10) # Swap tile at (5,3) to texture 10
# animate_ground(5, 3, 15, 60) # Animate tile at (5,3) using textures 15,16,17 with 60-frame delays
# animate_ground(2, 4, 20) # Animate tile at (2,4) using textures 20,21,22 with default 30-frame delays
# restore_ground(5, 3) # Restore original tile at (5,3)
# batch_swap_ground([[1,1,5], [1,2,5]]) # Swap multiple tiles at once
# restore_all_ground # Restore all swapped tiles
# swap_region_ground(5, 10) # Swap all tiles in region 5 to texture 10
# swap_region_ground(3, 15, true) # Swap region 3, skip tiles with events
# animate_region_ground(2, 20) # Animate all tiles in region 2 using textures 20,21,22
# animate_region_ground(4, 25, 60, true) # Animate region 4 with 60-frame delays, skip events
# restore_region_ground(5) # Restore all tiles in region 5 to original
# restore_region_ground(3, true) # Restore region 3, skip tiles with events
#
# Conditional Branch Examples:
# if ground_swapped?(5, 3)
# # Do something if tile is swapped
# end
#
# if ground_animated?(5, 3)
# # Do something if tile is animated
# end
#
# Advanced Script Examples:
# $game_map.create_animated_ground_tile($game_player.x, $game_player.y, 15, 45)
# $game_map.swap_ground_tile($game_player.x, $game_player.y, 15)
# texture_id = $game_map.get_ground_texture_id(5, 3)
# original_id = $game_map.get_original_ground_texture_id(5, 3)
# count = $game_map.swap_region_ground_tiles(1, 12, false, true)
# $game_map.animate_region_ground_tiles(7, 30, 45)
# Global helper methods for easier access
def swap_ground_tile(x, y, texture_id, animate = true)
$game_map.swap_ground_tile(x, y, texture_id, animate)
end
def create_animated_ground_tile(x, y, base_texture_id, frame_duration = 30, animate = true)
$game_map.create_animated_ground_tile(x, y, base_texture_id, frame_duration, animate)
end
def restore_ground_tile(x, y)
$game_map.restore_ground_tile(x, y)
end
def ground_tile_swapped?(x, y)
$game_map.ground_tile_swapped?(x, y)
end
def ground_tile_animated?(x, y)
$game_map.ground_tile_animated?(x, y)
end
def swap_region_ground_tiles(region_id, texture_id, animate = true, exclude_events = false)
$game_map.swap_region_ground_tiles(region_id, texture_id, animate, exclude_events)
end
def animate_region_ground_tiles(region_id, base_texture_id, frame_duration = 30, animate = true, exclude_events = false)
$game_map.animate_region_ground_tiles(region_id, base_texture_id, frame_duration, animate, exclude_events)
end
def restore_region_ground_tiles(region_id, exclude_events = false)
$game_map.restore_region_ground_tiles(region_id, exclude_events)
end
Code:
#==============================================================================
# ** FPLE Third Person Player Sprite
# v.1.5 old, now upgraded to v.1.8 using Claude.AI by 5Brainplay.
#==============================================================================
# This script adds a third-person view sprite of the player character that
# appears on screen during FPLE mode. The sprite can be positioned, scaled,
# and configured to show the player's current state.
#==============================================================================
module FPLE
#--------------------------------------------------------------------------
# * Player Sprite Configuration
#--------------------------------------------------------------------------
PLAYER_SPRITE_DEFAULT_X = 300 # Default X position on screen
PLAYER_SPRITE_DEFAULT_Y = 450 # Default Y position on screen
PLAYER_SPRITE_DEFAULT_SCALE = 3.0 # Default scale multiplier
PLAYER_SPRITE_DEFAULT_OPACITY = 255 # Default opacity (0-255)
PLAYER_SPRITE_Z = 1000 # Z-order (higher = in front)
PLAYER_SPRITE_DEFAULT_ANIMATE = true # Default enable walking animation
PLAYER_SPRITE_UPDATE_DIRECTION = false # Update sprite direction based on player facing
#--------------------------------------------------------------------------
# * Player Sprite Settings (Dynamic)
#--------------------------------------------------------------------------
@@player_sprite_enabled = true
@@player_sprite_animate = PLAYER_SPRITE_DEFAULT_ANIMATE
def self.player_sprite_enabled
@@player_sprite_enabled
end
def self.player_sprite_enabled=(value)
@@player_sprite_enabled = value
end
def self.player_sprite_animate
@@player_sprite_animate
end
def self.player_sprite_animate=(value)
@@player_sprite_animate = value
end
end
#==============================================================================
# ** FPLE::Player_Sprite
#==============================================================================
module FPLE
class Player_Sprite < Sprite
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize(viewport = nil)
super(viewport)
@character = $game_player
@tile_id = 0
@character_name = ""
@character_index = 0
@pattern = 0
@direction = 8
@animation_count = 0
@stop_count = 0
@jump_count = 0
# Set initial position and properties
self.x = FPLE::PLAYER_SPRITE_DEFAULT_X
self.y = FPLE::PLAYER_SPRITE_DEFAULT_Y
self.z = FPLE::PLAYER_SPRITE_Z
self.zoom_x = FPLE::PLAYER_SPRITE_DEFAULT_SCALE
self.zoom_y = FPLE::PLAYER_SPRITE_DEFAULT_SCALE
self.opacity = FPLE::PLAYER_SPRITE_DEFAULT_OPACITY
update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
if FPLE.player_sprite_enabled
update_bitmap
update_src_rect
update_visibility
update_animation if FPLE.player_sprite_animate
else
self.visible = false
end
end
#--------------------------------------------------------------------------
# * Update Transfer Origin Bitmap
#--------------------------------------------------------------------------
def update_bitmap
if graphic_changed?
@tile_id = @character.tile_id
@character_name = @character.character_name
@character_index = @character.character_index
if @tile_id > 0
set_tile_bitmap
else
set_character_bitmap
end
end
end
#--------------------------------------------------------------------------
# * Determine if Graphic Changed
#--------------------------------------------------------------------------
def graphic_changed?
@tile_id != @character.tile_id ||
@character_name != @character.character_name ||
@character_index != @character.character_index
end
#--------------------------------------------------------------------------
# * Set Tile Bitmap
#--------------------------------------------------------------------------
def set_tile_bitmap
sx = (@tile_id / 128 % 2 * 8 + @tile_id % 8) * 32
sy = @tile_id % 256 / 8 % 16 * 32
self.bitmap = tileset_bitmap(@tile_id)
self.src_rect.set(sx, sy, 32, 32)
self.ox = 16
self.oy = 32
end
#--------------------------------------------------------------------------
# * Set Character Bitmap
#--------------------------------------------------------------------------
def set_character_bitmap
self.bitmap = Cache.character(@character_name)
sign = @character_name[/^[\!\$]./]
if sign && sign.include?('$')
@cw = bitmap.width / 3
@ch = bitmap.height / 4
else
@cw = bitmap.width / 12
@ch = bitmap.height / 8
end
self.ox = @cw / 2
self.oy = @ch
end
#--------------------------------------------------------------------------
# * Get Tileset Bitmap
#--------------------------------------------------------------------------
def tileset_bitmap(tile_id)
set_number = tile_id / 256
return Cache.system("TileB") if set_number == 0
return Cache.system("TileC") if set_number == 1
return Cache.system("TileD") if set_number == 2
return Cache.system("TileE") if set_number == 3
return nil
end
#--------------------------------------------------------------------------
# * Update Transfer Origin Rectangle
#--------------------------------------------------------------------------
def update_src_rect
if @tile_id == 0
index = @character.character_index
pattern = @pattern < 3 ? @pattern : 1
sx = (index % 4 * 3 + pattern) * @cw
# Update direction based on player facing if enabled
if FPLE::PLAYER_SPRITE_UPDATE_DIRECTION
@direction = @character.direction
end
sy = (index / 4 * 4 + (@direction - 2) / 2) * @ch
self.src_rect.set(sx, sy, @cw, @ch)
end
end
#--------------------------------------------------------------------------
# * Update Visibility
#--------------------------------------------------------------------------
def update_visibility
self.opacity = @character.opacity
self.blend_type = @character.blend_type
self.visible = !@character.transparent && FPLE.player_sprite_enabled
end
#--------------------------------------------------------------------------
# * Update Animation
#--------------------------------------------------------------------------
def update_animation
if $game_temp.movement
# Player is moving, animate the sprite
@stop_count = 0
update_animation_pattern
else
# Player is stationary
@stop_count += 1
if @stop_count > 20 # Stop animation after standing still
@pattern = 1 # Default standing pattern
@animation_count = 0
end
end
end
#--------------------------------------------------------------------------
# * Update Animation Pattern
#--------------------------------------------------------------------------
def update_animation_pattern
@animation_count += 1.5
if @animation_count > 18
if @pattern == 0
@pattern = 1
elsif @pattern == 1
@pattern = 2
elsif @pattern == 2
@pattern = 1
end
@animation_count = 0
end
end
#--------------------------------------------------------------------------
# * Set Position
#--------------------------------------------------------------------------
def set_position(x, y)
self.x = x
self.y = y
end
#--------------------------------------------------------------------------
# * Set Scale
#--------------------------------------------------------------------------
def set_scale(scale_x, scale_y = nil)
scale_y = scale_x if scale_y.nil?
self.zoom_x = scale_x
self.zoom_y = scale_y
end
#--------------------------------------------------------------------------
# * Set Direction (for manual control)
#--------------------------------------------------------------------------
def set_direction(direction)
@direction = direction
end
end
end
#==============================================================================
# ** FPLE::Spriteset_Map - Modified
#==============================================================================
# Add player sprite support to the existing FPLE spriteset
module FPLE
class Spriteset_Map < ::Spriteset_Map
#--------------------------------------------------------------------------
# * Aliased methods for player sprite
#--------------------------------------------------------------------------
unless @already_aliased_player_sprite
alias create_characters_with_player_sprite create_characters
alias dispose_characters_with_player_sprite dispose_characters
alias update_characters_with_player_sprite update_characters
@already_aliased_player_sprite = true
end
#--------------------------------------------------------------------------
# * Create Characters (with player sprite)
#--------------------------------------------------------------------------
def create_characters
create_characters_with_player_sprite
create_player_sprite
end
#--------------------------------------------------------------------------
# * Create Player Sprite
#--------------------------------------------------------------------------
def create_player_sprite
if FPLE.player_sprite_enabled
@player_sprite = FPLE::Player_Sprite.new(@viewport1)
end
end
#--------------------------------------------------------------------------
# * Dispose of Characters (with player sprite)
#--------------------------------------------------------------------------
def dispose_characters
dispose_player_sprite
dispose_characters_with_player_sprite
end
#--------------------------------------------------------------------------
# * Dispose of Player Sprite
#--------------------------------------------------------------------------
def dispose_player_sprite
if @player_sprite
@player_sprite.dispose
@player_sprite = nil
end
end
#--------------------------------------------------------------------------
# * Update Characters (with player sprite)
#--------------------------------------------------------------------------
def update_characters
update_characters_with_player_sprite
update_player_sprite
end
#--------------------------------------------------------------------------
# * Update Player Sprite
#--------------------------------------------------------------------------
def update_player_sprite
if @player_sprite
@player_sprite.update
end
end
end
end
#==============================================================================
# ** Game_Temp - Player Sprite Commands
#==============================================================================
class Game_Temp
#--------------------------------------------------------------------------
# * Show Player Sprite
#--------------------------------------------------------------------------
def show_player_sprite
if $game_system.fple
FPLE.player_sprite_enabled = true
end
end
#--------------------------------------------------------------------------
# * Hide Player Sprite
#--------------------------------------------------------------------------
def hide_player_sprite
if $game_system.fple
FPLE.player_sprite_enabled = false
end
end
#--------------------------------------------------------------------------
# * Set Player Sprite Position
#--------------------------------------------------------------------------
def set_player_sprite_position(x, y)
if $game_system.fple && SceneManager.scene.is_a?(Scene_Map)
spriteset = SceneManager.scene.instance_variable_get(:@spriteset)
if spriteset.is_a?(FPLE::Spriteset_Map) && spriteset.instance_variable_get(:@player_sprite)
spriteset.instance_variable_get(:@player_sprite).set_position(x, y)
end
end
end
#--------------------------------------------------------------------------
# * Set Player Sprite Scale
#--------------------------------------------------------------------------
def set_player_sprite_scale(scale_x, scale_y = nil)
if $game_system.fple && SceneManager.scene.is_a?(Scene_Map)
spriteset = SceneManager.scene.instance_variable_get(:@spriteset)
if spriteset.is_a?(FPLE::Spriteset_Map) && spriteset.instance_variable_get(:@player_sprite)
spriteset.instance_variable_get(:@player_sprite).set_scale(scale_x, scale_y)
end
end
end
#--------------------------------------------------------------------------
# * Get Player Sprite Position
#--------------------------------------------------------------------------
def get_player_sprite_position
if $game_system.fple && SceneManager.scene.is_a?(Scene_Map)
spriteset = SceneManager.scene.instance_variable_get(:@spriteset)
if spriteset.is_a?(FPLE::Spriteset_Map) && spriteset.instance_variable_get(:@player_sprite)
sprite = spriteset.instance_variable_get(:@player_sprite)
return [sprite.x, sprite.y]
end
end
return [0, 0]
end
#--------------------------------------------------------------------------
# * Reset Player Sprite to Default Position
#--------------------------------------------------------------------------
def reset_player_sprite_position
set_player_sprite_position(FPLE::PLAYER_SPRITE_DEFAULT_X, FPLE::PLAYER_SPRITE_DEFAULT_Y)
end
end
#==============================================================================
# ** Script Call Methods - Global functions for easier access
#==============================================================================
#--------------------------------------------------------------------------
# * Simple script call to set player sprite position
# Usage in script call: set_player_sprite_xy(300, 450)
#--------------------------------------------------------------------------
def set_player_sprite_xy(x, y)
if $game_system.fple && SceneManager.scene.is_a?(Scene_Map)
spriteset = SceneManager.scene.instance_variable_get(:@spriteset)
if spriteset.is_a?(FPLE::Spriteset_Map) && spriteset.instance_variable_get(:@player_sprite)
spriteset.instance_variable_get(:@player_sprite).set_position(x, y)
end
end
end
#--------------------------------------------------------------------------
# * Alternative: More direct access to the player sprite
# Usage in script call: player_sprite_position(100, 200)
#--------------------------------------------------------------------------
def player_sprite_position(x, y)
$game_temp.set_player_sprite_position(x, y)
end
#--------------------------------------------------------------------------
# * Set individual coordinates
# Usage: set_player_sprite_x(150) or set_player_sprite_y(300)
#--------------------------------------------------------------------------
def set_player_sprite_x(x)
if $game_system.fple && SceneManager.scene.is_a?(Scene_Map)
spriteset = SceneManager.scene.instance_variable_get(:@spriteset)
if spriteset.is_a?(FPLE::Spriteset_Map) && spriteset.instance_variable_get(:@player_sprite)
sprite = spriteset.instance_variable_get(:@player_sprite)
sprite.set_position(x, sprite.y)
end
end
end
def set_player_sprite_y(y)
if $game_system.fple && SceneManager.scene.is_a?(Scene_Map)
spriteset = SceneManager.scene.instance_variable_get(:@spriteset)
if spriteset.is_a?(FPLE::Spriteset_Map) && spriteset.instance_variable_get(:@player_sprite)
sprite = spriteset.instance_variable_get(:@player_sprite)
sprite.set_position(sprite.x, y)
end
end
end
#============== Author: MGC =================
# First Person Labyrinth Explorer (FPLE) Engine - VX Ace version
# v.1.5 old, now upgraded to v.1.+ using Claude.AI by 5Brainplay.
#========================================
# First Person Labyrinth Explorer (FPLE) Engine - VX Ace version
# v.1.5 old, now upgraded to v.1.+ using Claude.AI by 5Brainplay.
#========================================