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 }
#2
This pure magic. Thanks :)
Valdred
Tech Administrator of Save-Point
Reply }
#3
(11-23-2010, 07:53 PM)Valdred Wrote: This pure magic. Thanks :)

It was already posted, but on the temporary forum...
That was the only script of my contribution that was missing here, I think.
Some scripts :
Working on :
Reply }
#4
Hello,

I don't know if you know about mkxp (https://github.com/Ancurio/mkxp), it's an open-source C implementation of the RGSS engine. It's supposed to replace the Game.exe and RGSSXXXX.dll files. It's more powerful and faster than the original RGSS Player, and it's cross-platform (with it you can play RMXP games on Mac and Linux).

The thing is that mkxp doesn't have Win32API for obvious reasons, and so this script cannot work using it. It would be great if you could make a version of Neo Mode 7 working with it, could you give it a try ?

Thanks !
Reply }
#5
His last posting was 2010 for this system and has not been around for roughly a year. Meanwhile, without support for use of outside DLLs, MKXP will not be able to use his custom graphic dll.
Up is down, left is right and sideways is straight ahead. - Cord "Circle of Iron", 1978 (written by Bruce Lee and James Coburn... really...)

[Image: QrnbKlx.jpg]
[Image: sGz1ErF.png]    [Image: liM4ikn.png]    [Image: fdzKgZA.png]    [Image: sj0H81z.png]
[Image: QL7oRau.png]    [Image: uSqjY09.png]    [Image: GAA3qE9.png]    [Image: 2Hmnx1G.png]    [Image: BwtNdKw.png%5B]
  Above are clickable links
Reply }
#6
(02-04-2015, 04:13 AM)DerVVulfman Wrote: His last posting was 2010 for this system and has not been around for roughly a year. Meanwhile, without support for use of outside DLLs, MKXP will not be able to use his custom graphic dll.
I can't send him a PM nor an email, so I tried to post it there ^^

If the functions that are currently in the DLL and needed by the scripts are built in mkxp (so in the engine) we should be able to call them without referencing the DLL, and it would be cross-platform aswell... that's why I asked MCG if he could rewrite his DLL directly into the source of mkxp (or a fork).
Reply }
#7
or if he could create a Non-DLL version of his script, would be nicer, not just for mkxp, but maybe for Regal and other nonRM editors.

But to be honest, all I want is a pure PC 3d version of RMXP, no heightmaps, actual models, or at the least , come on! let's get an RPG maker 4 up here... Surely we can run Plasystation 2 Graphics!
[Image: yy7iKKb.png]

ITCH: jayray.itch.io
Currently working on Goblin Gulch (MV)
Currently working on JayVinci Resurrection
Currently working on Bakin ABS (BAKIN)
Reply }
#8
We surely could, but it would take time to do and would cost more than $20 :D
Reply }
#9
It's called Unity.
Reply }
#10
Unity is, on my opinion, very bad and hard to master... but yeah, basically it's that :p
Reply }


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



Users browsing this thread: 2 Guest(s)