How to make VX Ace less framerate dependant?

Discussion in 'RGSSx Script Support' started by DaOwl, Jan 9, 2019.

  1. DaOwl

    DaOwl Warper Member

    Messages:
    4
    Likes Received:
    3
    First Language:
    FRENCH
    Primarily Uses:
    RMVXA
    Hello!
    Glad to be here.

    I currently work on VX Ace and something is really tearing me down with it.
    When I use a script call Graphics.frame_rate = 120, all the game speeds up by 2. And vice-versa when I set it to 30, etc.

    I would be glad to know how to make VX Ace less "Framerate dependant". Namely, that the game only gains fluidity when I set Graphics.frame_rate to 120, and feels laggy when I set it to 30.

    I also started to think about that and tried to write a lil script that is available here:
    https://www.dropbox.com/sh/f440k9tw6pfcyli/AACRP80nB7_4h1abf6jLpllva?dl=0

    Code:
    module BoubouEngine
      module_function
      def frame
      (Graphics.frame_rate/60.0).round(2)
      end
    end
    
    # Fix Parallax moves
    
    class Game_Map
      def update_parallax
        @parallax_x += (@parallax_sx / 64.0) / BoubouEngine::frame if @parallax_loop_x
        @parallax_y += (@parallax_sy / 64.0) / BoubouEngine::frame if @parallax_loop_y
      end
    end
    
    # Fix fade and weather effects
    
    class Game_Screen
      def start_fadeout(duration)
        @fadeout_duration = duration * BoubouEngine::frame
        @fadein_duration = 0
      end
     
      def start_fadein(duration)
        @fadein_duration = duration * BoubouEngine::frame
        @fadeout_duration = 0
      end
    
      def start_tone_change(tone, duration)
        @tone_target = tone.clone
        @tone_duration = duration * BoubouEngine::frame
        @tone = @tone_target.clone if @tone_duration == 0
      end
     
      def start_shake(power, speed, duration)
        @shake_power = power
        @shake_speed = speed
        @shake_duration = duration * BoubouEngine::frame
      end
    
      def change_weather(type, power, duration)
        @weather_type = type if type != :none || duration == 0
        @weather_power_target = type == :none ? 0.0 : power.to_f
        @weather_duration = duration * BoubouEngine::frame
        @weather_power = @weather_power_target if duration == 0
      end
     
    end
    
    # Fix characters move
    
    class Game_CharacterBase
      def distance_per_frame
        (2 ** real_move_speed / 256.0) / BoubouEngine::frame
      end
     
      def update_animation
        update_anime_count
        if @anime_count > (18 - real_move_speed * 2) * BoubouEngine::frame
          update_anime_pattern
          @anime_count = 0
        end
      end
    
    end
    
    # Fix some Battle animations
    
    class Sprite_Battler
      def start_effect(effect_type)
        @effect_type = effect_type
        case @effect_type
        when :appear
          @effect_duration = 16 * BoubouEngine::frame
          @battler_visible = true
        when :disappear
          @effect_duration = 32 * BoubouEngine::frame
          @battler_visible = false
        when :whiten
          @effect_duration = 16 * BoubouEngine::frame
          @battler_visible = true
        when :blink
          @effect_duration = 20 * BoubouEngine::frame
          @battler_visible = true
        when :collapse
          @effect_duration = 48 * BoubouEngine::frame
          @battler_visible = false
        when :boss_collapse
          @effect_duration = bitmap.height * BoubouEngine::frame
          @battler_visible = false
        when :instant_collapse
          @effect_duration = 16 * BoubouEngine::frame
          @battler_visible = false
        end
        revert_to_normal
      end
    end
    
    # Fix some things about Windows
    
    class Window_Base < Window
      def update
        super
        update_tone
        update_open if @opening
        update_close if @closing
      end
     
      def update_open
        self.openness += 48 / BoubouEngine::frame
        @opening = false if open?
      end
     
      def update_close
        self.openness -= 48 / BoubouEngine::frame
        @closing = false if close?
      end
     
      def draw_text_ex(x, y, text)
        reset_font_settings
        text = convert_escape_characters(text)
        pos = {:x => x, :y => y, :new_x => x, :height => calc_line_height(text)}
     
        # ---
     
        if Graphics.frame_rate < 60
          g = ( 1 / ( BoubouEngine::frame ) ).to_i
          process_character(text.slice!(0, g), text, pos) until text.empty?
        else
          process_character(text.slice!(0, 1), text, pos) until text.empty?
        end
      end
     
      def process_character(c, text, pos)
    
        # ---
     
        f  ||= 0
        p  ||= BoubouEngine::frame
     
        if Graphics.frame_rate >= 60
          while f < p
            Fiber.yield unless SceneManager.scene_is?(Scene_Battle)
            f    += 1
          end
          f = 0
        end
     
        case c
        when "\n"   # New line
          process_new_line(text, pos)
        when "\f"   # New page
          process_new_page(text, pos)
        when "\e"   # Control character
          process_escape_character(obtain_escape_code(text), text, pos)
        else        # Normal character
          process_normal_character(c, pos)
        end
      end
     
    end
    

    But during this little script session, I found that some animations, fade effects and such were coded in the built-in modules and classes, so they aren't easy to patch...

    Among other, I can list:
    - The cursor blink effect in all the Window_Selectable instances. [OK]
    - The Message's "Pause" icon animation (the little arrow at the bottom of the window_message) [OK]
    - The Scene_Menu fadeIn and fadeOut effects.
    - Battle Animations
    - Transitions (nah, it's okay. There is an argument "duration" for Graphics.transition)

    My "priorities" would be:
    - The cursor blink effect [OK]
    - The Message's Pause Graphic animation [OK]
    - The Battle Animations [ No Idea :/ ]
    - (Eventually) the Transitions [ No Idea :/ ] [it's OK]

    Does anyone know how to patch those elements of this listing to make them less "framerate dependant", as I started to do in my script for characters' moves and so on?


    I'm looking forward to reading your responses,
    Regards.
     
    Last edited: Jan 11, 2019
    #1
    Tw0Face likes this.
  2. mlogan

    mlogan Global Moderators Global Mod

    Messages:
    13,794
    Likes Received:
    7,616
    Location:
    Texas
    First Language:
    English
    Primarily Uses:
    RMMV

    I've moved this thread to Script Support. Please be sure to post your threads in the correct forum next time. Thank you.

     
    #2
  3. gstv87

    gstv87 Veteran Veteran

    Messages:
    1,767
    Likes Received:
    798
    First Language:
    Spanish
    Primarily Uses:
    RMVXA
    by default, the engine is *mostly always* *simply refreshing everything*.
    "simply refreshing everything" being one issue, and "mostly always" being another.

    the only way to make it less refresh-intensive, is to go into the code, and turn each window into collections of sub-objects rather than collections of texts and shapes that need to be refreshed every time.
    as in, you don't need to redraw the whole window every time the cursor is moved, you just need to pick up which item the cursor is selecting, clear (if possible) *the cursor* from it, or (if not possible) *the item itself*, alone, redraw the one item, and redraw the cursor, not the whole list on top of which the cursor is being drawn.
    that would take care of the "refreshing everything" part, and tuning it so that it happens only after a significant change on the window other than simply blinking the cursor, would take care of the "mostly always".
    the code *can* do that...... it's just, it wasn't coded that way.

    but that requires a big overhaul, of the whole code, and that might cause it to conflict with 3rd party plugins, which are often based on this, faulty, not-optimal code.
     
    #3
    DaOwl likes this.
  4. DaOwl

    DaOwl Warper Member

    Messages:
    4
    Likes Received:
    3
    First Language:
    FRENCH
    Primarily Uses:
    RMVXA
    Yeh, thank you!

    Indeed, it is possible to clear the cursor, and then hard-code a new one.
    I'll check it out...

    I know right, and I weighed the pros and cons. :/
     
    #4
  5. astracat111

    astracat111 Astra Cat Veteran

    Messages:
    205
    Likes Received:
    111
    Location:
    New York City
    First Language:
    English
    From using both VX Ace and MV, I think I remember enjoy MV due to it having a better frame rate, but then it would have performance issues (although it's been 3 years so maybe they fixed it with the updates by now).
     
    #5
  6. Poryg

    Poryg Dark Lord of the Castle of Javascreeps Veteran

    Messages:
    3,922
    Likes Received:
    9,905
    Location:
    Czech Republic
    First Language:
    Czech
    Primarily Uses:
    RMMV
    @astracat111 No, it's still as crap as it was before optimisation-wise. And it's not going to change to ensure compatibility with 3rd party plugins.
     
    #6
  7. gstv87

    gstv87 Veteran Veteran

    Messages:
    1,767
    Likes Received:
    798
    First Language:
    Spanish
    Primarily Uses:
    RMVXA
    @DaOwl I don't want to blatantly self-advertise here, but you could try my Window Replacement plugin.
    I tweaked it a bit to increase performance, but it's still largely untested.
    it *should* help with basic Window-related problems, and you could potentially design a window skin that would be as lightweight as conceivably possible..... but you'd have to make your own plugins, based on that, for battle scenes and animations.

    since I wrote a brand-new Window object, you could tap on that to help you tweak the other windows, but .....
    ¯\_(ツ)_/¯
    *untested*
     
    #7
    DaOwl likes this.
  8. DaOwl

    DaOwl Warper Member

    Messages:
    4
    Likes Received:
    3
    First Language:
    FRENCH
    Primarily Uses:
    RMVXA
    @gstv87
    dude, this is crazy!

    just wrote a lil patch below your script... ~

    Code:
    class Window < Object
      def update
        if self.active
          refreshCursor
          @animationCount += (1.0/BoubouEngine::frame)
        end
        updateTransform
      end
    end
    I'm not a really good programmer but it should be OK, I guess...


    EDIT:

    You're a gentleman. :3
     
    Last edited: Jan 10, 2019
    #8
  9. gstv87

    gstv87 Veteran Veteran

    Messages:
    1,767
    Likes Received:
    798
    First Language:
    Spanish
    Primarily Uses:
    RMVXA
    ah yes.... the self.update call..... heh....
    *thought bubble with the gallons of coffee and tea I drank fixing it*

    yeh.... heheh....
     
    #9
    DaOwl likes this.

Share This Page