Compare commits

...
6 Commits
10 changed files with 99 additions and 20 deletions
+3
View File
@@ -0,0 +1,3 @@
out/
assets/
gamecontrollerdb.txt
Binary file not shown.
Binary file not shown.
Binary file not shown.
+48
View File
@@ -0,0 +1,48 @@
#version 330
in vec2 fragTexCoord;
in vec4 fragColor;
out vec4 finalColor;
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// Adjust these values to tweak the aesthetic:
const float SCANLINE_INTENSITY = 0.25; // Lower value = softer lines (0.08 to 0.20)
const float BLOOM_AMOUNT = 0.10; // Slight phosphor bleed/glow
const float CRT_CURVATURE = 0.03; // Subtle screen bulge (0.0 = flat)
void main() {
// 1. Subtle screen curvature distortion
vec2 uv = fragTexCoord;
vec2 dc = abs(0.5 - uv);
uv.x += uv.x * (dc.y * dc.y) * CRT_CURVATURE;
uv.y += uv.y * (dc.x * dc.x) * CRT_CURVATURE;
// Discard pixels outside the curved screen bounds
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
finalColor = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
// 2. Sample pixel with slight horizontal blur (Phosphor bleed)
vec4 col = texture(texture0, uv);
vec4 col_left = texture(texture0, uv - vec2(0.0008, 0.0));
vec4 col_right = texture(texture0, uv + vec2(0.0008, 0.0));
col.rgb = mix(col.rgb, (col_left.rgb + col_right.rgb) * 0.5, BLOOM_AMOUNT);
// 3. Gaussian scanline profile matching 360 vertical lines
float scanline = sin(uv.y * 360.0 * 3.14159);
// Smooth power curve prevents harsh pitch-black cutoffs
float scanline_factor = pow(0.5 + 0.5 * scanline, 1.8);
// Apply scanlines smoothly
col.rgb *= mix(1.0 - SCANLINE_INTENSITY, 1.0, scanline_factor);
// 4. Subtle corner vignette
float vig = (16.0 * uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y));
col.rgb *= pow(vig, 0.05);
finalColor = col * colDiffuse * fragColor;
}
+4 -4
View File
@@ -20,7 +20,7 @@ Sound_ID :: enum {
Audio_Manager :: struct {
sounds: map[Sound_ID]rl.Sound,
music: rl.Music,
music_loaded: bool,
music_loaded: bool, //
sfx_vol: f32, // User SFX volume setting
user_music_vol: f32, // User Music volume setting
@@ -40,13 +40,13 @@ audio_init :: proc(audio: ^Audio_Manager) {
audio.sounds = make(map[Sound_ID]rl.Sound)
// Load SFX
audio.sfx_vol = 0.3
audio.sfx_vol = 0.4
audio.sounds[.UI_Select] = rl.LoadSound("assets/audio/ui/select.ogg")
audio.sounds[.Ball_Collision] = rl.LoadSound("assets/audio/gameplay/ballhit.ogg")
// Load Music Stream
audio.user_music_vol = 0.1
audio.current_music_vol = 0.1
audio.user_music_vol = 0.4
audio.current_music_vol = 0.4
audio.fade_state = .None
audio.music = rl.LoadMusicStream("assets/audio/gameplay/music/track_1.wav")
audio.music_loaded = true
+2 -1
View File
@@ -66,13 +66,13 @@ process_events :: proc(game: ^Game) {
intensity := 0.5 + (speed_factor * 4.5)
game_trigger_shake(game, intensity, duration = 0.15)
audio_play_sfx(&game.audio, .Ball_Collision)
case Simple_Event:
#partial switch e {
case .Game_Start:
set_root_scene(game, make_gameplay_scene())
game.transition = {true, 0, 0.2}
audio_fade_in(&game.audio, duration = 1.5)
case .Game_Pause:
@@ -92,6 +92,7 @@ process_events :: proc(game: ^Game) {
case .Game_Main_Menu:
set_root_scene(game, make_main_menu())
game.transition = {true, 0, 0.3}
audio_fade_out(&game.audio, duration = 1.0)
case .Game_Back:
+29 -3
View File
@@ -22,10 +22,17 @@ RESOLUTIONS := [?]Resolution{
{3840, 2160, "3840x2160"},
}
Transition :: struct {
active: bool,
elapsed: f32,
duration: f32,
}
Game :: struct {
viewport: rl.RenderTexture2D,
bg_texture: rl.Texture2D,
crt_shader: rl.Shader,
transition: Transition,
scene_stack: [dynamic]Scene,
should_close: bool,
audio: Audio_Manager,
@@ -79,9 +86,14 @@ game_init :: proc(game: ^Game) {
bg_img := rl.GenImageGradientRadial(VIEWPORT_W, VIEWPORT_H, 0.3, bg_center, bg_corner)
game.bg_texture = rl.LoadTextureFromImage(bg_img)
rl.UnloadImage(bg_img) // Free CPU memory
game.crt_shader = rl.LoadShader(nil, "assets/shaders/crt.fs")
// some ray gui color updates for now
rl.GuiSetStyle(.SLIDER, i32(rl.GuiControlProperty.BASE_COLOR_NORMAL), 0x00000000)
rl.GuiSetStyle(.SLIDER, i32(rl.GuiControlProperty.BORDER_WIDTH), 0x00000000)
rl.GuiSetStyle(.SLIDER, i32(rl.GuiControlProperty.BASE_COLOR_PRESSED), 0x66BFFFFF)
rl.GuiSetStyle(.SLIDER, i32(rl.GuiControlProperty.TEXT_COLOR_FOCUSED), 0x66BFFFFF)
// Setup 2D camera matching the 640x360 viewport center
game.camera = rl.Camera2D{
target = rl.Vector2{VIEWPORT_W / 2.0, VIEWPORT_H / 2.0},
@@ -90,6 +102,7 @@ game_init :: proc(game: ^Game) {
zoom = 1.0,
}
game.transition = {true, 0, 0.2}
game.should_close = false
set_root_scene(game, make_main_menu())
}
@@ -121,10 +134,15 @@ game_update :: proc(game: ^Game) {
}
active_scene := get_active_scene(game)
if active_scene != nil {
if game.transition.active {
game.transition.elapsed += dt
if game.transition.elapsed >= game.transition.duration do game.transition.active = false
} else if active_scene != nil {
scene_update(active_scene, game, input, dt)
}
// background music buffer streaming
audio_update(&game.audio, dt)
@@ -146,13 +164,21 @@ game_render :: proc(game: ^Game) {
for &scene in game.scene_stack {
scene_render(&scene)
}
// when game transition active increment its elapsed time
// render will check and display accordingly
if game.transition.active {
a := u8(255 * (1 - clamp(game.transition.elapsed / game.transition.duration, 0, 1)))
rl.DrawRectangle(0, 0, VIEWPORT_W, VIEWPORT_H, {0, 0, 0, a})
}
rl.EndMode2D()
rl.EndTextureMode()
render_game_to_window(game)
rl.DrawFPS(10, game.window_h - 20)
when DEBUG do rl.DrawFPS(10, game.window_h - 20)
rl.EndDrawing()
}
+4 -3
View File
@@ -1,5 +1,6 @@
package game
import "core:strings"
import "core:fmt"
import rl "vendor:raylib"
@@ -177,8 +178,8 @@ list_menu_items :: proc(canvas: Canvas, menu: UI_Menu) {
item_rec := get_canvas_item_rec(canvas, i, top_margin = UI_TOP_MARGIN_LIST)
is_selected := (i == menu.selected_index)
border_color := is_selected ? rl.ORANGE : rl.DARKGRAY
text_color := is_selected ? rl.ORANGE : rl.WHITE
border_color := is_selected ? rl.SKYBLUE : rl.DARKGRAY
text_color := is_selected ? rl.SKYBLUE : rl.WHITE
rl.DrawRectangleLinesEx(item_rec, UI_ITEM_BORDER_THICK, border_color)
@@ -191,7 +192,7 @@ list_menu_items :: proc(canvas: Canvas, menu: UI_Menu) {
case UI_Slider:
slider_rec := item_rec
text_width := rl.MeasureText(v.label, UI_LABEL_FONT_SIZE)
text_width := 31
slider_rec.x = slider_rec.x + f32(text_width * 2)
slider_rec.width = (slider_rec.width - f32(text_width * 2))