09-05-2025, 09:30 PM
(This post was last modified: 09-06-2025, 01:00 AM by 5Brainplay.)
I fixed version without door calls for yami anti-lag, & added public to class game_map for private calls.
I'm currently trying to add a pool array with AI to help save FPS+50%, instead of hovering around 66 vs 99FPS+.
I'm currently trying to add a pool array with AI to help save FPS+50%, instead of hovering around 66 vs 99FPS+.
Code:
#===============================================================================
# First Person Labyrinth Explorer (FPLE) Engine - VX Ace version
# v.1.5
# Author: MGC
#===============================================================================
# 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
#--------------------------------------------------------------------------
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
surface[5] = (surface[1].abs << 5) + surface[2].abs
else # character surfaces
base_z = (surface[1].abs >> 1) + (surface[2].abs >> 6) - 2
# Check if surface has z-modifier (from 4-side/6-side rendering)
z_modifier = surface[15] || 0 # Additional z-modifier if present
# Add small offset based on surface type and alignment
type_offset = surface[7] || 0 # Surface type
align_offset = surface[8] || 0 # V-align
# Create unique z-values for different surface configurations
z_offset = case type_offset
when 1 # Horizontal walls
case surface[2] <=> 0 # dx comparison
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 # dy comparison
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
# Additional offset for vertical alignment
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
surface[5] = base_z.to_f + z_offset + v_align_offset + z_modifier
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 add_two_sided_surfaces(surface, dy, dx, surfaces_temp, i, dir)
# Handle special case where player is at same position as box
if dx == 0 && dy == 0
# For multi-sided boxes at same position, render as face-player type
surfaces_temp.push([0, 0, 0, 5, 0, 0,
surface.bitmap.__id__,
0, # Face player type for same position
surface.character.fple_v_align,
surface.character.fple_stretch,
surface.opacity,
surface.blend_type,
surface.fit,
surface.zoom,
0]) # No mirror
surface.displayed = true
return
end
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
if dx < -32
faces_to_render << {type: 2, d_align: 0, z_priority: 4, name: :left}
end
# Right face
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
# Render the faces
faces_to_render.each_with_index do |face_config, face_index|
side_dy = dy
side_dx = dx
# Apply position adjustments
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], # NEVER type 0
surface.character.fple_v_align, surface.character.fple_stretch,
surface.opacity, surface.blend_type,
surface.fit, surface.zoom, 0, z_modifier] # No mirror for multi-sided
surfaces_temp.push(surface_data)
end
surface.displayed = true
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 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
clear_character_surfaces(character_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(character_surfaces)
surfaces_temp2 += add_character_surfaces_right(character_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(character_surfaces)
surfaces_temp2 += add_character_surfaces_down(character_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(character_surfaces)
surfaces_temp2 += add_character_surfaces_up(character_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(character_surfaces)
surfaces_temp2 += add_character_surfaces_left(character_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
clear_character_surfaces(character_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(character_surfaces)
surfaces_temp2 += add_character_surfaces_down(character_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(character_surfaces)
surfaces_temp2 += add_character_surfaces_left(character_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(character_surfaces)
surfaces_temp2 += add_character_surfaces_right(character_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(character_surfaces)
surfaces_temp2 += add_character_surfaces_up(character_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
#--------------------------------------------------------------------------
# * 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