Window

January 14, 2026 ยท View on GitHub

GMR provides window management and timing control through the GMR::Window and GMR::Time modules. Configure window size, fullscreen mode, VSync, virtual resolution, and frame timing.

Window Configuration

Setting Window Size

# Set window dimensions
Window.set_size(1280, 720)

# Set window title
Window.set_title("My Game")

Window size changes take effect immediately on native platforms. On web, the canvas size is controlled by HTML/CSS.

Querying Dimensions

# Logical dimensions (what your code sees)
width = Window.width     # UI-scaled width
height = Window.height   # UI-scaled height (always 360 baseline)

# Actual screen dimensions in pixels
screen_w = Window.screen_width
screen_h = Window.screen_height

# Actual window dimensions (ignoring virtual resolution)
actual_w = Window.actual_width
actual_h = Window.actual_height

Fullscreen Mode

# Toggle fullscreen
Window.toggle_fullscreen

# Set fullscreen explicitly
Window.fullscreen = true
Window.fullscreen = false

# Check current state
if Window.fullscreen?
  puts "Running in fullscreen"
end

On native platforms, fullscreen uses the monitor's native resolution. On web, fullscreen requests the browser's fullscreen API.

VSync (Vertical Synchronization)

VSync synchronizes frame presentation with the display's refresh rate to eliminate screen tearing. When enabled, the GPU waits for the monitor's vertical blank interval before presenting each frame.

Enabling/Disabling VSync

# Enable VSync (default)
Window.vsync = true

# Disable VSync for lower latency
Window.vsync = false

# Alternative setter
Window.set_vsync(true)

# Query current state
if Window.vsync?
  puts "VSync is enabled"
end

VSync Behavior

VSync StateFrame PacingTearingLatency
Enabled (default)Locked to refresh rateNoneHigher
DisabledUnlimited or target FPSPossibleLower

When VSync is enabled:

  • Frames are presented at the monitor's refresh rate (typically 60Hz)
  • No screen tearing occurs
  • Input latency may be slightly higher
  • Target FPS is automatically set to 0 (unlimited) to avoid double-throttling

When VSync is disabled:

  • Frames are presented as soon as they're ready
  • Screen tearing may occur during fast motion
  • Input latency is minimized
  • Target FPS defaults to 60 as a software limiter

Platform Notes

PlatformVSync Mechanism
WindowsWGL swap interval
LinuxGLX swap interval
macOSCGL swap interval
WebBrowser-controlled via requestAnimationFrame

On web builds, VSync is handled automatically by the browser's requestAnimationFrame and cannot be disabled.

Frame Timing

The GMR::Time module provides frame timing information and control.

Delta Time

def update(dt)
  # dt is the time since last frame in seconds
  # Typically 0.016 at 60 FPS
  @player.x += @speed * dt  # Frame-rate independent movement
end

Delta time is also accessible via:

Time.delta  # Same as the dt parameter

Elapsed Time

# Total time since game started
Time.elapsed  # Returns seconds as float

# Example: Flash effect every 0.5 seconds
visible = (Time.elapsed % 1.0) < 0.5

Frame Rate

# Get current FPS
fps = Time.fps

# Set target frame rate
Time.set_target_fps(60)   # Limit to 60 FPS
Time.set_target_fps(144)  # Limit to 144 FPS
Time.set_target_fps(0)    # Unlimited (VSync controls pacing)

Note: When VSync is enabled, the display refresh rate takes precedence over the target FPS. Setting a target FPS below the refresh rate will still cap the frame rate, but setting it higher has no effect.

Time Scale

Control the speed of game time for slow-motion, pause, or fast-forward effects:

# Normal speed
Time.scale = 1.0

# Slow motion (half speed)
Time.scale = 0.5

# Pause
Time.scale = 0.0

# Fast forward (double speed)
Time.scale = 2.0

# Query current scale
current_scale = Time.scale

Timers created with scaled: true (the default) respect time scale. Physics and animations that use dt should also be affected.

Virtual Resolution

Render to a fixed-size buffer and scale to fit the window. Ideal for pixel-art games that need crisp integer scaling.

Enabling Virtual Resolution

def init
  Window.set_size(960, 540)
  Window.set_virtual_resolution(320, 180)  # Render at 320x180
  Window.set_filter_point  # Crisp pixel scaling (nearest neighbor)
end

Texture Filtering

MethodResultUse Case
Window.set_filter_pointCrisp, pixelatedPixel art, retro games
Window.set_filter_bilinearSmooth, blurredHD graphics, photos

Querying Virtual Resolution

# Check if virtual resolution is enabled
if Window.virtual_resolution?
  puts "Rendering to virtual buffer"
end

Clearing Virtual Resolution

# Return to native resolution
Window.clear_virtual_resolution

Complete Virtual Resolution Example

include GMR

def init
  # 960x540 window, rendering at 320x180 (3x integer scale)
  Window.set_size(960, 540)
  Window.set_virtual_resolution(320, 180)
  Window.set_filter_point

  @camera = Camera2D.new
  @camera.view_height = 9
  @camera.viewport_size = Vec2.new(320, 180)  # Must match virtual res!
  @camera.offset = Vec2.new(160, 90)
end

def draw
  @camera.use do
    Graphics.clear(:black)
    # ... draw game at 320x180
  end
end

Important: When using virtual resolution with a camera, set viewport_size to match the virtual resolution, not the window size.

Device Pixel Ratio (Web)

On high-DPI displays (Retina, 4K monitors), web browsers use a device pixel ratio greater than 1.0. GMR can render at the native device resolution or the CSS resolution.

# Render at native device pixel ratio (sharper on Retina)
Window.use_native_dpr

# Render at CSS resolution (default, better performance)
Window.use_css_dpr

# Query current device pixel ratio
dpr = Window.device_pixel_ratio  # 1.0, 2.0, etc.

# Check if native DPR rendering is enabled
if Window.native_dpr?
  puts "Rendering at native resolution"
end
MethodResolution on 2x RetinaPerformance
use_css_dpr (default)1280x720Better
use_native_dpr2560x1440Lower

Monitor Information

Query connected monitors for multi-monitor setups or resolution selection:

# Number of monitors
count = Window.monitor_count

# Monitor properties (0-indexed)
width = Window.monitor_width(0)
height = Window.monitor_height(0)
refresh_rate = Window.monitor_refresh_rate(0)  # Hz
name = Window.monitor_name(0)

# Example: List all monitors
Window.monitor_count.times do |i|
  puts "Monitor #{i}: #{Window.monitor_name(i)}"
  puts "  Resolution: #{Window.monitor_width(i)}x#{Window.monitor_height(i)}"
  puts "  Refresh: #{Window.monitor_refresh_rate(i)}Hz"
end

Window Resize Handling

GMR calls on_resize when the window size changes:

def on_resize(width, height)
  # Update camera viewport
  @camera.viewport_size = Vec2.new(width, height)
  @camera.offset = Vec2.new(width / 2, height / 2)
end

This is called automatically when:

  • The user resizes the window
  • Fullscreen is toggled
  • The browser window changes size (web)

Note: on_resize is not called before init. Initialize your camera in init using Window.width and Window.height.

Complete Example

include GMR

def init
  Window.set_title("Window Demo")
  Window.set_size(1280, 720)

  # Enable VSync for smooth rendering
  Window.vsync = true

  # Setup camera
  @camera = Camera2D.new
  @camera.view_height = 9
  @camera.viewport_size = Vec2.new(Window.width, Window.height)
  @camera.offset = Vec2.new(Window.width / 2, Window.height / 2)

  input do |i|
    i.toggle_fullscreen :f11
    i.toggle_vsync :v
  end
end

def on_resize(width, height)
  @camera.viewport_size = Vec2.new(width, height)
  @camera.offset = Vec2.new(width / 2, height / 2)
end

def update(dt)
  if Input.action_pressed?(:toggle_fullscreen)
    Window.toggle_fullscreen
  end

  if Input.action_pressed?(:toggle_vsync)
    Window.vsync = !Window.vsync?
  end
end

def draw
  @camera.use do
    Graphics.clear(:dark_gray)
    # ... draw game
  end

  # UI overlay
  Graphics.draw_text("FPS: #{Time.fps}", 10, 10, 16, :white)
  Graphics.draw_text("VSync: #{Window.vsync? ? 'ON' : 'OFF'}", 10, 30, 16, :white)
  Graphics.draw_text("Press F11 for fullscreen, V to toggle VSync", 10, 50, 16, :gray)
end

Quick Reference

GMR::Window

MethodDescription
set_size(w, h)Set window dimensions
set_title(title)Set window title
widthLogical width (UI-scaled)
heightLogical height (360 baseline)
screen_widthActual screen width in pixels
screen_heightActual screen height in pixels
toggle_fullscreenToggle fullscreen mode
fullscreen=Set fullscreen mode
fullscreen?Check if fullscreen
vsync=Enable/disable VSync
vsync?Check if VSync is enabled
set_vsync(enabled)Enable/disable VSync
set_virtual_resolution(w, h)Enable virtual resolution
clear_virtual_resolutionDisable virtual resolution
virtual_resolution?Check if virtual resolution is enabled
set_filter_pointNearest-neighbor filtering
set_filter_bilinearBilinear filtering
monitor_countNumber of connected monitors
monitor_width(i)Monitor width in pixels
monitor_height(i)Monitor height in pixels
monitor_refresh_rate(i)Monitor refresh rate in Hz
monitor_name(i)Monitor name string

GMR::Time

MethodDescription
deltaTime since last frame (seconds)
elapsedTotal time since start (seconds)
fpsCurrent frames per second
set_target_fps(fps)Set target frame rate (0 = unlimited)
scaleGet current time scale
scale=Set time scale (0 = pause, 1 = normal)

See Also

  • Camera - World-space rendering and resolution modes
  • Graphics - Drawing and rendering
  • Engine Model - Frame execution order
  • Input - Keyboard, mouse, gamepad input