482
main.odin
Normal file
482
main.odin
Normal file
@@ -0,0 +1,482 @@
|
||||
package main
|
||||
|
||||
import "core:fmt"
|
||||
import "core:math"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
SFX: []u8 : #load("sfx.mp3")
|
||||
OTF: []u8 : #load("a.otf")
|
||||
|
||||
clampf :: proc(v: f32, lo: f32, hi: f32) -> f32 {
|
||||
if v < lo do return lo
|
||||
if v > hi do return hi
|
||||
return v
|
||||
}
|
||||
|
||||
lerp :: proc(a, b, t: f32) -> f32 {
|
||||
return a + (b - a) * clampf(t, 0, 1)
|
||||
}
|
||||
|
||||
color_mul_rgb :: proc(a, b: rl.Color) -> rl.Color {
|
||||
return {
|
||||
u8((f32(a.r) * f32(b.r)) / 255),
|
||||
u8((f32(a.g) * f32(b.g)) / 255),
|
||||
u8((f32(a.b) * f32(b.b)) / 255),
|
||||
255,
|
||||
}
|
||||
}
|
||||
|
||||
with_alpha :: proc(c: rl.Color, alpha: f32) -> rl.Color {
|
||||
out := c
|
||||
out.a = u8(clampf(alpha, 0, 1) * 255)
|
||||
return out
|
||||
}
|
||||
|
||||
// easings
|
||||
ease_out_cubic :: proc(t: f32) -> f32 {
|
||||
t1 := clampf(t, 0, 1)
|
||||
return 1 - (1 - t1) * (1 - t1) * (1 - t1)
|
||||
}
|
||||
ease_in_out_cubic :: proc(t: f32) -> f32 {
|
||||
t1 := clampf(t, 0, 1)
|
||||
if t1 < 0.5 {
|
||||
return 4 * t1 * t1 * t1
|
||||
}
|
||||
u := 2 * t1 - 2
|
||||
return 0.5 * u * u * u + 1
|
||||
}
|
||||
ease_out_back :: proc(t: f32, s: f32 = 1.70158) -> f32 {
|
||||
t1 := clampf(t, 0, 1)
|
||||
return 1 + s * math.pow(t1 - 1, 3) + s * (t1 - 1) * math.pow(t1 - 1, 2)
|
||||
}
|
||||
|
||||
adsr :: proc(t, attack, decay, sustain: f32, r_start: f32, r_dur: f32) -> f32 {
|
||||
if t <= 0 {return 0}
|
||||
if t < attack {
|
||||
return ease_out_cubic(t / attack)
|
||||
}
|
||||
if t < attack + decay {
|
||||
return lerp(1, sustain, ease_in_out_cubic((t - attack) / decay))
|
||||
}
|
||||
if t < r_start {
|
||||
return sustain
|
||||
}
|
||||
return sustain * (1 - ease_out_cubic((t - r_start) / math.max(r_dur, 0.0001)))
|
||||
}
|
||||
|
||||
draw_noun_verbed_sheen :: proc(
|
||||
font: rl.Font,
|
||||
text: string,
|
||||
center: rl.Vector2,
|
||||
base_font_size: f32,
|
||||
spacing: f32,
|
||||
text_color: rl.Color,
|
||||
text_opacity: f32,
|
||||
sheen_tint: rl.Color,
|
||||
blur_size_: f32,
|
||||
blur_opacity: f32,
|
||||
) {
|
||||
blur_size := blur_size_
|
||||
screen_h := rl.GetScreenHeight()
|
||||
s := f32(screen_h) / 1080.0
|
||||
|
||||
if blur_size <= 1.0001 {
|
||||
blur_size = 1.0001
|
||||
}
|
||||
|
||||
steps_f := 20.0 * blur_size * math.pow(s, 0.25)
|
||||
zoomSteps := i32(math.floor(steps_f))
|
||||
if zoomSteps < 6 {
|
||||
zoomSteps = 6
|
||||
}
|
||||
|
||||
voff := s / (blur_size - 1.0)
|
||||
|
||||
base_size := rl.MeasureTextEx(font, fmt.ctprintf("{}", text), base_font_size, spacing)
|
||||
base_origin := rl.Vector2{base_size.x * 0.5, base_size.y * 0.5}
|
||||
|
||||
glow_base := color_mul_rgb(text_color, sheen_tint)
|
||||
|
||||
rl.BeginBlendMode(.ADDITIVE)
|
||||
for i := zoomSteps; i >= 0; i -= 1 {
|
||||
t := f32(i) / f32(zoomSteps)
|
||||
scale_factor := f32(math.pow(blur_size, t))
|
||||
|
||||
denom := f32(math.log2_f32(blur_size) / math.log2_f32(2))
|
||||
if denom == 0 {
|
||||
denom = 0.000001
|
||||
}
|
||||
fat_product := f32(math.pow(scale_factor, 1.0 / denom))
|
||||
|
||||
alpha := blur_opacity / fat_product
|
||||
if alpha <= 0.001 {
|
||||
continue
|
||||
}
|
||||
|
||||
fs := base_font_size * scale_factor
|
||||
sp := spacing * scale_factor
|
||||
|
||||
size := rl.MeasureTextEx(font, fmt.ctprintf("{}", text), fs, sp)
|
||||
origin := rl.Vector2{size.x * 0.5, size.y * 0.5}
|
||||
|
||||
y_offset := voff * (scale_factor - 1.0)
|
||||
|
||||
rl.DrawTextPro(
|
||||
font,
|
||||
fmt.ctprintf("{}", text),
|
||||
rl.Vector2{center.x, center.y + y_offset},
|
||||
origin,
|
||||
0.0,
|
||||
fs,
|
||||
sp,
|
||||
with_alpha(glow_base, alpha),
|
||||
)
|
||||
}
|
||||
rl.EndBlendMode()
|
||||
|
||||
rl.DrawTextPro(
|
||||
font,
|
||||
fmt.ctprintf("{}", text),
|
||||
center,
|
||||
base_origin,
|
||||
0.0,
|
||||
base_font_size,
|
||||
spacing,
|
||||
with_alpha(text_color, text_opacity),
|
||||
)
|
||||
}
|
||||
|
||||
draw_shadow_bar :: proc(
|
||||
center_y: f32,
|
||||
rel_size: f32,
|
||||
opacity: f32,
|
||||
offset: f32,
|
||||
softness: f32,
|
||||
tint: rl.Color,
|
||||
) {
|
||||
if rel_size <= 0.0 || opacity <= 0.0 {
|
||||
return
|
||||
}
|
||||
|
||||
w := rl.GetScreenWidth()
|
||||
hf := f32(rl.GetScreenHeight())
|
||||
|
||||
shadow_h := rel_size * 0.25 * hf
|
||||
center := center_y + offset * hf
|
||||
top := center - shadow_h * 0.5
|
||||
|
||||
c_tint := rl.Color{tint.r, tint.g, tint.b, u8(clampf(opacity, 0, 1) * 255)}
|
||||
c_clear := rl.Color{tint.r, tint.g, tint.b, 0}
|
||||
|
||||
y0 := i32(math.round(top))
|
||||
total_h := i32(math.round(shadow_h))
|
||||
if total_h <= 0 {
|
||||
return
|
||||
}
|
||||
y3 := y0 + total_h
|
||||
|
||||
fade_h := shadow_h * clampf(softness, 0, 1) * 0.5
|
||||
fade_i := i32(math.round(fade_h))
|
||||
if fade_i * 2 > total_h {
|
||||
fade_i = total_h / 2
|
||||
}
|
||||
|
||||
y1 := y0 + fade_i
|
||||
y2 := y3 - fade_i
|
||||
mid_h := y2 - y1
|
||||
|
||||
rl.BeginBlendMode(.ALPHA)
|
||||
|
||||
if fade_i > 0 {
|
||||
rl.DrawRectangleGradientV(0, y0, w, y1 - y0, c_clear, c_tint)
|
||||
}
|
||||
|
||||
if mid_h > 0 {
|
||||
rl.DrawRectangle(0, y1, w, mid_h, c_tint)
|
||||
}
|
||||
|
||||
if fade_i > 0 {
|
||||
rl.DrawRectangleGradientV(0, y2, w, y3 - y2, c_tint, c_clear)
|
||||
}
|
||||
|
||||
rl.EndBlendMode()
|
||||
}
|
||||
|
||||
draw_sheen_sweep :: proc(
|
||||
font: rl.Font,
|
||||
text: string,
|
||||
center: rl.Vector2,
|
||||
font_size: f32,
|
||||
spacing: f32,
|
||||
tint: rl.Color,
|
||||
progress: f32,
|
||||
core_frac: f32,
|
||||
soft_frac: f32,
|
||||
core_alpha: f32,
|
||||
soft_alpha: f32,
|
||||
) {
|
||||
size := rl.MeasureTextEx(font, fmt.ctprintf("{}", text), font_size, spacing)
|
||||
origin := rl.Vector2{size.x * 0.5, size.y * 0.5}
|
||||
|
||||
left := center.x - origin.x
|
||||
top := center.y - origin.y
|
||||
width := size.x
|
||||
height := size.y
|
||||
|
||||
p := clampf(progress, 0, 1)
|
||||
|
||||
x_center := left + width * p
|
||||
core_w := width * core_frac
|
||||
soft_w := width * soft_frac
|
||||
|
||||
bright := rl.Color{255, 235, 210, 255}
|
||||
|
||||
rl.BeginBlendMode(.ADDITIVE)
|
||||
|
||||
rl.BeginScissorMode(i32(x_center - soft_w * 0.5), i32(top), i32(soft_w), i32(height))
|
||||
rl.DrawTextPro(
|
||||
font,
|
||||
fmt.ctprintf("{}", text),
|
||||
center,
|
||||
origin,
|
||||
0,
|
||||
font_size,
|
||||
spacing,
|
||||
with_alpha(bright, soft_alpha),
|
||||
)
|
||||
rl.EndScissorMode()
|
||||
|
||||
rl.BeginScissorMode(i32(x_center - core_w * 0.5), i32(top), i32(core_w), i32(height))
|
||||
rl.DrawTextPro(
|
||||
font,
|
||||
fmt.ctprintf("{}", text),
|
||||
center,
|
||||
origin,
|
||||
0,
|
||||
font_size,
|
||||
spacing,
|
||||
with_alpha(bright, core_alpha),
|
||||
)
|
||||
rl.EndScissorMode()
|
||||
|
||||
rl.EndBlendMode()
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
mon := rl.GetCurrentMonitor()
|
||||
w, h := rl.GetMonitorWidth(mon), rl.GetMonitorHeight(mon)
|
||||
|
||||
rl.SetConfigFlags(
|
||||
{
|
||||
.WINDOW_TRANSPARENT,
|
||||
.WINDOW_RESIZABLE,
|
||||
.WINDOW_MOUSE_PASSTHROUGH,
|
||||
.WINDOW_HIGHDPI,
|
||||
.WINDOW_TOPMOST,
|
||||
.WINDOW_UNFOCUSED,
|
||||
.WINDOW_UNDECORATED,
|
||||
.FULLSCREEN_MODE,
|
||||
},
|
||||
)
|
||||
rl.InitWindow(w, h, "amongus")
|
||||
|
||||
rl.InitAudioDevice()
|
||||
music := rl.LoadMusicStreamFromMemory(".mp3", raw_data(SFX), i32(len(SFX)))
|
||||
rl.PlayMusicStream(music)
|
||||
|
||||
rt := rl.LoadRenderTexture(rl.GetScreenWidth(), rl.GetScreenHeight())
|
||||
rl.SetTextureFilter(rt.texture, .BILINEAR)
|
||||
|
||||
font := rl.LoadFontFromMemory(".otf", raw_data(OTF), i32(len(OTF)), 64, nil, 0)
|
||||
|
||||
text := "NIXOS REBUILT"
|
||||
base_font_size0 := f32(128)
|
||||
spacing := f32(2)
|
||||
text_color := rl.Color{235, 200, 120, 255}
|
||||
sheen_tint := rl.Color{255, 178, 153, 255}
|
||||
|
||||
// base durations
|
||||
fade_in_dur := f32(0.55)
|
||||
scale_dur := f32(1.10)
|
||||
sweep_delay := f32(0.20)
|
||||
sweep_dur := f32(1.20)
|
||||
glow_rise_dur := f32(0.70)
|
||||
|
||||
post_fade_in_dur := f32(0.25)
|
||||
post_hold_after_sweep := f32(0.35)
|
||||
post_fade_out_dur := f32(0.60)
|
||||
|
||||
DUR_SCALE :: f32(2.0)
|
||||
|
||||
blur_base := f32(1.0)
|
||||
blur_opacity_base := f32(0.08)
|
||||
|
||||
// overlay appears 7s into the mp3
|
||||
OVERLAY_DELAY :: f32(5.0)
|
||||
|
||||
SHEEN_GAIN :: 0.3 // overall intensity (0..1)
|
||||
SHEEN_W_SCALE :: 0.5 // width scaler (<1 = thinner)
|
||||
SHEEN_SOFT_ALPHA_CAP :: 0.10 // upper cap for soft halo
|
||||
SHEEN_CORE_ALPHA_CAP :: 0.28 // upper cap for core
|
||||
|
||||
prev_mt := f32(0)
|
||||
ended := false
|
||||
len_s := f32(rl.GetMusicTimeLength(music))
|
||||
|
||||
running := true
|
||||
for !rl.WindowShouldClose() && running {
|
||||
free_all(context.temp_allocator)
|
||||
|
||||
if rl.IsWindowResized() {
|
||||
rl.UnloadRenderTexture(rt)
|
||||
rt = rl.LoadRenderTexture(rl.GetScreenWidth(), rl.GetScreenHeight())
|
||||
rl.SetTextureFilter(rt.texture, .BILINEAR)
|
||||
}
|
||||
|
||||
rl.UpdateMusicStream(music)
|
||||
mt_raw := f32(rl.GetMusicTimePlayed(music))
|
||||
if !ended {
|
||||
if mt_raw < prev_mt - 0.02 ||
|
||||
mt_raw >= len_s - 0.01 ||
|
||||
(!rl.IsMusicStreamPlaying(music) && mt_raw > 0) {
|
||||
ended = true
|
||||
rl.StopMusicStream(music)
|
||||
}
|
||||
}
|
||||
mt := mt_raw
|
||||
if ended {
|
||||
mt = len_s
|
||||
running = false
|
||||
}
|
||||
prev_mt = mt_raw
|
||||
|
||||
visible := mt >= OVERLAY_DELAY
|
||||
t := mt - OVERLAY_DELAY
|
||||
if t < 0 {t = 0}
|
||||
|
||||
fade_in := fade_in_dur * DUR_SCALE
|
||||
scale_len := scale_dur * DUR_SCALE
|
||||
sweep_dly := sweep_delay * DUR_SCALE
|
||||
sweep_len := sweep_dur * DUR_SCALE
|
||||
glow_len := glow_rise_dur * DUR_SCALE
|
||||
post_in := post_fade_in_dur * DUR_SCALE
|
||||
post_hold := post_hold_after_sweep * DUR_SCALE
|
||||
post_out := post_fade_out_dur * DUR_SCALE
|
||||
|
||||
alpha := ease_out_cubic(t / fade_in)
|
||||
scale_bump := 0.06 * ease_out_back(t / scale_len, 1.3)
|
||||
font_size := base_font_size0 * (1.0 + scale_bump)
|
||||
|
||||
glow_in := ease_out_cubic(t / glow_len)
|
||||
glow_pulse := 0.5 + 0.5 * f32(math.sin(t * 2.0))
|
||||
|
||||
sweep_end_time := sweep_dly + sweep_len
|
||||
fade_out_start := sweep_end_time + post_hold
|
||||
|
||||
blur_env := adsr(
|
||||
t,
|
||||
0.18 * DUR_SCALE, // attack
|
||||
0.35 * DUR_SCALE, // decay
|
||||
0.70, // sustain level
|
||||
fade_out_start, // release start
|
||||
post_out, // release dur
|
||||
)
|
||||
blur_size := blur_base * lerp(1.00, 1.30, ease_in_out_cubic(blur_env))
|
||||
blur_opacity := blur_opacity_base
|
||||
blur_opacity *= (0.60 + 0.40 * blur_env) // grow with env
|
||||
blur_opacity *= clampf(glow_in * (0.8 + 0.2 * glow_pulse), 0.0, 1.0)
|
||||
|
||||
sheen_t := t - sweep_dly
|
||||
|
||||
raw_env := adsr(
|
||||
sheen_t,
|
||||
0.10 * DUR_SCALE,
|
||||
0.22 * DUR_SCALE,
|
||||
0.65,
|
||||
sweep_len,
|
||||
0.28 * DUR_SCALE,
|
||||
)
|
||||
sheen_env := math.pow(clampf(raw_env, 0, 1), 0.75) * SHEEN_GAIN
|
||||
|
||||
core_frac := lerp(0.12, 0.18, sheen_env) * SHEEN_W_SCALE
|
||||
soft_frac := lerp(0.24, 0.34, sheen_env) * SHEEN_W_SCALE
|
||||
|
||||
core_alpha_dyn := math.min(lerp(0.10, 0.26, sheen_env), SHEEN_CORE_ALPHA_CAP)
|
||||
soft_alpha_dyn := math.min(lerp(0.03, 0.09, sheen_env), SHEEN_SOFT_ALPHA_CAP)
|
||||
|
||||
center := rl.Vector2{f32(rl.GetScreenWidth()) * 0.5, f32(rl.GetScreenHeight()) * 0.5}
|
||||
|
||||
rl.BeginTextureMode(rt)
|
||||
rl.ClearBackground(rl.BLANK)
|
||||
|
||||
if visible {
|
||||
draw_shadow_bar(center.y, 1.4, 0.95, -0.002, 0.5, rl.BLACK)
|
||||
|
||||
draw_noun_verbed_sheen(
|
||||
font,
|
||||
text,
|
||||
center,
|
||||
font_size,
|
||||
spacing,
|
||||
text_color,
|
||||
alpha,
|
||||
sheen_tint,
|
||||
blur_size,
|
||||
blur_opacity,
|
||||
)
|
||||
|
||||
sweep_p := clampf((t - sweep_dly) / sweep_len, 0, 1)
|
||||
if sweep_p > 0 && sweep_p <= 1 {
|
||||
draw_sheen_sweep(
|
||||
font,
|
||||
text,
|
||||
center,
|
||||
font_size,
|
||||
spacing,
|
||||
sheen_tint,
|
||||
sweep_p,
|
||||
core_frac,
|
||||
soft_frac,
|
||||
core_alpha_dyn,
|
||||
soft_alpha_dyn,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
rl.EndTextureMode()
|
||||
|
||||
post_alpha := f32(1.0)
|
||||
if !visible {
|
||||
post_alpha = 0
|
||||
} else {
|
||||
if t < post_in {
|
||||
post_alpha = ease_out_cubic(t / post_in)
|
||||
} else if t >= fade_out_start {
|
||||
post_alpha = 1.0 - ease_out_cubic((t - fade_out_start) / post_out)
|
||||
}
|
||||
post_alpha = clampf(post_alpha, 0, 1)
|
||||
}
|
||||
|
||||
rl.BeginDrawing()
|
||||
rl.ClearBackground(rl.BLANK)
|
||||
|
||||
src := rl.Rectangle{0, 0, f32(rt.texture.width), -f32(rt.texture.height)}
|
||||
dst := rl.Rectangle{0, 0, f32(rl.GetScreenWidth()), f32(rl.GetScreenHeight())}
|
||||
rl.DrawTexturePro(
|
||||
rt.texture,
|
||||
src,
|
||||
dst,
|
||||
rl.Vector2{0, 0},
|
||||
0,
|
||||
with_alpha(rl.WHITE, post_alpha),
|
||||
)
|
||||
|
||||
rl.EndDrawing()
|
||||
}
|
||||
|
||||
rl.UnloadRenderTexture(rt)
|
||||
rl.UnloadFont(font)
|
||||
rl.UnloadMusicStream(music)
|
||||
rl.CloseAudioDevice()
|
||||
rl.CloseWindow()
|
||||
}
|
||||
Reference in New Issue
Block a user