Neo Mode 7 +
#1
RMXP : Add-on for the Neo Mode 7 Engine : Neo Mode 7 +
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 :
Reply }


Messages In This Thread
Neo Mode 7 + - by MGC - 11-23-2010, 07:46 PM
RE: [RMXP] Neo Mode 7 + - by deValdr - 11-23-2010, 07:53 PM
RE: [RMXP] Neo Mode 7 + - by MGC - 11-23-2010, 07:58 PM
RE: Neo Mode 7 + - by natinusala - 02-03-2015, 10:59 AM
RE: Neo Mode 7 + - by DerVVulfman - 02-04-2015, 04:13 AM
RE: Neo Mode 7 + - by natinusala - 02-04-2015, 09:31 AM
RE: Neo Mode 7 + - by JayRay - 02-04-2015, 11:26 PM
RE: Neo Mode 7 + - by natinusala - 02-05-2015, 08:47 PM
RE: Neo Mode 7 + - by MetalRenard - 02-05-2015, 08:57 PM
RE: Neo Mode 7 + - by natinusala - 02-06-2015, 01:34 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
   Neo Mode 7 Script by MGCaladtogel MGC 59 125,167 09-29-2017, 03:48 AM
Last Post: DerVVulfman
   Penguinboyroy's Boss Mode Script Segment penguinboyroy 1 6,716 06-23-2010, 05:40 PM
Last Post: penguinboyroy



Users browsing this thread: 1 Guest(s)