RMRK is retiring.
Registration is disabled. The site will remain online, but eventually become a read-only archive. More information.

RMRK.net has nothing to do with Blockchains, Cryptocurrency or NFTs. We have been around since the early 2000s, but there is a new group using the RMRK name that deals with those things. We have nothing to do with them.
NFTs are a scam, and if somebody is trying to persuade you to buy or invest in crypto/blockchain/NFT content, please turn them down and save your money. See this video for more information.
Shake Window [1.5]

0 Members and 1 Guest are viewing this topic.

*
Rep:
Level 82
GIAW 14: 1st Place (Easy Mode)2013 Most Promising Project2013 Best RPG Maker User (Programming)2013 Project of the YearParticipant - GIAW 11Bronze - GIAW 10
Shake Window
Version: 1.5
Author: Exhydra
Date: 6-14-2011

Version History


  • <Version 1.5> 06.20.2011 - Cleaned up code; Changed WinAPIs slightly.
  • <Version 1.4> 06.14.2011 - Cleaned code a little.
  • <Version 1.2> 06.14.2011 - [FIX] Determines if the game is full screen and runs a normal screen shake instead.
  • <Version 1.1> 06.14.2011 - [FIX] Maintained the game window position through rapid calls.
  • <Version 1.0> 06.13.2011 - Original Release

Description


Shaking the screen not enough to emphasize something that happened in game? Want the metor you just dropped on the players to rock more than the pixels inside of the game? Shake Window will allow you to kindly jiggle or ruthlessly rattle the game window in custom directions as well as allow you to shake the screen while you're at it.

Features

  • Shake the game window with variable speed, power and direction.
  • Shake the screen along with the game window.
  • Bypasses the speed and power limitation of the Shake Screen command within the Event Editor.

Screenshots

None

Instructions

See Script Header

Script


Code: [Select]
#===============================================================================
# Shake Window
#===============================================================================
# Author       : Exhydra
# Version      : 1.5
# Last Updated : 06/20/2011
#===============================================================================
# Updates
# -----------------------------------------------------------------------------
# » 06/20/11 Cleaned up code; Changed WinAPIs slightly.
# » 06/14/11 [FIX] Maintained the game window position through rapid calls
#            [FIX] Determines if the game is full screen and runs a normal
#                  screen shake instead.
# » 06/13/11 Initial Release.
#===============================================================================
# Future Options
# -----------------------------------------------------------------------------
# » Nothing! Suggestions?
#===============================================================================
# Instructions
# -----------------------------------------------------------------------------
# To Use :
#   Call : (from a Script Event command)
#     gms = $game_map.screen
#     gms.shake_window(power, speed, duration[, route, ds_option])
#
#     'route' Values
#      7 8 9
#      4  (6) - Default; Right then Left (Valid for Window Shake ONLY)
#      1 2 3
#
#     'ds_option' Values
#       (0)   - Default; Shake Window Only
#        1    - Shake Window and Screen
#        2    - Shake Screen Only
#   
#   Examples :
#     gms = $game_map.screen
#     gms.shake_window(5, 5, 15)
#
#     gms = $game_map.screen
#     gms.shake_window(8, 8, 60, 9, 1)
#===============================================================================
# Description
# -----------------------------------------------------------------------------
# - Shakes the window of the game, or shakes the window and the screen or just
#   shakes the screen. This script allows the user to go beyond the limitations
#   of the Shake Screen command within the Event Editor. However, that is just
#   a by-product and can be easily done without including this script.
#===============================================================================

#===============================================================================
# [NOTE:] -
#===============================================================================

#===============================================================================
# -? Game_Screen
# -----------------------------------------------------------------------------
# Summary of Changes:
#    New Method(s)     - shake_window
#    Aliased Method(s) - clear, update_shake
#===============================================================================

class Game_Screen
  #--------------------------------------------------------------------------
  # » Clear                                                         [ Alias ]
  #--------------------------------------------------------------------------
  alias ex_shakewindow_clear clear unless $@
  def clear
    @sw_power = 0
    @sw_speed = 0
    @sw_duration = 0
    @sw_direction = 0
    @sw_shake = 0
    @sw_hwnd = 0
    @sw_szEval = ""
    @sw_rect = []
   
    ex_shakewindow_clear
  end
 
  #--------------------------------------------------------------------------
  # » Shake Window                                                    [ New ]
  #     power        : Shake Intensity
  #     speed        : Shake Speed
  #     duration     : Shake Duration (60 = 1 sec)
  #    [route]       : Direction Window will Shake Towards
  #     7 8 9
  #     4 ?(6) - Default; Right then Left (Valid for Window Shake ONLY)
  #     1 2 3
  #    [ds_option]   : 'Double Shake' Option
  #      (0)   - Default; Window Shake Only
  #       1    - Window and Screen Shake
  #       2    - Screen Shake Only
  #--------------------------------------------------------------------------
  def shake_window(power, speed, duration, route = 6, ds_option = 0)
    return if @sw_shake != 0
    ds_option      = 2 if Ex_WinAPI.CheckFullScreen == true
   
    case ds_option
      when 1
        start_shake(power, speed, duration)
      when 2
        start_shake(power, speed, duration)
        return
    end
   
    case route
      when 1
        @sw_direction = 1
        @szEval = "@sw_rect[0] + (-@sw_shake), @sw_rect[1] + (@sw_shake)"
      when 2
        @sw_direction = 1
        @szEval = "@sw_rect[0], @sw_rect[1] + (@sw_shake)"
      when 3
        @sw_direction = 1
        @szEval = "@sw_rect[0] + (@sw_shake), @sw_rect[1] + (@sw_shake)"
      when 4
        @sw_direction = -1
        @szEval = "@sw_rect[0] + (@sw_shake), @sw_rect[1]"
      when 6
        @sw_direction = 1
        @szEval = "@sw_rect[0] + (@sw_shake), @sw_rect[1]"
      when 7
        @sw_direction = -1
        @szEval = "@sw_rect[0] + (@sw_shake), @sw_rect[1] + (@sw_shake)"
      when 8
        @sw_direction = -1
        @szEval = "@sw_rect[0], @sw_rect[1] + (@sw_shake)"
      when 9
        @sw_direction = -1
        @szEval = "@sw_rect[0] + (-@sw_shake), @sw_rect[1] + (@sw_shake)"
      else
        @sw_direction = 1
        @szEval = "@sw_rect[0] + (@sw_shake), @sw_rect[1]"
    end
     
    @sw_power = power
    @sw_speed = speed
    @sw_duration = duration
    @sw_hwnd = Ex_WinAPI.AcquireGameWindow
    @sw_rect = Ex_WinAPI.AcquireGameWindowRect
  end

  #--------------------------------------------------------------------------
  # » Update Shake                                                  [ Alias ]
  #--------------------------------------------------------------------------
  alias ex_shakewindow_update_shake update_shake unless $@
  def update_shake
    if @sw_duration >= 1 or @sw_shake != 0
      sw_delta = (@sw_power * @sw_speed * @sw_direction) / 10.0
      if @sw_duration <= 1 and @sw_shake * (@sw_shake + sw_delta) < 0
        @sw_shake = 0
      else
        @sw_shake += sw_delta
      end
      if @sw_shake > @sw_power * 2
        @sw_direction = -1
      end
      if @sw_shake < - @sw_power * 2
        @sw_direction = 1
      end
      if @sw_duration >= 1
        @sw_duration -= 1
      end
     
      if Ex_WinAPI.CheckFullScreen != true
        eval("Ex_WinAPI.SetWindowPosition(@sw_hwnd, " + @szEval + ",
              @sw_rect[2] - @sw_rect[0], @sw_rect[3] - @sw_rect[1])")
      end
     
    end
   
    ex_shakewindow_update_shake
  end
end


class Ex_WinAPI
  #--------------------------------------------------------------------------
  # » Windows API Declarations                                [ Windows API ]
  #--------------------------------------------------------------------------
  @@getCurrentThreadId       = Win32API.new('kernel32' ,'GetCurrentThreadId'      , ['']                                , 'L')
  @@getWindowLong            = Win32API.new('user32'   ,'GetWindowLongA'          , ['L', 'I']                          , 'L')
  @@getWindowRect            = Win32API.new('user32'   ,'GetWindowRect'           , ['L', 'P']                          , 'L')
  @@getWindowThreadProcessId = Win32API.new('user32'   ,'GetWindowThreadProcessId', ['L', 'P']                          , 'L')
  @@getClientRect            = Win32API.new('user32'   ,'GetClientRect'           , ['L', 'P']                          , 'L')
  @@setWindowPosition        = Win32API.new('user32'   ,'SetWindowPos'            , ['L', 'L', 'I', 'I', 'I', 'I', 'I'] , 'I')
  @@findWindowEx             = Win32API.new('user32'   ,'FindWindowEx'            , ['L', 'L', 'P', 'P']                , 'L')

  #--------------------------------------------------------------------------
  # » Constants
  #--------------------------------------------------------------------------
  @@gwl_STYLE                = -16
 
  @@ws_MINIMIZEBOX           = 0x20000
  @@ws_DLGFRAME              = 0x00400000
  @@ws_BORDER                = 0x00800000
  @@ws_SYSMENU               = 0x00080000
  @@ws_CLIPSIBLINGS          = 0x04000000
  @@ws_VISIBLE               = 0x10000000

  @@ws_RGSS_NORM             = @@ws_SYSMENU | @@ws_CLIPSIBLINGS | @@ws_VISIBLE |
                               @@ws_BORDER  | @@ws_DLGFRAME     | @@ws_MINIMIZEBOX
 
  #--------------------------------------------------------------------------
  # » Variables
  #--------------------------------------------------------------------------
  @@gameHwnd                 = nil
 
  #--------------------------------------------------------------------------
  # » Acquire Game Window                                     [ Windows API ]
  #--------------------------------------------------------------------------
  def self.AcquireGameWindow
    return @@gameHwnd if @@gameHwnd
    procID     = [0].pack('L')
    threadID   = @@getCurrentThreadId.call
    gameTitle = ($data_system.nil?) ? 0 : $data_system.game_title
    @@gameHwnd = 0

    begin
      @@gameHwnd = @@findWindowEx.call(0, @@gameHwnd, "RGSS Player", gameTitle)

      if @@gameHwnd
        wndThreadID = @@getWindowThreadProcessId.call(@@gameHwnd, procID)
       
        return @@gameHwnd unless wndThreadID != threadID; gameTitle = 0
      end
    end until @@gameHwnd == 0

    raise "ERROR : RGSS player window not found!"
    return 0
  end

  #--------------------------------------------------------------------------
  # » Acquire Game Window Long                                [ Windows API ]
  #--------------------------------------------------------------------------
  def self.AcquireGameWindowLong
    wHwnd   = self.AcquireGameWindow
   
    return @@getWindowLong.call(wHwnd, @@gwl_STYLE)
  end
 
  #--------------------------------------------------------------------------
  # » Acquire Game Window Rect                                [ Windows API ]
  #--------------------------------------------------------------------------
  def self.AcquireGameWindowRect
    aRect      = [0,0,0,0].pack('L4')
    wHwnd      = self.AcquireGameWindow
   
    @@getWindowRect.call(wHwnd, aRect)
    l, t, r, b = aRect.unpack('L4')
    return l, t, r, b
  end
 
  #--------------------------------------------------------------------------
  # » Acquire Client Screen Rect                              [ Windows API ]
  #--------------------------------------------------------------------------
  def self.AcquireClientScreenRect
    aScreen    = [0,0,0,0].pack('L4')
    wHwnd      = self.AcquireGameWindow
   
    @@getClientRect.call(wHwnd, aScreen)
    l, t, r ,b = aScreen.unpack('L4')
    return l, t, r, b
  end

  #--------------------------------------------------------------------------
  # » Check Full Screen                                       [ Windows API ]
  #--------------------------------------------------------------------------
  def self.CheckFullScreen
    aRect        = self.AcquireGameWindowRect
    aScreen      = self.AcquireClientScreenRect
    lCurrScreen  = self.AcquireGameWindowLong

    if aRect[0] <= aScreen[0] and
       aRect[1] <= aScreen[1] and
       aRect[2] >= aScreen[2] and
       aRect[3] >= aScreen[3] or
       lCurrScreen | @@ws_RGSS_NORM != @@ws_RGSS_NORM
      return true
    else
      return false
    end
  end
 
  #--------------------------------------------------------------------------
  # » Set Window Position                                     [ Windows API ]
  #     window_hWnd  : Window HWND
  #     window_x     : Window Screen X (Top Left)
  #     window_y     : Window Screen Y (Top Left)
  #     window_w     : Window Width
  #     window_h     : Window Height
  #--------------------------------------------------------------------------
  def self.SetWindowPosition(window_hWnd, window_x, window_y, window_w, window_h)
    return @@setWindowPosition.call(window_hWnd, 0, window_x, window_y, window_w, window_h, 0)
  end

end

Credit


  • Exhydra

Thanks

  • <Numerous Script Authors; Windows API> (GetPrivateProfileString, Find Window, AquireGameWindow)

Support


  • Please post in this thread for support.

Known Compatibility Issues

  • Unsure (hopefully none)

Demo


None

Author's Notes


  • First consolidated script! It still feels a little bulky and I'm looking at different ways to streamline the way I did things. Any help with optimization is appreciated.

Restrictions

  • Free for use in non-commercial and commercial games.
« Last Edit: June 23, 2011, 01:10:48 AM by Exhydra »

UPDATED 05-29-14


IS YOUR PROJECT OPTIMIZED?
UPDATED 07/04/15 - v2.5

RPG MAKER TOOLBOX
UPDATED 07/04/15 - v1.5

*****
my name is Timothy what's yours
Rep:
Level 79
Hello
2014 Most Missed Member2014 Zero to Hero2014 Best IRC Quote2012 Zero To HeroSecret Santa 2012 ParticipantContestant - GIAW 9For frequently finding and reporting spam and spam bots2011 Zero to Hero
Looks great Exhyrda, a nice script to enter the scripting scene proper. ;)
For your issues regarding the window falling off the screen, if you have a conditional in an update method or something similar to check if window.y < 0 or window.y > 544 (off the top of my head, I can't remember the proper dimensions XD) you can just have a method run to keep the window on the screen. I'll give it a shot later tonight.
For your full screen thingamy, you could use a similar way of finding that out: there are API's required to make the game window fullscreen, but I can't remember any of them... yeah. I'll get back to you later on about that.
Looks cool, welcome to the world of scripting (MA's the boss). I look forward to more works.
it's like a metaphor or something i don't know

********
Rep:
Level 96
2011 Most Missed Member2010 Zero To Hero
Very cool script, bro.

*****
my name is Timothy what's yours
Rep:
Level 79
Hello
2014 Most Missed Member2014 Zero to Hero2014 Best IRC Quote2012 Zero To HeroSecret Santa 2012 ParticipantContestant - GIAW 9For frequently finding and reporting spam and spam bots2011 Zero to Hero
Okay, I think I found that Win32API thing I was talking about. From an old full-screen I wrote yonks ago, I found that to activate fullscreen I used the following call.
Code: [Select]
    $keybd = Win32API.new ('user32.dll', 'keybd_event', ['i', 'i', 'l', 'l'], 'v')
    $keybd.call 0xA4, 0, 0, 0
    $keybd.call 13, 0, 0, 0
    $keybd.call 13, 0, 2, 0
    $keybd.call 0xA4, 0, 2, 0
So in a conditional to test if the window is in fullscreen, see if you can't use this.
Code: [Select]
if $keybd == Win32API.new ('user32.dll', 'keybd_event', ['i', 'i', 'l', 'l'], 'v')
I think that should work, I'll give it a shot when I'm on a computer with VX.
EDIT:: Dang, doesn't work. I'll look into it more.
« Last Edit: June 14, 2011, 12:12:44 PM by Pacman »
it's like a metaphor or something i don't know

*****
Rep:
Level 84
This text is way too personal.
Bronze - GIAW 11 (Hard)Silver - GIAW Halloween
Not the most elegant solution, but you can run a check for Ex_WinAPI.AcquireGameWindow to see if it's [0, 0, 640, 480], which is always the value that RPG Maker VX uses for its fullscreen option.

Otherwise, really neat script!

*
Rep:
Level 82
GIAW 14: 1st Place (Easy Mode)2013 Most Promising Project2013 Best RPG Maker User (Programming)2013 Project of the YearParticipant - GIAW 11Bronze - GIAW 10
Hmm, stopping the screen slide was easier than I thought. I just made sure that @sw_shake was always zero before the script could be started again ('return if @sw_shake != 0') and that seems to work fine. I shoved version 1.1 into a parallel process and it didn't budge after an extended period of time. I also cleaned up some of the @szEval code and made it smaller, although I still think there must be an easier way to do what I did.

However, checking for full screen is still a bit of a problem. I don't think it would be reliable to check for a certain screen size, as people may alter theirs with resolution modifying scripts. What I'm probably going to have to do is check the game window size versus the monitor window size, and if they overlap then the game is full screen. I've been scouring for an easy solution within the RPGVX data structures, looking for a flag that declares that full screen is enabled, but it doesn't look like there is one. You'd think that there would be ... ah well.

Thanks for the feedback so far! 

EDIT : Here's a work-around script, but it feels kind of dirty how I'm determining full screen. Basically comparing GetWindowLong information beside each other instead of checking for a specific window style. I updated the code in the original post.

EDIT II : Here is the code that I tried using before, and it seems to me that it would be better for me to narrow down which window styles (WS_STYLE) are being changed rather than just comparing one GetWindowLong number against the other. I commented in where I was running into problems. All of the available window styles are listed here :

Normal Window Styles : http://msdn.microsoft.com/en-us/library/ms632600%28v=vs.85%29.aspx
Extended Window Styles : http://msdn.microsoft.com/en-us/library/ff700543(v=vs.85).aspx

Code: [Select]
class Ex_FSCheck
  # Changing GWL_EXSTYLE to -20 enables checking for extended window styles
  @GWL_STYLE = -16

  @WS_CAPTION = 0x00C00000
  @WS_VISIBLE = 0x10000000
  @WS_DISABLED = 0x08000000
  @WS_MAXIMIZEBOX = 0x10000
  @WS_MINIMIZEBOX = 0x20000
  @WS_POPUP = 0x80000000

  @WS_EX_MDICHILD = 0x00000040
  @WS_EX_COMPOSITED = 0x02000000
 
  def self.AcquireGameWindowLong(nIndex = @GWL_STYLE)
    get_long = Win32API.new('user32.dll', 'GetWindowLongA', ['L', 'I'], 'l')
    window_hwnd = self.AcquireGameWindow
    wnd_tmp = get_long.call(window_hwnd, nIndex)

    # Is this how I would check these two against each other?
    # This -always- returns true. Even if I use @WS_DISABLED, and I know the window certainly isn't disabled.
    if wnd_tmp && @WS_POPUP == @WS_POPUP
      return true
    else
      return false
    end
  end

  def self.AcquireGameWindow
    window_title = GetPrivateProfileString("Game", "Title", "", "./Game.ini")
    return FindWindow("RGSS Player", window_title)
  end
 
  def self.FindWindow(window_class, window_title)
    find_window = Win32API.new('user32.dll', 'FindWindowA', ['P', 'P'], 'l')
    return find_window.call(window_class, window_title)
  end
 
  def self.GetPrivateProfileString(ini_section, ini_key, default_val, ini_file)
    get_string = Win32API.new('kernel32.dll', 'GetPrivateProfileStringA', ['P', 'P', 'P', 'P', 'L', 'P'], 'l')
    sz_buffer = "\0" * (256 + 1)
    get_string.call(ini_section, ini_key, default_val, sz_buffer, 256, ini_file)
    return sz_buffer.delete!("\0")
  end
end


EDIT III : I found another way to check for full screen, but I feel that it's also a bit flimsy. Well, either way I have lined out works fine, but I'm sure that there are better ways of going about doing it ...

EDIT IV : Alright, narrowed it down a little further. Close enough, I think.

Code: [Select]
class Ex_FSCheck
#===============================================================================
# Full Screen Check
#===============================================================================
# Author       : Exhydra
# Version      : 1.5
# Last Updated : 07/14/2011
#===============================================================================
  #--------------------------------------------------------------------------
  # ? Windows API Declarations                                [ Windows API ]
  #--------------------------------------------------------------------------
  @getCurrentThreadId       = Win32API.new('kernel32', 'GetCurrentThreadId'      , ['']                  , 'L')
  @getWindowRect            = Win32API.new('user32',   'GetWindowRect'           , ['L', 'P']            , 'L')
  @getWindowThreadProcessId = Win32API.new('user32',   'GetWindowThreadProcessId', ['L', 'P']            , 'L')
  @getClientRect            = Win32API.new('user32',   'GetClientRect'           , ['L', 'P']            , 'L')
  @findWindowEx             = Win32API.new('user32',   'FindWindowEx'            , ['L', 'L', 'P', 'P']  , 'L')

  #--------------------------------------------------------------------------
  # ? Acquire Game Window                                     [ Windows API ]
  #--------------------------------------------------------------------------
  def self.AcquireGameWindow
    procID     = [0].pack('L')
    threadID   = @getCurrentThreadId.call
    nextWindow = 0
   
    begin
      nextWindow = @findWindowEx.call(0, nextWindow, "RGSS Player", 0)
     
      if nextWindow
        wndThreadID = @getWindowThreadProcessId.call(nextWindow, procID)
       
        if wndThreadID == threadID
          return nextWindow
        end
      end
    end until nextWindow == 0
   
    raise "ERROR : RGSS player window not found!"
    return 0
  end

  #--------------------------------------------------------------------------
  # ? Acquire Game Window Rect                                [ Windows API ]
  #--------------------------------------------------------------------------
  def self.AcquireGameWindowRect
    aRect      = [0,0,0,0].pack('L4')
    wHwnd      = self.AcquireGameWindow
   
    @getWindowRect.call(wHwnd, aRect)
    l, t, r, b = aRect.unpack('L4')
    return l, t, r, b
  end
 
  #--------------------------------------------------------------------------
  # ? Acquire Client Screen Rect                              [ Windows API ]
  #--------------------------------------------------------------------------
  def self.AcquireClientScreenRect
    aScreen    = [0,0,0,0].pack('L4')
    wHwnd      = self.AcquireGameWindow
   
    @getClientRect.call(wHwnd, aScreen)
    l, t, r ,b = aScreen.unpack('L4')
    return l, t, r, b
  end

  #--------------------------------------------------------------------------
  # ? Check Full Screen                                       [ Windows API ]
  #--------------------------------------------------------------------------
  def self.CheckFullScreen
    aRect         = self.AcquireGameWindowRect
    aScreen       = self.AcquireClientScreenRect
   
    if aRect[0] <= aScreen[0] and
       aRect[1] <= aScreen[1] and
       aRect[2] >= aScreen[2] and
       aRect[3] >= aScreen[3]
      return true
    else
      return false
    end
  end
 
end
« Last Edit: June 15, 2011, 03:51:19 AM by Exhydra »

UPDATED 05-29-14


IS YOUR PROJECT OPTIMIZED?
UPDATED 07/04/15 - v2.5

RPG MAKER TOOLBOX
UPDATED 07/04/15 - v1.5