Compare commits
3 Commits
65b0a40006
...
f035596255
Author | SHA1 | Date |
---|---|---|
Jill | f035596255 | |
Jill | 560c635694 | |
Jill | d1b5b4d301 |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
|
@ -24,3 +24,7 @@ shards:
|
|||
git: https://github.com/calebuharrison/libstbimage.git
|
||||
version: 0.1.0+git.commit.32bc23af165dbe004a7468426f09e6701463bc72
|
||||
|
||||
sdl:
|
||||
git: https://github.com/ysbaddaden/sdl.cr.git
|
||||
version: 0.1.0+git.commit.a86f867f8c7afbceb8d166ec09185ee14bf0c6d5
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ dependencies:
|
|||
branch: master
|
||||
crystimage:
|
||||
github: calebuharrison/CrystImage
|
||||
sdl:
|
||||
github: ysbaddaden/sdl.cr
|
||||
|
||||
targets:
|
||||
funfriend:
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
class Funfriend::ChatterContext < Funfriend::WindowContext
|
||||
getter renderer : TextRenderer
|
||||
getter parent : WindowContext?
|
||||
property parent_relative_pos : NamedTuple(x: Int32, y: Int32)
|
||||
getter window_size : NamedTuple(width: Int32, height: Int32)
|
||||
property timer : Float64
|
||||
|
||||
WINDOW_SIZE = {width: 256, height: 32}
|
||||
DEFAULT_DURATION = 10.0
|
||||
DEFAULT_DURATION = 6.0
|
||||
|
||||
PADDING = 10
|
||||
|
||||
def initialize(text : String, position : NamedTuple(x: Int32, y: Int32), duration : Float64 = DEFAULT_DURATION)
|
||||
def initialize(text : String, position : NamedTuple(x: Int32, y: Int32), duration : Float64 = DEFAULT_DURATION, parent : WindowContext? = nil)
|
||||
sheet = FontMan.parse_bm(File.read "assets/fonts/SpaceMono.fnt")
|
||||
|
||||
position_data = FontMan.position_text(text, sheet)
|
||||
|
@ -34,6 +36,26 @@ class Funfriend::ChatterContext < Funfriend::WindowContext
|
|||
x: position[:x] - window_size[:width]//2,
|
||||
y: position[:y] - window_size[:height]//2,
|
||||
}
|
||||
|
||||
@parent = parent
|
||||
if parent
|
||||
@parent_relative_pos = {
|
||||
x: position[:x] - (parent.window.position[:x] + parent.window.size[:width] // 2),
|
||||
y: position[:y] - (parent.window.position[:y] + parent.window.size[:height] // 2),
|
||||
}
|
||||
else
|
||||
@parent_relative_pos = {x: 0, y: 0}
|
||||
end
|
||||
end
|
||||
|
||||
def update_position
|
||||
if parent
|
||||
p = parent.not_nil!
|
||||
window.position = {
|
||||
x: p.window.position[:x] + p.window.size[:width] // 2 + parent_relative_pos[:x] - window_size[:width] // 2,
|
||||
y: p.window.position[:y] + p.window.size[:height] // 2 + parent_relative_pos[:y] - window_size[:height] // 2,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def render(dt : Float64)
|
||||
|
@ -52,11 +74,21 @@ class Funfriend::ChatterContext < Funfriend::WindowContext
|
|||
window.should_close
|
||||
end
|
||||
|
||||
update_position
|
||||
|
||||
render(dt)
|
||||
|
||||
window.swap_buffers
|
||||
end
|
||||
|
||||
def bump
|
||||
@parent_relative_pos = {
|
||||
x: parent_relative_pos[:x],
|
||||
y: parent_relative_pos[:y] - window_size[:height] - 10
|
||||
}
|
||||
update_position
|
||||
end
|
||||
|
||||
def clean_up
|
||||
renderer.clean_up
|
||||
end
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
module Funfriend::Ease
|
||||
extend self
|
||||
|
||||
include Math
|
||||
|
||||
def inSine(x)
|
||||
1 - cos(x * (PI * 0.5))
|
||||
end
|
||||
def outSine(x)
|
||||
sin(x * (PI * 0.5))
|
||||
end
|
||||
def inOutSine(x)
|
||||
0.5 - 0.5 * cos(x * PI)
|
||||
end
|
||||
end
|
|
@ -4,9 +4,11 @@ require "crystgl"
|
|||
require "crystimage"
|
||||
|
||||
require "./log.cr"
|
||||
require "./ease.cr"
|
||||
require "./gl.cr"
|
||||
require "./textureman.cr"
|
||||
require "./fontman.cr"
|
||||
require "./soundman.cr"
|
||||
require "./window_context.cr"
|
||||
require "./funfriend_context.cr"
|
||||
require "./funfriend_renderer.cr"
|
||||
|
@ -24,8 +26,6 @@ module Funfriend
|
|||
@@contexts = [] of WindowContext
|
||||
@@main_context : WindowContext?
|
||||
|
||||
@@clean_up_queue = [] of WindowContext
|
||||
|
||||
def self.should_close?
|
||||
@@main_context && @@main_context.not_nil!.window.should_close?
|
||||
end
|
||||
|
@ -33,6 +33,7 @@ module Funfriend
|
|||
def self.init_contexts
|
||||
add_context(FunfriendContext.new)
|
||||
@@main_context = @@contexts[0]
|
||||
at_exit { contexts.each &.destroy }
|
||||
end
|
||||
|
||||
def self.add_context(context : WindowContext)
|
||||
|
@ -46,6 +47,8 @@ module Funfriend
|
|||
def self.run
|
||||
Logging.init
|
||||
|
||||
SoundMan.init
|
||||
|
||||
CrystGLFW.run do
|
||||
init_contexts
|
||||
|
||||
|
@ -57,7 +60,7 @@ module Funfriend
|
|||
@@contexts = @@contexts.select do |context|
|
||||
if context.window.should_close?
|
||||
context.close
|
||||
@@clean_up_queue << context
|
||||
at_exit { context.clean_up }
|
||||
false
|
||||
else
|
||||
context.update(dt)
|
||||
|
@ -67,9 +70,6 @@ module Funfriend
|
|||
|
||||
CrystGLFW.wait_events(1/120)
|
||||
end
|
||||
|
||||
@@contexts.each &.destroy
|
||||
@@clean_up_queue.each &.clean_up
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,33 @@
|
|||
class Funfriend::FunfriendContext < Funfriend::WindowContext
|
||||
getter renderer : FunfriendRenderer
|
||||
property chatter_timer : Float64
|
||||
|
||||
WINDOW_SIZE = {width: 82, height: 82}
|
||||
CHATTER_TIMER = 5.0
|
||||
CHATTER_TIMER = 3.0
|
||||
|
||||
CHATTER_ARRAY = [
|
||||
["HELLO AGAIN"],
|
||||
["HI INTERLOPER"],
|
||||
["HELLO!", "IS THE AUTH LAYER STILL DISSOCIATED?", "I MISS THEM"],
|
||||
["INTERLOPER!", "WELCOME", "BUT ALSO PLEASE DO NOT BOTHER ME", "VERY BUSY"]
|
||||
]
|
||||
|
||||
getter renderer : FunfriendRenderer
|
||||
property chatter_timer : Float64 = 1.0
|
||||
property chatter_index : Int32 = 0
|
||||
property chatter_array : Array(String)? = CHATTER_ARRAY.sample
|
||||
|
||||
property held : Bool = false
|
||||
property held_at : NamedTuple(x: Int32, y: Int32) = {x: 0, y: 0}
|
||||
STAY_STILL_AFTER_HELD = 1.0
|
||||
property held_timer : Float64 = 0.0
|
||||
|
||||
property static_pos : NamedTuple(x: Int32, y: Int32)
|
||||
|
||||
property easing_from : NamedTuple(x: Int32, y: Int32) = {x: 0, y: 0}
|
||||
property easing_to : NamedTuple(x: Int32, y: Int32) = {x: 0, y: 0}
|
||||
property easing_dur : Float64 = 0.0
|
||||
property easing_t : Float64 = 0.0
|
||||
|
||||
WANDER_TIMER = 4.0
|
||||
property wander_timer : Float64 = WANDER_TIMER
|
||||
|
||||
def initialize
|
||||
super(
|
||||
|
@ -12,8 +36,6 @@ class Funfriend::FunfriendContext < Funfriend::WindowContext
|
|||
transparent: true
|
||||
)
|
||||
|
||||
@chatter_timer = 1.0
|
||||
|
||||
# just for initialization, let OpenGL know this is the current context
|
||||
window.make_context_current
|
||||
@renderer = FunfriendRenderer.new
|
||||
|
@ -22,6 +44,21 @@ class Funfriend::FunfriendContext < Funfriend::WindowContext
|
|||
if event.action.press? && event.mouse_button.two?
|
||||
renderer.catmoding = !renderer.catmoding
|
||||
end
|
||||
if event.mouse_button.one?
|
||||
if event.action.press?
|
||||
@easing_dur = 0.0
|
||||
@held = true
|
||||
@held_at = {
|
||||
x: window.cursor.position[:x].to_i,
|
||||
y: window.cursor.position[:y].to_i,
|
||||
}
|
||||
@held_timer = STAY_STILL_AFTER_HELD
|
||||
window.cursor Window::Cursor::Shape::Hand
|
||||
elsif event.action.release?
|
||||
@held = false
|
||||
window.cursor Window::Cursor::Shape::Arrow
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
window.on_key do |event|
|
||||
|
@ -36,6 +73,7 @@ class Funfriend::FunfriendContext < Funfriend::WindowContext
|
|||
x: monitor.position[:x] + (monitor.video_mode.size[:width] * rand((0.0..1.0))).to_i,
|
||||
y: monitor.position[:y] + (monitor.video_mode.size[:height] * rand((0.0..1.0))).to_i
|
||||
}
|
||||
@static_pos = window.position
|
||||
end
|
||||
|
||||
def render(dt : Float64)
|
||||
|
@ -46,27 +84,81 @@ class Funfriend::FunfriendContext < Funfriend::WindowContext
|
|||
renderer.render(dt, WINDOW_SIZE[:width], WINDOW_SIZE[:height])
|
||||
end
|
||||
|
||||
def goto(pos : NamedTuple(x: Int32, y: Int32), dur : Float64)
|
||||
@easing_t = 0.0
|
||||
@easing_dur = dur
|
||||
@easing_from = window.position
|
||||
@easing_to = pos
|
||||
|
||||
LOG.info { "going from #{easing_from} to #{easing_to}" }
|
||||
end
|
||||
|
||||
def update_wander(dt : Float64)
|
||||
if @easing_dur != 0.0 && @easing_t <= @easing_dur
|
||||
@easing_t = @easing_t + dt
|
||||
a = Ease.inOutSine(@easing_t / @easing_dur)
|
||||
|
||||
window.position = {
|
||||
x: (@easing_from[:x] * (1.0 - a) + @easing_to[:x] * a).to_i,
|
||||
y: (@easing_from[:y] * (1.0 - a) + @easing_to[:y] * a).to_i,
|
||||
}
|
||||
|
||||
@wander_timer = WANDER_TIMER
|
||||
else
|
||||
@wander_timer = @wander_timer - dt
|
||||
if @wander_timer <= 0
|
||||
goto({
|
||||
x: @static_pos[:x] + (-40 .. 40).sample,
|
||||
y: @static_pos[:y] + (-40 .. 40).sample,
|
||||
}, 4.0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update_pos(dt : Float64)
|
||||
if held
|
||||
window.position = {
|
||||
x: window.position[:x] - held_at[:x] + window.cursor.position[:x].to_i,
|
||||
y: window.position[:y] - held_at[:y] + window.cursor.position[:y].to_i,
|
||||
}
|
||||
@static_pos = window.position
|
||||
else
|
||||
@held_timer = @held_timer - dt
|
||||
if @held_timer <= 0
|
||||
update_wander(dt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def say(text : String)
|
||||
Funfriend.contexts.each do |context|
|
||||
if context.is_a?(ChatterContext) && context.parent == self
|
||||
context.bump
|
||||
end
|
||||
end
|
||||
|
||||
Funfriend.add_context(ChatterContext.new(text, {
|
||||
x: window.position[:x] + WINDOW_SIZE[:width] // 2,
|
||||
y: window.position[:y] + WINDOW_SIZE[:height] // 2 - 70
|
||||
}, parent: self))
|
||||
|
||||
SoundMan.play_sound("assets/sfx/talk#{(1..8).sample}.ogg")
|
||||
end
|
||||
|
||||
def update(dt : Float64)
|
||||
@chatter_timer = @chatter_timer - dt
|
||||
if @chatter_timer <= 0.0
|
||||
@chatter_timer = @chatter_timer + CHATTER_TIMER
|
||||
|
||||
Funfriend.contexts.each do |context|
|
||||
if context.is_a?(ChatterContext)
|
||||
window = context.window
|
||||
window.position = {
|
||||
x: window.position[:x],
|
||||
y: window.position[:y] - context.window_size[:height] - 10
|
||||
}
|
||||
end
|
||||
if @chatter_array.try &.[(@chatter_index)]?
|
||||
say(@chatter_array.not_nil![@chatter_index])
|
||||
end
|
||||
|
||||
Funfriend.add_context(ChatterContext.new(renderer.catmoding ? "HEWWO INTEWWOPEW" : "HELLO INTERLOPER", {
|
||||
x: window.position[:x] + WINDOW_SIZE[:width] // 2,
|
||||
y: window.position[:y] + WINDOW_SIZE[:height] // 2 - 70
|
||||
}))
|
||||
@chatter_index = @chatter_index + 1
|
||||
end
|
||||
|
||||
update_pos(dt)
|
||||
|
||||
render(dt)
|
||||
|
||||
window.swap_buffers
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
require "sdl"
|
||||
require "sdl/mix"
|
||||
|
||||
module Funfriend::SoundMan
|
||||
extend self
|
||||
|
||||
@@sounds = Hash(String, SDL::Mix::Sample).new
|
||||
|
||||
def play_sound(filepath : String)
|
||||
if !@@sounds.has_key?(filepath)
|
||||
sound = SDL::Mix::Sample.new(filepath)
|
||||
@@sounds[filepath] = sound
|
||||
end
|
||||
|
||||
SDL::Mix::Channel.play(@@sounds[filepath])
|
||||
end
|
||||
|
||||
def init
|
||||
SDL.init(SDL::Init::AUDIO); at_exit { SDL.quit }
|
||||
SDL::Mix.init(SDL::Mix::Init::OGG); at_exit { SDL::Mix.quit }
|
||||
SDL::Mix.open
|
||||
|
||||
SDL::Mix::Channel.volume = SDL::Mix::MAX_VOLUME // 5
|
||||
end
|
||||
end
|