require "sdl" require "sdl/image" ## Helper code comes here class Naka def self.init SDL.init SDL::Init::VIDEO SDL::IMG.init SDL::IMG::Init::PNG at_exit { SDL.quit } end end class Naka::Renderer < SDL::Renderer end class Naka::Window alias Flags = LibSDL::WindowFlags alias Position = LibSDL::WindowPosition getter renderer def initialize(title, width, height, x : Position = Position::UNDEFINED, y : Position = Position::UNDEFINED, flags : Flags = Flags::SHOWN) @window = SDL::Window.new(title, width, height, x, y, flags) @renderer = Naka::Renderer.new @window end def newImage(file_path) : SDL::Texture SDL::IMG.load file_path, @renderer end # FIXME: We’ll probably want options for scaling, rotations, and so on. def draw(texture : SDL::Texture, x : Int32, y : Int32) @renderer.copy texture, dstrect: SDL::Rect[x, y, texture.width, texture.height] end end class Naka::Timer getter start getter last_update def initialize @start = Time.now @last_update = @start end def step now = Time.now dt = now.epoch_ms - @last_update.epoch_ms @last_update = now dt end end class Naka::Event class Quit end class Draw getter window : Naka::Window def initialize(@window) end end class Update getter dt : Int64 def initialize(@dt) end end # FIXME: THIS MAIN LOOP IS **NOT** READY FOR PRODUCTION # Update events are still missing, and both Draw and Update should # be time-based. # Why having a `window` parameter instead of making a Window#loop method? # Because we may want to have a `windows` parameter in the future, although # unlikely. But still possible. def self.loop(window, &block) max_fps = 60 max_dt = 1000. / 60 timer = Naka::Timer.new renderer = window.renderer ::loop do exit_requested = false while event = SDL::Event.poll r_value = yield case event when SDL::Event::Quit Naka::Event::Quit.new else # FIXME: Most event types may need proper Naka:: classes. event end if r_value == Naka::Event::Quit exit_requested = true break end end break if exit_requested dt = timer.step r_value = yield Naka::Event::Update.new dt break if r_value == Naka::Event::Quit renderer.draw_color = SDL::Color[255, 255, 255, 255] renderer.clear yield Naka::Event::Draw.new window renderer.present sleep 0.001 end end end ## Actual application code comes here Naka.init window = Naka::Window.new "Test", 640, 480 naka = window.newImage "naka.png" Naka::Event.loop window do |event| case event when Naka::Event::Quit next Naka::Event::Quit when Naka::Event::Update p "Update(#{event.dt})" when Naka::Event::Draw p "Draw" event.window.draw naka, 20, 20 end end