11-23-2010, 07:46 PM
RMXP : Add-on for the Neo Mode 7 Engine : Neo Mode 7 +
Version: 1.0
Version: 1.0
Introduction
This add-on for the Neo Mode 7 script was designed to increase a little the performances. Results may vary depending on the machine.
Features
- global performances slightly increased when rendering mode 7.
- mode 7 drawing only when moving -> lag is strongly reduced at stop.
- resolutions [R2]&[R3] applied only when moving -> not so ugly at stop (you can disable this feature by replacing "false" by "true" line 34.
Installation
Paste this script below the Neo Mode 7 script (compatible with the latest version on this board - 29/03/2010, or here), and copy the DLL at the root of your project.
Script :
Code:
#============================================================================
# Add-on : Neo Mode 7 +
# V.1.0 - 15/09/10
# Author : MGC
#
# This script increases (a little) the performances of the Neo Mode 7 engine.
# It is compliant with the 29/03/10 version that can be found on rmvxp.com.
# It requires the file "MGCmode7+.dll".
#
# Paste this script below the last part of the Neo Mode 7 script.
#============================================================================
#============================================================================
# ** Game_System
#============================================================================
class Game_System
#--------------------------------------------------------------------------
# * Aliased methods (F12 compatibility)
#--------------------------------------------------------------------------
unless @already_aliased_neoM7Plus
alias initialize_neoM7Plus_game_system initialize
@already_aliased_neoM7Plus = true
end
#--------------------------------------------------------------------------
# * Public Instance Variables
# fple_always_same_res (boolean): true = same quality when moving or not
#--------------------------------------------------------------------------
attr_accessor :neoM7Plus_always_same_res
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
initialize_neoM7Plus_game_system
self.neoM7Plus_always_same_res = false
end
end
#============================================================================
# ** Sprite
#============================================================================
class Sprite
#--------------------------------------------------------------------------
# calculate x and y coordinates in mode 7 for a vertical sprite
#--------------------------------------------------------------------------
def neoM7(x_map, y_map)
x_map = 32 * x_map
y_map = 32 * y_map
y_init = $game_temp.zoom_sprites * (y_map - $game_temp.pivot - $game_map.display_y.to_i / 4)
x_init = $game_temp.zoom_sprites * (x_map - 320 - $game_map.display_x.to_i / 4)
y_intermediate = (y_init * $game_temp.cos_theta -
x_init * $game_temp.sin_theta).to_i >> 11
x_intermediate = (x_init * $game_temp.cos_theta +
y_init * $game_temp.sin_theta).to_i >> 11
self.y = $game_temp.pivot + ($game_temp.distance_h * y_intermediate *
$game_temp.cos_alpha) / (($game_temp.distance_h << 11) - y_intermediate *
$game_temp.sin_alpha)
self.x = 320 + ($game_temp.slope_value * y +
$game_temp.corrective_value) * x_intermediate
end
#--------------------------------------------------------------------------
# calculate x and y coordinates in mode 7 for a character sprite
#--------------------------------------------------------------------------
def neoM7_character(x_screen, y_screen)
y_init = $game_temp.zoom_sprites * (y_screen - $game_temp.pivot)
x_init = $game_temp.zoom_sprites * (x_screen - 320)
y_intermediate = (y_init * $game_temp.cos_theta -
x_init * $game_temp.sin_theta).to_i >> 11
x_intermediate = (x_init * $game_temp.cos_theta +
y_init * $game_temp.sin_theta).to_i >> 11
self.y = $game_temp.pivot + ($game_temp.distance_h * y_intermediate *
$game_temp.cos_alpha) / (($game_temp.distance_h << 11) - y_intermediate *
$game_temp.sin_alpha)
self.x = (320 + ($game_temp.slope_value * y +
$game_temp.corrective_value) * x_intermediate)
end
end
#============================================================================
# ** Bitmap
#============================================================================
class Bitmap
NeoMode7Plus = Win32API.new("MGCmode7+.dll", "NeoMode7Plus", "lllllll", "l")
CHLP = Win32API.new("MGCmode7+.dll", "CleanHeightLimitPlus", "lll", "l")
#--------------------------------------------------------------------------
# mode 7 transformation
#--------------------------------------------------------------------------
def neoM7(tileset, data, map_width, map_height, off_x, off_y, options)
raise RGSSError.new("Disposed bitmap") if disposed?
NeoMode7Plus.call(self.__id__, tileset.__id__, data.__id__, off_x, off_y,
[$game_temp.cos_alpha, $game_temp.sin_alpha, $game_temp.distance_h,
$game_temp.pivot_map.to_i, $game_temp.slope_value_map,
$game_temp.corrective_value_map, $game_temp.neoM7_height_limit,
$game_temp.cos_theta, $game_temp.sin_theta, $game_temp.distance_p.to_i,
$game_temp.zoom_map].__id__, options.__id__)
end
#--------------------------------------------------------------------------
def neoM7_screen(tileset, data, map_width, map_height, off_x, off_y, options)
raise RGSSError.new("Disposed bitmap") if disposed?
NeoMode7Plus.call(self.__id__, tileset.__id__, data.__id__, off_x, off_y,
[$game_temp.cos_alpha, $game_temp.sin_alpha, $game_temp.distance_h,
$game_temp.pivot.to_i, $game_temp.slope_value_map,
(131072 * $game_temp.corrective_value).to_i, $game_temp.height_limit_sprites.to_i,
$game_temp.cos_theta, $game_temp.sin_theta, 0,
$game_temp.zoom_map].__id__, options.__id__)
end
#--------------------------------------------------------------------------
# delete pixels beyond the horizon
#--------------------------------------------------------------------------
def clean_limit(old_limit, new_limit)
raise RGSSError.new("Disposed bitmap") if disposed?
CHLP.call(self.__id__, old_limit, new_limit)
end
end
#============================================================================
# ** Tilemap_neoM7
#============================================================================
class Tilemap_neoM7
#--------------------------------------------------------------------------
# * Alias : F12 compatibility
#--------------------------------------------------------------------------
unless @already_aliased_neoM7Plus
alias increase_zoom_neoM7Plus_tilemap increase_zoom
alias set_zoom_neoM7Plus_tilemap set_zoom
alias update_animated_neoM7Plus_tilemap update_animated
@already_aliased_neoM7Plus = true
end
#--------------------------------------------------------------------------
# * Attributes
#--------------------------------------------------------------------------
attr_accessor :sprite_screen # sprite used to contain the map's drawing when not moving
#--------------------------------------------------------------------------
# * Object Initialization
# viewport : viewport
#--------------------------------------------------------------------------
def initialize(viewport, spriteset)
@even = true
@viewport = viewport
@spriteset = spriteset
@id = $game_map.map_id # map's ID : used to load or save the map in Cache
self.tilesets_list = [] # contains tilesets (Bitmap)
@height = $game_map.height << 5 # @height : map's height (in pixel)
@width = $game_map.width << 5 # @width : map's width (in pixel)
@options = [0, 0, 0]
@options[0] = $game_system.neoM7_loop ? 1 : 0
@zoom = $game_system.neoM7_zoom # zoom level of the map
$game_temp.zoom_sprites = @zoom.to_f / 100
$game_temp.zoom_map = (4096 * (1.0 / $game_temp.zoom_sprites)).to_i
# tilesets graphics and data map are loaded if already in Cache
if RPG::Cache_Datamap.in_cache(@id)
@bitmap_data = RPG::Cache_Datamap.load(@id)
@map_tileset = RPG::Cache_Tileset.load(@id)
tilesets_list.push(@map_tileset)
if $game_system.neoM7_animated
@map_tileset_2 = RPG::Cache_Tileset.load(@id, 1)
@map_tileset_3 = RPG::Cache_Tileset.load(@id, 2)
@map_tileset_4 = RPG::Cache_Tileset.load(@id, 3)
tilesets_list.push(@map_tileset_2)
tilesets_list.push(@map_tileset_3)
tilesets_list.push(@map_tileset_4)
end
else # draw the data map and the tileset and save them in the Cache
draw_map
end
# create vertical elements from tiles
data_V = Data_Vertical_Sprites.new(viewport)
# @vertical_sprites : list of vertical sprites (Sprite_V)
@vertical_sprites = data_V.list_sprites_V
# @vertical_sprites_animated : list of animated vertical sprites (Sprite_V)
@vertical_sprites_animated = data_V.list_sprites_V_animated
# angle of rotation (theta)
self.theta = $game_system.neoM7_theta
theta_rad = (Math::PI * theta) / 180
# easier to work with integer value than floats ('>>' and '<<' operations)
$game_temp.cos_theta = (2048 * Math.cos(theta_rad)).to_i
$game_temp.sin_theta = (2048 * Math.sin(theta_rad)).to_i
# offsets : equivalent to display_x and display_y
@offset_x = 0
@offset_y = 0
$game_temp.distance_h = 480 # distance between the center of the map (halfwidth, pivot) and the point of view
# screenline's number of the slant's pivot = y-coordinate of the rotation center
$game_temp.pivot = $game_system.neoM7_pivot # character sprites
$game_temp.pivot_map = $game_temp.pivot /
($game_system.neoM7_resolution == 1 ? 1 :
($game_system.neoM7_resolution == 2 ? 1.33 : 2)) # map sprite
# distance between the center of the map (halfwidth, pivot) and the projection plane surface
$game_temp.distance_p = $game_temp.distance_h - $game_temp.distance_h /
($game_system.neoM7_resolution == 1 ? 1 :
($game_system.neoM7_resolution == 2 ? 1.334 : 2))
# zoom value of the map sprite
@coeff_resolution = ($game_system.neoM7_resolution == 1 ? 1 :
($game_system.neoM7_resolution == 2 ? 1.334 : 2))
# x-offset for the 3 resolutions
@offset_x_res = ($game_system.neoM7_resolution == 1 ? 0 :
($game_system.neoM7_resolution == 2 ? 80 : 160))
# y-offset for the 3 resolutions
@offset_y_res = $game_temp.pivot - $game_temp.pivot_map
@index_animated = 0 # 0..3 : index of animated tiles pattern
# map sprite
self.sprite = Sprite.new(@viewport)
sprite.x = 0
sprite.y = 0
sprite.z = - 99999 # map must not mask vertical elements
self.sprite_screen = Sprite.new(viewport)
sprite_screen.x = 0
sprite_screen.y = 0
sprite_screen.z = - 99999
if $game_system.neoM7_resolution != 1
sprite.bitmap = ($game_system.neoM7_resolution == 2 ?
Bitmap.new(480, 360) : Bitmap.new(320, 240))
else
sprite.bitmap = Bitmap.new(640, 480) # screen dimensions
end
sprite.zoom_x = @coeff_resolution
sprite.zoom_y = @coeff_resolution
if $game_system.neoM7Plus_always_same_res
sprite_screen.bitmap = sprite.bitmap
sprite_screen.zoom_x = @coeff_resolution
sprite_screen.zoom_y = @coeff_resolution
else
sprite_screen.bitmap = Bitmap.new(640, 480)
end
# angle of slant (alpha)
self.alpha = $game_system.neoM7_alpha
refresh_alpha
end
#--------------------------------------------------------------------------
# * Refresh all the parameters dependent on the angle of slant
#--------------------------------------------------------------------------
def refresh_alpha
# angle of slant
alpha_rad = (Math::PI * alpha) / 180
$game_temp.cos_alpha = (2048 * Math.cos(alpha_rad)).to_i
$game_temp.sin_alpha = (2048 * Math.sin(alpha_rad)).to_i
$game_system.neoM7_alpha = alpha
$game_system.neoM7_pivot = $game_temp.pivot
# h0, z0 : intermediate values used to calculate the slope
h0 = (- ($game_temp.distance_h) * $game_temp.pivot *
$game_temp.cos_alpha) / (($game_temp.distance_h << 11) +
$game_temp.pivot * $game_temp.sin_alpha) + $game_temp.pivot
z0 = ($game_temp.distance_h << 11).to_f /
(($game_temp.distance_h << 11) + $game_temp.pivot * $game_temp.sin_alpha)
# slope
$game_temp.slope_value = (1.0 - z0) / ($game_temp.pivot - h0)
$game_temp.slope_value_map = (131072 * $game_temp.slope_value).to_i
$game_temp.corrective_value = 1.0 - $game_temp.pivot * $game_temp.slope_value
$game_temp.corrective_value_map = (131072 * $game_temp.corrective_value / @coeff_resolution).to_i
last_line = - $game_temp.pivot_map - $game_system.neoM7_horizon
old_limit = $game_temp.neoM7_height_limit
$game_temp.neoM7_height_limit = (($game_temp.distance_h - $game_temp.distance_p) *
last_line * $game_temp.cos_alpha) / (($game_temp.distance_h << 11) -
last_line * $game_temp.sin_alpha) + $game_temp.pivot_map
if $game_system.neoM7_white_horizon
@options[1] = $game_temp.neoM7_height_limit > 0 ? 1 : 0
end
$game_temp.neoM7_height_limit = [$game_temp.neoM7_height_limit.to_i, 0].max
$game_temp.height_limit_sprites = $game_temp.neoM7_height_limit * @coeff_resolution
@even = ((old_limit - $game_temp.neoM7_height_limit) & 1 == 0 ? @even : !@even)
# delete lines beyond the new horizon
sprite.bitmap.clean_limit(old_limit,
$game_temp.neoM7_height_limit) if old_limit < $game_temp.neoM7_height_limit
@need_update = true
end
#--------------------------------------------------------------------------
# * Increase (or decrease) the angle of rotation
#--------------------------------------------------------------------------
def increase_theta(value)
self.theta += value
self.theta %= 360
theta_rad = (Math::PI * theta) / 180
$game_temp.cos_theta = (2048 * Math.cos(theta_rad)).to_i
$game_temp.sin_theta = (2048 * Math.sin(theta_rad)).to_i
$game_system.neoM7_theta = theta
@need_update = true
end
#--------------------------------------------------------------------------
# * Set the angle of rotation
#--------------------------------------------------------------------------
def set_theta(value)
self.theta = value % 360
theta_rad = (Math::PI * theta) / 180
$game_temp.cos_theta = (2048 * Math.cos(theta_rad)).to_i
$game_temp.sin_theta = (2048 * Math.sin(theta_rad)).to_i
$game_system.neoM7_theta = theta
@need_update = true
end
#--------------------------------------------------------------------------
# * Increase (or decrease) the zoom level
#--------------------------------------------------------------------------
def increase_zoom(value)
increase_zoom_neoM7Plus_tilemap(value)
@need_update = true
end
#--------------------------------------------------------------------------
# * Set the zoom level
#--------------------------------------------------------------------------
def set_zoom(value)
set_zoom_neoM7Plus_tilemap(value)
@need_update = true
end
#--------------------------------------------------------------------------
# * Update the map sprite and the vertical sprites
#--------------------------------------------------------------------------
def update
@offset_x = $game_map.display_x / 4 + @offset_x_res
@offset_y = $game_map.display_y / 4 + @offset_y_res
if !@need_update && (@offset_x != @offset_x_old || @offset_y != @offset_y_old)
@offset_x_old = @offset_x
@offset_y_old = @offset_y
@need_update = true
end
if @need_update
@need_update_anim = false
sprite_screen.visible = false
sprite.visible = true
# update map sprite
if $game_system.neoM7_filter
@even = !@even
@need_update = @even
@options[2] = @even ? 1 : 2
else
@need_update = false
end
sprite.bitmap.neoM7(@map_tileset, @bitmap_data, @width, @height, @offset_x, @offset_y, @options)
# update vertical sprites
for vertical_sprite in @vertical_sprites
vertical_sprite.update
end
@need_update_screen = true
elsif @need_update_screen || @need_update_anim
sprite_screen.visible = true
sprite.visible = false
@options[2] = 0
sprite_screen.bitmap.clear
if $game_system.neoM7Plus_always_same_res
sprite_screen.bitmap.neoM7(@map_tileset, @bitmap_data, @width, @height, @offset_x, @offset_y, @options)
else
sprite_screen.bitmap.neoM7_screen(@map_tileset, @bitmap_data, @width, @height,
$game_map.display_x / 4, $game_map.display_y / 4, @options)
end
@need_update_screen = false
@need_update_anim = false
end
end
#--------------------------------------------------------------------------
# * Update animation for animated tiles
#--------------------------------------------------------------------------
def update_animated
update_animated_neoM7Plus_tilemap
@need_update_anim = true
end
end
DLL : MGCmode7+.dll
Some scripts :
Working on :