Use PF::Keys instead of LibSDL::Scancode, add fill_rect method

This commit is contained in:
Alex Clink 2022-02-02 00:33:53 -05:00
parent 3db76bcd44
commit c43dfbd90e
8 changed files with 95 additions and 66 deletions

View file

@ -13,7 +13,7 @@ class ThreeDee < PF::Game
@paused = false @paused = false
@speed = 5.0 @speed = 5.0
@text = PF::PixelText.new("./assets/pf-font.png") @text = PF::PixelText.new("./assets/pf-font.png")
@controller : PF::Controller(LibSDL::Scancode) @controller : PF::Controller(PF::Keys)
def initialize(*args, **kwargs) def initialize(*args, **kwargs)
super super
@ -23,16 +23,16 @@ class ThreeDee < PF::Game
@model = PF::Mesh.load_obj("./assets/pixelfaucet.obj") @model = PF::Mesh.load_obj("./assets/pixelfaucet.obj")
@model.position.z = @model.position.z + 2.0 @model.position.z = @model.position.z + 2.0
@controller = PF::Controller(LibSDL::Scancode).new({ @controller = PF::Controller(PF::Keys).new({
LibSDL::Scancode::RIGHT => "Rotate Right", PF::Keys::RIGHT => "Rotate Right",
LibSDL::Scancode::LEFT => "Rotate Left", PF::Keys::LEFT => "Rotate Left",
LibSDL::Scancode::UP => "Up", PF::Keys::UP => "Up",
LibSDL::Scancode::DOWN => "Down", PF::Keys::DOWN => "Down",
LibSDL::Scancode::A => "Left", PF::Keys::A => "Left",
LibSDL::Scancode::D => "Right", PF::Keys::D => "Right",
LibSDL::Scancode::W => "Forward", PF::Keys::W => "Forward",
LibSDL::Scancode::S => "Backward", PF::Keys::S => "Backward",
LibSDL::Scancode::SPACE => "Pause", PF::Keys::SPACE => "Pause",
}) })
end end
@ -48,45 +48,45 @@ class ThreeDee < PF::Game
forward = @camera.forward_vector forward = @camera.forward_vector
strafe = @camera.strafe_vector strafe = @camera.strafe_vector
if @controller.action?("Right") if @controller.held?("Right")
@camera.position = @camera.position + (strafe * @speed * dt) @camera.position = @camera.position + (strafe * @speed * dt)
end end
if @controller.action?("Left") if @controller.held?("Left")
@camera.position = @camera.position - (strafe * @speed * dt) @camera.position = @camera.position - (strafe * @speed * dt)
end end
if @controller.action?("Up") if @controller.held?("Up")
@camera.position.y = @camera.position.y + @speed * dt @camera.position.y = @camera.position.y + @speed * dt
end end
if @controller.action?("Down") if @controller.held?("Down")
@camera.position.y = @camera.position.y - @speed * dt @camera.position.y = @camera.position.y - @speed * dt
end end
# Controll the camera pitch instead of aft - # Controll the camera pitch instead of aft -
# if @controller.action?("Up") # if @controller.held?("Up")
# @camera.pitch = @camera.pitch + (@speed / 2) * dt # @camera.pitch = @camera.pitch + (@speed / 2) * dt
# end # end
# if @controller.action?("Down") # if @controller.held?("Down")
# @camera.pitch = @camera.pitch - (@speed / 2) * dt # @camera.pitch = @camera.pitch - (@speed / 2) * dt
# end # end
if @controller.action?("Rotate Left") if @controller.held?("Rotate Left")
@camera.yaw = @camera.yaw - (@speed / 2) * dt @camera.yaw = @camera.yaw - (@speed / 2) * dt
end end
if @controller.action?("Rotate Right") if @controller.held?("Rotate Right")
@camera.yaw = @camera.yaw + (@speed / 2) * dt @camera.yaw = @camera.yaw + (@speed / 2) * dt
end end
if @controller.action?("Forward") if @controller.held?("Forward")
@camera.position = @camera.position + (forward * @speed * dt) @camera.position = @camera.position + (forward * @speed * dt)
end end
if @controller.action?("Backward") if @controller.held?("Backward")
@camera.position = @camera.position - (forward * @speed * dt) @camera.position = @camera.position - (forward * @speed * dt)
end end

View file

@ -15,11 +15,11 @@ module PF
@noise_zoom = width / 4 @noise_zoom = width / 4
@xpos = 0.0 @xpos = 0.0
@controller = PF::Controller(LibSDL::Scancode).new({ @controller = PF::Controller(Keys).new({
LibSDL::Scancode::UP => "scale up", Keys::UP => "scale up",
LibSDL::Scancode::DOWN => "scale down", Keys::DOWN => "scale down",
LibSDL::Scancode::RIGHT => "zoom up", Keys::RIGHT => "zoom up",
LibSDL::Scancode::LEFT => "zoom down", Keys::LEFT => "zoom down",
}) })
end end

View file

@ -1,14 +1,13 @@
require "../src/game" require "../src/game"
require "../src/lehmer32" require "../src/lehmer32"
require "../src/pixel_text" require "../src/pixel_text"
require "../src/controller"
module PF module PF
class Proceedural < Game class Proceedural < Game
@buffer_size : Int32 @buffer_size : Int32
@buffer : Pointer(UInt32) @buffer : Pointer(UInt32)
@text = PF::PixelText.new("assets/pf-font.png") @text = PixelText.new("assets/pf-font.png")
@pan : PF::Vector2(Float64) = PF::Vector[0.0, 0.0] @pan : Vector2(Float64) = PF::Vector[0.0, 0.0]
@seed : UInt32 @seed : UInt32
def initialize(*args, **kwargs) def initialize(*args, **kwargs)
@ -17,13 +16,13 @@ module PF
@buffer = screen.pixel_pointer(0, 0) @buffer = screen.pixel_pointer(0, 0)
@random = Lehmer32.new @random = Lehmer32.new
@redraw = true @redraw = true
@text.color(PF::Pixel.new(255, 255, 255)) @text.color(Pixel.new(255, 255, 255))
@controller = PF::Controller(LibSDL::Scancode).new({ @controller = Controller(Keys).new({
LibSDL::Scancode::LEFT => "left", Keys::LEFT => "left",
LibSDL::Scancode::RIGHT => "right", Keys::RIGHT => "right",
LibSDL::Scancode::UP => "up", Keys::UP => "up",
LibSDL::Scancode::DOWN => "down", Keys::DOWN => "down",
}) })
@speed = 100.0 @speed = 100.0
@ -36,7 +35,7 @@ module PF
def update(dt, event) def update(dt, event)
@controller.map_event(event) @controller.map_event(event)
@redraw = true if @controller.any_pressed? @redraw = true if @controller.any_held?
@pan.x += @speed * dt if @controller.held?("right") @pan.x += @speed * dt if @controller.held?("right")
@pan.x -= @speed * dt if @controller.held?("left") @pan.x -= @speed * dt if @controller.held?("left")
@pan.y -= @speed * dt if @controller.held?("up") @pan.y -= @speed * dt if @controller.held?("up")

View file

@ -25,7 +25,7 @@ end
class TriangleThing < PF::Game class TriangleThing < PF::Game
@tri : Triangle @tri : Triangle
@paused = false @paused = false
@controller : PF::Controller(LibSDL::Scancode) @controller : PF::Controller(PF::Keys)
def initialize(@width, @height, @scale) def initialize(@width, @height, @scale)
super(@width, @height, @scale) super(@width, @height, @scale)
@ -34,10 +34,10 @@ class TriangleThing < PF::Game
@tri.position = viewport / 2 @tri.position = viewport / 2
@tri.frame = PF::Shape.circle(3, size = @width / 3) @tri.frame = PF::Shape.circle(3, size = @width / 3)
@controller = PF::Controller(LibSDL::Scancode).new({ @controller = PF::Controller(PF::Keys).new({
LibSDL::Scancode::RIGHT => "Rotate Right", PF::Keys::RIGHT => "Rotate Right",
LibSDL::Scancode::LEFT => "Rotate Left", PF::Keys::LEFT => "Rotate Left",
LibSDL::Scancode::SPACE => "Pause", PF::Keys::SPACE => "Pause",
}) })
end end
@ -50,8 +50,8 @@ class TriangleThing < PF::Game
@paused = !@paused if @controller.pressed?("Pause") @paused = !@paused if @controller.pressed?("Pause")
@tri.rotation = @tri.rotation + 0.5 * dt if @controller.action?("Rotate Right") @tri.rotation = @tri.rotation + 0.5 * dt if @controller.held?("Rotate Right")
@tri.rotation = @tri.rotation - 0.5 * dt if @controller.action?("Rotate Left") @tri.rotation = @tri.rotation - 0.5 * dt if @controller.held?("Rotate Left")
unless @paused unless @paused
@tri.rotation = @tri.rotation + 1.0 * dt @tri.rotation = @tri.rotation + 1.0 * dt

View file

@ -1,10 +1,17 @@
require "./lib_sdl" require "./lib_sdl"
module PF module PF
alias Keys = LibSDL::Scancode
# Handle button to action mapping in a dynamic way # Handle button to action mapping in a dynamic way
class Controller(T) class Controller(T)
PRESSED = 0b0000001_u8 @[Flags]
READ = 0b0000010_u8 enum State : UInt8
Unset = 0
Pressed
Released
Read
end
# Detect the current keyboard layout # Detect the current keyboard layout
def self.detect_layout def self.detect_layout
@ -31,10 +38,10 @@ module PF
end end
def initialize(@mapping : Hash(T, String)) def initialize(@mapping : Hash(T, String))
@keysdown = {} of String => UInt8 @keysdown = {} of String => State
@mapping.values.each do |key| @mapping.values.each do |key|
@keysdown[key] = 0 @keysdown[key] = State::Unset
end end
end end
@ -58,36 +65,45 @@ module PF
def press(button) def press(button)
return nil unless registered?(button) return nil unless registered?(button)
@keysdown[@mapping[button]] |= PRESSED return nil if @keysdown[@mapping[button]] & State::Pressed == State::Pressed
@keysdown[@mapping[button]] = State::Pressed
end end
def release(button) def release(button)
return nil unless registered?(button) return nil unless registered?(button)
@keysdown[@mapping[button]] = 0 return nil unless @keysdown[@mapping[button]] & State::Pressed == State::Pressed
@keysdown[@mapping[button]] = State::Released
end end
# =============== # ===============
def any_pressed? def any_held?
@keysdown.any? { |name, state| state & PRESSED > 0 } @keysdown.any? { |name, state| state & State::Pressed == State::Pressed }
end
def none_held?
!any_held?
end end
# Returns true the first time called if a button has been pressed # Returns true the first time called if a button has been pressed
def pressed?(name) def pressed?(name)
return false if @keysdown[name] & READ != 0 return false if @keysdown[name] & State::Read == State::Read
return false unless @keysdown[name] & PRESSED != 0 return false unless @keysdown[name] & State::Pressed == State::Pressed
@keysdown[name] |= READ @keysdown[name] |= State::Read
true true
end end
# Returns true if a registered button is being held # Returns true if a registered button is being held
def held?(name) def held?(name)
@keysdown[name] & PRESSED > 0 @keysdown[name] & State::Pressed == State::Pressed
end end
# ditto # Returns true the first time called after a button has been released
def action?(name) def released?(name)
@keysdown[name] & PRESSED > 0 return false unless @keysdown[name] & State::Released == State::Released
return false if @keysdown[name] & State::Read == State::Read
@keysdown[name] |= State::Read
true
end end
end end
end end

View file

@ -1,22 +1,22 @@
require "./lib_sdl" require "./lib_sdl"
require "./pixel" require "./pixel"
require "./sprite" require "./sprite"
require "./controller"
module PF module PF
abstract class Game abstract class Game
FPS_INTERVAL = 1.0 FPS_INTERVAL = 1.0
SHOW_FPS = true SHOW_FPS = true
property scale : Int32 getter title : String
property title : String
property running = true
property screen : Sprite
getter width : Int32 getter width : Int32
getter height : Int32 getter height : Int32
getter scale : Int32
@viewport : Vector2(Int32)? = nil @viewport : Vector2(Int32)? = nil
property running = true
property screen : Sprite
delegate :draw_point, :draw_line, :scan_line, :draw_circle, :draw_triangle, :draw_rect, :draw_shape, delegate :draw_point, :draw_line, :scan_line, :draw_circle, :draw_triangle, :draw_rect, :draw_shape,
:fill_triangle, :fill_rect, :fill_circle, :fill_shape, to: @screen :fill_triangle, :fill_rect, :fill_circle, :fill_shape, to: @screen
@ -28,7 +28,7 @@ module PF
def initialize(@width, @height, @scale = 1, @title = self.class.name, def initialize(@width, @height, @scale = 1, @title = self.class.name,
flags = SDL::Renderer::Flags::ACCELERATED, flags = SDL::Renderer::Flags::ACCELERATED,
window_flags : SDL::Window::Flags = SDL::Window::Flags::SHOWN) window_flags : SDL::Window::Flags = SDL::Window::Flags::SHOWN)
SDL.init(SDL::Init::VIDEO) SDL.init(SDL::Init::EVERYTHING)
@window = SDL::Window.new(@title, @width * @scale, @height * @scale, flags: window_flags) @window = SDL::Window.new(@title, @width * @scale, @height * @scale, flags: window_flags)
@renderer = SDL::Renderer.new(@window, flags: flags) @renderer = SDL::Renderer.new(@window, flags: flags)
@renderer.scale = {@scale, @scale} @renderer.scale = {@scale, @scale}
@ -38,6 +38,10 @@ module PF
abstract def update(dt : Float64, event : SDL::Event) abstract def update(dt : Float64, event : SDL::Event)
abstract def draw abstract def draw
# To be overridden
def on_exit
end
def width=(value : Int32) def width=(value : Int32)
@viewport = nil @viewport = nil
@width = value @width = value
@ -75,6 +79,7 @@ module PF
break unless @running break unless @running
end end
ensure ensure
on_exit
SDL.quit SDL.quit
end end

View file

@ -22,7 +22,7 @@ module PF
end end
end end
def draw_to(surface : SDL::Surface, text : String, x : Int32 = 0, y : Int32 = 0) def draw_to(surface : SDL::Surface, text : String, x : Int = 0, y : Int = 0)
ix = 0 ix = 0
iy = 0 iy = 0
text.each_char do |char| text.each_char do |char|
@ -59,5 +59,9 @@ module PF
end end
draw_to(sprite.surface, text, x, y) draw_to(sprite.surface, text, x, y)
end end
def draw_to(sprite : Sprite, text : String, pos : Vector2(Int))
draw_to(sprite.surface, text, pos.x, pos.y)
end
end end
end end

View file

@ -12,5 +12,10 @@ module PF
end end
end end
end end
# ditto
def fill_rect(p1 : PF::Vector2(Int), p2 : PF::Vector2(Int), pixel : Pixel = Pixel.new)
fill_rect(p1.x, p1.y, p2.x, p2.y, pixel)
end
end end
end end