naka-chan-dayo/src/naka/naka.cr

199 lines
4.2 KiB
Crystal
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

require "sdl"
require "sdl/image"
require "sdl/ttf"
## Helper code comes here
class Naka
def self.init
SDL.init SDL::Init::VIDEO
SDL::IMG.init SDL::IMG::Init::PNG
SDL::TTF.init
at_exit {
SDL.quit
SDL::TTF.quit
}
end
end
class Naka::Renderer < SDL::Renderer
end
class Naka::Window
alias Flags = LibSDL::WindowFlags
alias Position = LibSDL::WindowPosition
getter renderer
@current_font : SDL::TTF::Font? = nil
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
@renderer.draw_blend_mode = SDL::BlendMode::BLEND
end
def newImage(file_path) : SDL::Texture
SDL::IMG.load(file_path, @renderer).tap do |texture|
texture.blend_mode = SDL::BlendMode::BLEND
end
end
def newFont(file_path, font_size = 12) : SDL::TTF::Font
SDL::TTF::Font.new file_path, font_size
end
# FIXME: Well probably want options for scaling, rotations, and so on.
def draw(texture : SDL::Texture, x : Int32, y : Int32, scale_x = 1, scale_y = 1)
@renderer.copy texture,
dstrect: SDL::Rect[x, y, (texture.width * scale_x).to_i, (texture.height * scale_y).to_i]
end
def draw(surface : SDL::Surface, x : Int32, y : Int32)
@renderer.copy surface,
dstrect: SDL::Rect[x, y, surface.width, surface.height]
end
def set_font(@current_font)
end
# FIXME:
# - This only prints properly “solid” text. Shaded text (depixelated)
# would need some additional OpenGL manipulations.
# - This is very inefficient resources-wise. If we are willing to drop
# ligatures support (is it even supported in SDL::TTF?), we should
# build a textures atlas of all glyphs and use that to render text.
# - Alternatively, it may be worth it to let users generate a texture of
# some text and draw it, manually.
def print(text, x, y)
font = @current_font
return if font.nil?
surface = font.render_solid(text, SDL::Color[0, 0, 0, 255], @renderer.draw_color)
draw surface, x, y
end
end
class Naka::Timer
getter start
getter last_update
def initialize
@start = Time.local
@last_update = @start
end
def step
now = Time.local
dt = now.to_unix_ms - @last_update.to_unix_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: Split in KeyUp and KeyDown.
class KeyUp
getter key : LibSDL::Keycode
getter scan_code : LibSDL::Scancode
def initialize(@key, @scan_code)
end
end
class KeyDown
getter key : LibSDL::Keycode
getter scan_code : LibSDL::Scancode
getter repeat : Bool
def initialize(@key, @scan_code, @repeat)
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
when SDL::Event::Keyboard
keysym = event.keysym
if event.type == LibSDL::EventType::KEYUP
Naka::Event::KeyUp.new keysym.sym, keysym.scancode
elsif event.type == LibSDL::EventType::KEYDOWN
Naka::Event::KeyDown.new keysym.sym, keysym.scancode, event.repeat != 0
end
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