Class: RichEngine::Game

Inherits:
Object
  • Object
show all
Defined in:
lib/rich_engine/game.rb

Overview

The base class for all games. Subclass it, implement the lifecycle hooks, and draw to @canvas each frame; the game loop, input, rendering, and frame pacing are handled for you.

The lifecycle hooks are the core public API:

Examples:

A minimal game that draws a title and quits on "q"

class MyGame < RichEngine::Game
  def on_create
    @title = "My Awesome Game"
  end

  def on_update(elapsed_time, key)
    quit! if key == :q

    @canvas.write_string(@title, x: 1, y: 1)
  end
end

MyGame.play

Defined Under Namespace

Classes: Exit

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(width, height, target_fps: 60) ⇒ Game

Returns a new instance of Game.

Parameters:

  • width (Integer)

    the screen width in characters

  • height (Integer)

    the screen height in characters

  • target_fps (Integer, nil) (defaults to: 60)

    target frames per second; pass nil to run uncapped without frame pacing



41
42
43
44
45
46
47
48
49
# File 'lib/rich_engine/game.rb', line 41

def initialize(width, height, target_fps: 60)
  @width = width
  @height = height
  @target_fps = target_fps
  @frame_budget = @target_fps ? 1.0 / @target_fps : nil
  @config = {screen_width: @width, screen_height: @height}
  @io = RichEngine::IO.new(width, height)
  @canvas = RichEngine::Canvas.new(width, height)
end

Class Method Details

.play(width: 50, height: 10, target_fps: 60) ⇒ void

This method returns an undefined value.

Builds a game and runs it. The convenient entry point for starting a game.

Parameters:

  • width (Integer) (defaults to: 50)

    the screen width in characters

  • height (Integer) (defaults to: 10)

    the screen height in characters

  • target_fps (Integer, nil) (defaults to: 60)

    target frames per second; pass nil to run uncapped without frame pacing



59
60
61
# File 'lib/rich_engine/game.rb', line 59

def self.play(width: 50, height: 10, target_fps: 60)
  new(width, height, target_fps: target_fps).play
end

Instance Method Details

#game_loop(elapsed_time) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Runs a single frame: reads input, calls #on_update, renders, and sleeps to honor the target FPS.

Parameters:

  • elapsed_time (Float)

    seconds elapsed since the last frame



127
128
129
130
131
132
# File 'lib/rich_engine/game.rb', line 127

def game_loop(elapsed_time)
  key = read_input
  on_update(elapsed_time, key)
  render
  sleep_if_needed(elapsed_time)
end

#on_createvoid

This method returns an undefined value.

Lifecycle hook called once before the game loop starts. Override it to set up initial state (instance variables, timers, canvas slots, etc.).



93
94
# File 'lib/rich_engine/game.rb', line 93

def on_create
end

#on_destroyvoid

This method returns an undefined value.

Lifecycle hook called once after the game loop ends. Override it to tear down state or print a final message.



110
111
# File 'lib/rich_engine/game.rb', line 110

def on_destroy
end

#on_update(_elapsed_time, _key) ⇒ void

This method returns an undefined value.

Lifecycle hook called once per frame. Override it to update game state and draw to @canvas.

Parameters:

  • _elapsed_time (Float)

    seconds elapsed since the last frame

  • _key (Symbol, nil)

    the last key pressed (e.g. :q, :up, :space, :esc), or nil if no key was pressed this frame



103
104
# File 'lib/rich_engine/game.rb', line 103

def on_update(_elapsed_time, _key)
end

#playvoid

This method returns an undefined value.

Runs the game: prepares the terminal, calls #on_create, then loops calling #on_update and rendering every frame until the game exits, finally calling #on_destroy and restoring the terminal.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/rich_engine/game.rb', line 68

def play
  prepare_screen
  on_create

  previous_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)

  loop do
    current_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    elapsed_time = current_time - previous_time
    previous_time = current_time

    check_game_exit do
      game_loop(elapsed_time)
    end
  end

  on_destroy
ensure
  restore_screen
end

#quit!void

This method returns an undefined value.

Exits the game loop, triggering #on_destroy and terminal restore.

Raises:

  • (Exit)

    always, to unwind out of the loop



117
118
119
# File 'lib/rich_engine/game.rb', line 117

def quit!
  raise Exit
end