diff --git a/assets/audio/breath.mp3 b/assets/audio/breath.mp3 new file mode 100644 index 0000000..4b903a5 Binary files /dev/null and b/assets/audio/breath.mp3 differ diff --git a/assets/audio/die.mp3 b/assets/audio/die.mp3 new file mode 100644 index 0000000..128c504 Binary files /dev/null and b/assets/audio/die.mp3 differ diff --git a/assets/audio/fishPickup.mp3 b/assets/audio/fishPickup.mp3 new file mode 100644 index 0000000..c4e79bd Binary files /dev/null and b/assets/audio/fishPickup.mp3 differ diff --git a/assets/audio/swim1.mp3 b/assets/audio/swim1.mp3 new file mode 100644 index 0000000..1b19675 Binary files /dev/null and b/assets/audio/swim1.mp3 differ diff --git a/assets/audio/swim2.mp3 b/assets/audio/swim2.mp3 new file mode 100644 index 0000000..5d89251 Binary files /dev/null and b/assets/audio/swim2.mp3 differ diff --git a/assets/audio/swim3.mp3 b/assets/audio/swim3.mp3 new file mode 100644 index 0000000..8686edb Binary files /dev/null and b/assets/audio/swim3.mp3 differ diff --git a/assets/audio/swim4.mp3 b/assets/audio/swim4.mp3 new file mode 100644 index 0000000..20256ce Binary files /dev/null and b/assets/audio/swim4.mp3 differ diff --git a/assets/audio/uiBuy.mp3 b/assets/audio/uiBuy.mp3 new file mode 100644 index 0000000..47bcb39 Binary files /dev/null and b/assets/audio/uiBuy.mp3 differ diff --git a/assets/audio/uiClick.mp3 b/assets/audio/uiClick.mp3 new file mode 100644 index 0000000..a6079ff Binary files /dev/null and b/assets/audio/uiClick.mp3 differ diff --git a/assets/audio/waterrecordings.wav b/assets/audio/waterrecordings.wav new file mode 100644 index 0000000..d86366f Binary files /dev/null and b/assets/audio/waterrecordings.wav differ diff --git a/assets/img/enemies/whirlpool.aseprite b/assets/img/enemies/whirlpool.aseprite new file mode 100644 index 0000000..f85c550 Binary files /dev/null and b/assets/img/enemies/whirlpool.aseprite differ diff --git a/assets/img/enemies/whirlpool.json b/assets/img/enemies/whirlpool.json new file mode 100644 index 0000000..21c2e0d --- /dev/null +++ b/assets/img/enemies/whirlpool.json @@ -0,0 +1,51 @@ +{ "frames": { + "whirlpool 0.aseprite": { + "frame": { "x": 0, "y": 0, "w": 20, "h": 20 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 }, + "sourceSize": { "w": 20, "h": 20 }, + "duration": 300 + }, + "whirlpool 1.aseprite": { + "frame": { "x": 20, "y": 0, "w": 20, "h": 20 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 }, + "sourceSize": { "w": 20, "h": 20 }, + "duration": 300 + }, + "whirlpool 2.aseprite": { + "frame": { "x": 40, "y": 0, "w": 20, "h": 20 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 }, + "sourceSize": { "w": 20, "h": 20 }, + "duration": 300 + }, + "whirlpool 3.aseprite": { + "frame": { "x": 60, "y": 0, "w": 20, "h": 20 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 }, + "sourceSize": { "w": 20, "h": 20 }, + "duration": 300 + } + }, + "meta": { + "app": "http://www.aseprite.org/", + "version": "1.2.27-x64", + "image": "whirlpool.png", + "format": "RGBA8888", + "size": { "w": 80, "h": 20 }, + "scale": "1", + "frameTags": [ + ], + "layers": [ + { "name": "Layer 1", "opacity": 255, "blendMode": "normal" }, + { "name": "Layer 2", "opacity": 255, "blendMode": "normal" } + ], + "slices": [ + ] + } +} diff --git a/assets/img/enemies/whirlpool.png b/assets/img/enemies/whirlpool.png new file mode 100644 index 0000000..2e9d310 Binary files /dev/null and b/assets/img/enemies/whirlpool.png differ diff --git a/assets/img/map/backBack.png b/assets/img/map/backBack.png new file mode 100644 index 0000000..f0e9259 Binary files /dev/null and b/assets/img/map/backBack.png differ diff --git a/assets/img/map/backFront.png b/assets/img/map/backFront.png new file mode 100644 index 0000000..2d47720 Binary files /dev/null and b/assets/img/map/backFront.png differ diff --git a/assets/shaders/pixel.fs b/assets/shaders/pixel.fs index 2148371..7e576a9 100644 --- a/assets/shaders/pixel.fs +++ b/assets/shaders/pixel.fs @@ -8,25 +8,43 @@ in vec4 fragColor; uniform sampler2D texture0; uniform vec4 colDiffuse; +// Time fed from CPU +uniform float time = 0.0; + // Output fragment color out vec4 finalColor; // Viewport dimensions -const float renderWidth = 1080; -const float renderHeight = 720; +const vec2 viewport = vec2(1080.0, 720.0); // Pixel scaling -uniform float pixelWidth = 2.0; -uniform float pixelHeight = 2.0; +const vec2 pixelScale = vec2(2.0, 2.0); void main() { - float dx = pixelWidth * (1.0 / renderWidth); - float dy = pixelHeight * (1.0 / renderHeight); - vec2 coord = vec2(dx * floor(fragTexCoord.x / dx), dy * floor(fragTexCoord.y / dy)); + // Calculate the distance to merge pixels + float dx = pixelScale.x * (1.0 / viewport.x); + float dy = pixelScale.y * (1.0 / viewport.y); - vec3 tc = texture(texture0, coord).rgb; + // Get the base UV coordinate of the pixel + vec2 baseUV = fragTexCoord; + + // Use a wave function to translate the pixel UV + float X = baseUV.x*0.5+time; + float Y = baseUV.y*0.25+time; + baseUV.y += cos(X+Y)*0.0025*cos(Y); + baseUV.x += sin(X-Y)*0.012*sin(Y); + // Calculate a UV for this new blocky pixel + vec2 pixelatedUV = vec2(dx * floor(baseUV.x / dx), dy * floor(baseUV.y / dy)); + + // Rebuild the texture with the new UVs + vec3 tc = texture(texture0, pixelatedUV).rgb; + + // Apply a color filter + tc = tc + vec3(0, 0.05, 0.15); + + // Build the final pixel finalColor = vec4(tc, 1.0); -} +} \ No newline at end of file diff --git a/assets/worlds/mainworld.json b/assets/worlds/mainworld.json index 146d91d..4f9198f 100644 --- a/assets/worlds/mainworld.json +++ b/assets/worlds/mainworld.json @@ -1,7 +1,7 @@ { "end_position": { "x": 350.0, - "y": 2100.0 + "y": 2050.0 }, "player_spawn": { "x": 220.0, diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs index 1ebedaf..58f74e1 100644 --- a/src/logic/ingame/mod.rs +++ b/src/logic/ingame/mod.rs @@ -16,12 +16,17 @@ pub enum InGameState { pub struct InGameScreen { current_state: InGameState, + shader_time_var_location: i32, } impl InGameScreen { - pub fn new() -> Self { + pub unsafe fn new(game_core: &GameCore) -> Self { Self { current_state: InGameState::SWIMMING, + shader_time_var_location: raylib::ffi::GetShaderLocation( + *game_core.resources.pixel_shader, + rstr!("time").as_ptr(), + ), } } @@ -46,13 +51,49 @@ impl InGameScreen { }; // Clear the background - context_2d.draw_rectangle_gradient_v( - world_bounds.x as i32, - world_bounds.y as i32, - world_bounds.width as i32, - world_bounds.height as i32, - WATER, - WATER_DARK, + // context_2d.draw_rectangle_gradient_v( + // world_bounds.x as i32, + // world_bounds.y as i32, + // world_bounds.width as i32, + // world_bounds.height as i32, + // WATER, + // WATER_DARK, + // ); + context_2d.draw_texture_pro( + &game_core.resources.background_back, + Rectangle { + x: 0.0, + y: 0.0, + width: game_core.resources.background_back.width as f32, + height: game_core.resources.background_back.height as f32, + }, + Rectangle::new( + 0.0, + 0.0, + (game_core.resources.background_back.width * 2) as f32, + (game_core.resources.background_back.height * 2) as f32, + ), + Vector2 { x: 0.0, y: 0.0 }, + 0.0, + Color::WHITE, + ); + context_2d.draw_texture_pro( + &game_core.resources.background_front, + Rectangle { + x: 0.0, + y: 0.0, + width: game_core.resources.background_front.width as f32, + height: game_core.resources.background_front.height as f32, + }, + Rectangle::new( + 0.0, + 0.0, + (game_core.resources.background_front.width * 2) as f32, + (game_core.resources.background_front.height * 2) as f32, + ), + Vector2 { x: 0.0, y: 0.0 }, + 0.0, + Color::WHITE, ); // Render fish @@ -176,11 +217,9 @@ impl Screen for InGameScreen { { let mut context_2d = draw_handle.begin_mode2D(game_core.master_camera); - // Clear frame context_2d.clear_background(Color::BLACK); - // Render the world self.render_world(&mut context_2d, game_core, dt); if game_core.show_simple_debug_info { @@ -223,8 +262,7 @@ impl Screen for InGameScreen { game_core.world.whirlpool.retain(|x| !x.should_remove()); - // Render transponder - game_core.resources.transponder.draw(&mut context_2d, game_core.world.end_position + Vector2::new(0.0, -50.0), 0.0); + @@ -232,6 +270,12 @@ impl Screen for InGameScreen { + // Render transponder + game_core.resources.transponder.draw( + &mut context_2d, + game_core.world.end_position, + 0.0, + ); // Render Player game_core @@ -243,13 +287,19 @@ impl Screen for InGameScreen { } } + // Update the shader's internal time + game_core + .resources + .pixel_shader + .set_shader_value(self.shader_time_var_location, draw_handle.get_time() as f32); + // Render the 2D context via the ripple shader { let mut shader_context = draw_handle.begin_shader_mode(&game_core.resources.pixel_shader); // Blit the texture - shader_context.draw_texture_rec( + shader_context.draw_texture_pro( &game_core.resources.shader_texture, Rectangle { x: 0.0, @@ -257,7 +307,14 @@ impl Screen for InGameScreen { width: game_core.resources.shader_texture.width() as f32, height: (game_core.resources.shader_texture.height() as f32) * -1.0, }, + Rectangle { + x: -10.0, + y: -10.0, + width: win_width as f32 + 20.0, + height: win_height as f32 + 20.0, + }, Vector2::zero(), + 0.0, Color::WHITE, ); } @@ -273,9 +330,14 @@ impl Screen for InGameScreen { return Some(GameState::GameEnd); } - if game_core.world.end_position.distance_to(game_core.player.position) <= 70.0{ - return Some(GameState::WinGame); - } + if game_core + .world + .end_position + .distance_to(game_core.player.position) + <= 70.0 + { + return Some(GameState::WinGame); + } return None; } diff --git a/src/logic/pausemenu.rs b/src/logic/pausemenu.rs index 375dec5..7b627f0 100644 --- a/src/logic/pausemenu.rs +++ b/src/logic/pausemenu.rs @@ -125,7 +125,7 @@ impl Screen for PauseMenuScreen { draw_handle.draw_text( "Credits:\n\t- @ewpratten\n\t- @rsninja722\n\t- @wm-c\n\t- @catarinaburghi", (win_width / 2) - (SCREEN_PANEL_SIZE.x as i32 / 2) + 10, - (win_height / 2) - (SCREEN_PANEL_SIZE.y as i32 / 2) + 120, + (win_height / 2) - (SCREEN_PANEL_SIZE.y as i32 / 2) + 170, 20, Color::BLACK, ); diff --git a/src/main.rs b/src/main.rs index c4822d3..e4982fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,16 @@ mod world; use gamecore::{GameCore, GameProgress, GameState}; use lib::{utils::profiler::GameProfiler, wrappers::audio::player::AudioPlayer}; use log::info; -use logic::{gameend::GameEndScreen, ingame::InGameScreen, loadingscreen::LoadingScreen, mainmenu::MainMenuScreen, pausemenu::PauseMenuScreen, screen::Screen, shop::ShopScreen, winscreen::{self, WinScreen}}; +use logic::{ + gameend::GameEndScreen, + ingame::InGameScreen, + loadingscreen::LoadingScreen, + mainmenu::MainMenuScreen, + pausemenu::PauseMenuScreen, + screen::Screen, + shop::ShopScreen, + winscreen::{self, WinScreen}, +}; use raylib::prelude::*; use world::{load_world_colliders, World}; @@ -69,10 +78,13 @@ fn main() { let mut loading_screen = LoadingScreen::new(); let mut main_menu_screen = MainMenuScreen::new(); let mut pause_menu_screen = PauseMenuScreen::new(); - let mut ingame_screen = InGameScreen::new(); + let mut ingame_screen; + unsafe { + ingame_screen = InGameScreen::new(&game_core); + } let mut game_end_screen = GameEndScreen::new(); let mut shop_screen = ShopScreen::new(); - let mut win_screen = WinScreen::new(); + let mut win_screen = WinScreen::new(); // Main rendering loop while !raylib.window_should_close() { @@ -117,12 +129,12 @@ fn main() { &mut audio_system, &mut game_core, ), - GameState::WinGame => win_screen.render( + GameState::WinGame => win_screen.render( &mut draw_handle, &raylib_thread, &mut audio_system, &mut game_core, - ) + ), }; // If needed, update the global state diff --git a/src/resources.rs b/src/resources.rs index f67c6f0..8175e18 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -31,6 +31,10 @@ pub struct GlobalResources { // Darkness layer pub darkness_overlay: Texture2D, + + // Backgrounds + pub background_front: Texture2D, + pub background_back: Texture2D, // Shop & items pub shop_background: Texture2D, @@ -167,6 +171,14 @@ impl GlobalResources { &thread, &Image::load_image("./assets/img/map/darkness.png")?, )?, + background_front: raylib.load_texture_from_image( + &thread, + &Image::load_image("./assets/img/map/backFront.png")?, + )?, + background_back: raylib.load_texture_from_image( + &thread, + &Image::load_image("./assets/img/map/backBack.png")?, + )?, shop_background: raylib.load_texture_from_image( &thread, &Image::load_image("./assets/img/map/shopHighRes.png")?,