Merge branch 'master' into suck-monster

This commit is contained in:
wm-c 2021-04-25 20:49:30 -04:00
commit 1928d0d292
22 changed files with 150 additions and 314 deletions

View File

@ -13,9 +13,4 @@ serialstudio = "0.1.0"
serde = "1.0.125" serde = "1.0.125"
serde_json = "1.0.64" serde_json = "1.0.64"
failure = "0.1.8" failure = "0.1.8"
parry2d = "0.4.0"
log = "0.4.14"
env_logger = "0.8.3"
nalgebra = "0.26.1"
rand = "0.8.3" rand = "0.8.3"
tiled = "0.9.4"

View File

@ -28,7 +28,7 @@ impl EnemyBase for JellyFish {
fn render( fn render(
&mut self, &mut self,
context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>, context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>,
player: &mut Player, _player: &mut Player,
resources: &mut GlobalResources, resources: &mut GlobalResources,
dt: f64, dt: f64,
) { ) {
@ -77,7 +77,7 @@ impl EnemyBase for JellyFish {
&& !is_jelly_stunned; && !is_jelly_stunned;
} }
fn handle_logic(&mut self, player: &mut Player, dt: f64) { fn handle_logic(&mut self, player: &mut Player, _dt: f64) {
// Handle stunning the player // Handle stunning the player
if self.do_stun_player { if self.do_stun_player {
if self.position.distance_to(player.position).abs() <= JELLYFISH_STUN_REACH { if self.position.distance_to(player.position).abs() <= JELLYFISH_STUN_REACH {
@ -86,7 +86,7 @@ impl EnemyBase for JellyFish {
} }
} }
fn handle_getting_attacked(&mut self, stun_duration: f64, current_time: f64) { fn handle_getting_attacked(&mut self, stun_duration: f64, _current_time: f64) {
self.stunned_timer = stun_duration; self.stunned_timer = stun_duration;
self.max_stunned_time = stun_duration; self.max_stunned_time = stun_duration;
} }

View File

@ -1,11 +1,11 @@
use crate::{ use crate::{
lib::utils::calculate_linear_slide, lib::utils::calculate_linear_slide,
pallette::{TRANSLUCENT_RED_64, TRANSLUCENT_WHITE_128, TRANSLUCENT_WHITE_64}, pallette::{TRANSLUCENT_RED_64, TRANSLUCENT_WHITE_128},
player::Player, player::Player,
}; };
use super::base::EnemyBase; use super::base::EnemyBase;
use rand::{prelude::ThreadRng, Rng}; use rand::Rng;
use raylib::prelude::*; use raylib::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -13,7 +13,6 @@ const OCTOPUS_SUCK_AIR_DELAY: f64 = 3.5;
const OCTOPUS_SUCK_AIR_RANGE: f32 = 70.0; const OCTOPUS_SUCK_AIR_RANGE: f32 = 70.0;
const OCTOPUS_SUCK_AIR_DURATION: f64 = 1.0; const OCTOPUS_SUCK_AIR_DURATION: f64 = 1.0;
const OCTOPUS_SUCK_AIR_AMOUNT: f32 = 0.1; const OCTOPUS_SUCK_AIR_AMOUNT: f32 = 0.1;
// const RNG: ThreadRng = rand::thread_rng();
#[derive(Debug, Serialize, Deserialize, Default, Clone)] #[derive(Debug, Serialize, Deserialize, Default, Clone)]
struct OctopusAirBubble { struct OctopusAirBubble {
@ -124,7 +123,7 @@ impl EnemyBase for Octopus {
} }
} }
fn handle_logic(&mut self, player: &mut crate::player::Player, dt: f64) { fn handle_logic(&mut self, player: &mut crate::player::Player, _dt: f64) {
if self.suck_air_time_remaining > 0.0 && !self.has_taken_air_from_player { if self.suck_air_time_remaining > 0.0 && !self.has_taken_air_from_player {
if player.position.distance_to(self.current_position).abs() <= OCTOPUS_SUCK_AIR_RANGE { if player.position.distance_to(self.current_position).abs() <= OCTOPUS_SUCK_AIR_RANGE {
// Take air from the player // Take air from the player
@ -136,7 +135,7 @@ impl EnemyBase for Octopus {
} }
} }
fn handle_getting_attacked(&mut self, stun_duration: f64, current_time: f64) { fn handle_getting_attacked(&mut self, stun_duration: f64, _current_time: f64) {
self.stunned_timer = stun_duration; self.stunned_timer = stun_duration;
self.max_stunned_time = stun_duration; self.max_stunned_time = stun_duration;
} }

View File

@ -1,18 +1,7 @@
use rand::{prelude::ThreadRng, Rng}; use rand::{prelude::ThreadRng, Rng};
use raylib::prelude::*; use raylib::prelude::*;
use crate::{ use crate::{player::Player, resources::GlobalResources};
gamecore::{self, GameCore},
lib::utils::triangles::rotate_vector,
player::Player,
resources::GlobalResources,
world::World,
};
const FISH_FOLLOW_PLAYER_DISTANCE: f32 = 30.0;
const FISH_FOLLOW_PLAYER_SPEED: f32 = 1.8;
const FISH_FOLLOW_PLAYER_SPEED_FAST: f32 = FISH_FOLLOW_PLAYER_SPEED * 3.0;
const FISH_ATTACH_RADIUS: f32 = 20.0;
const FISH_VISION: f32 = 25.0; const FISH_VISION: f32 = 25.0;
const FISH_MAX_SPEED: f32 = 2.0; const FISH_MAX_SPEED: f32 = 2.0;
@ -63,7 +52,12 @@ impl FishEntity {
return output; return output;
} }
pub fn handle_follow_player(&mut self, player: &Player, dt: f64, other_fish: &Vec<FishEntity>) { pub fn handle_follow_player(
&mut self,
player: &Player,
_dt: f64,
other_fish: &Vec<FishEntity>,
) {
let mut acceleration: Vector2 = Vector2::zero(); let mut acceleration: Vector2 = Vector2::zero();
let mut steer: Vector2 = Vector2::zero(); let mut steer: Vector2 = Vector2::zero();
@ -140,11 +134,7 @@ impl FishEntity {
self.position += self.velocity; self.position += self.velocity;
} }
pub fn handle_free_movement(&mut self, player: &mut Player, dt: f64) { pub fn handle_free_movement(&mut self, player: &mut Player, _dt: f64) {
// Distance and direction to player
let dist_to_player = player.position - self.position;
let dist_to_player_lin = self.position.distance_to(player.position);
// Handle player picking up fish // Handle player picking up fish
if player.position.distance_to(self.position).abs() <= player.size.y * 2.2 { if player.position.distance_to(self.position).abs() <= player.size.y * 2.2 {
self.following_player = true; self.following_player = true;

View File

@ -5,15 +5,13 @@ use std::{fmt, fs::File, io::BufReader};
use raylib::{ use raylib::{
camera::Camera2D, math::Vector2, prelude::RaylibDrawHandle, RaylibHandle, RaylibThread, camera::Camera2D, math::Vector2, prelude::RaylibDrawHandle, RaylibHandle, RaylibThread,
}; };
use failure::Error;
use crate::{ use crate::{
player::{Player, PlayerInventory}, player::{Player, PlayerInventory},
resources::GlobalResources, resources::GlobalResources,
world::World, world::World,
}; };
use failure::Error;
use log::debug;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// Overall states for the game /// Overall states for the game
@ -26,7 +24,7 @@ pub enum GameState {
InGame, InGame,
GameEnd, GameEnd,
InShop, InShop,
WinGame WinGame,
} }
impl fmt::Display for GameState { impl fmt::Display for GameState {
@ -80,7 +78,6 @@ impl GameProgress {
} }
pub fn update(&mut self, new_progress: &GameProgress) { pub fn update(&mut self, new_progress: &GameProgress) {
// Bring in new data // Bring in new data
self.coins = new_progress.coins; self.coins = new_progress.coins;
self.inventory = new_progress.inventory.clone(); self.inventory = new_progress.inventory.clone();
@ -92,7 +89,6 @@ impl GameProgress {
if result.is_err() { if result.is_err() {
println!("Could not save game state. Holding in RAM"); println!("Could not save game state. Holding in RAM");
} }
} }
} }
@ -152,8 +148,6 @@ impl GameCore {
} }
pub fn switch_state(&mut self, new_state: GameState, draw_handle: Option<&RaylibDrawHandle>) { pub fn switch_state(&mut self, new_state: GameState, draw_handle: Option<&RaylibDrawHandle>) {
debug!("Switching global state to: {}", new_state);
self.last_state = self.state; self.last_state = self.state;
self.state = new_state; self.state = new_state;

View File

@ -2,7 +2,6 @@ use raylib::{
color::Color, color::Color,
math::{Rectangle, Vector2}, math::{Rectangle, Vector2},
prelude::{RaylibDraw, RaylibDrawHandle}, prelude::{RaylibDraw, RaylibDrawHandle},
texture::Texture2D,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@ -1,32 +0,0 @@
use std::usize;
use raylib::prelude::*;
pub struct FrameRange {
pub min: usize,
pub max: usize,
}
pub struct ComplexAnimationTool {
sprite_sheet: Texture2D,
frames_per_second: f32,
frame_size: Vector2,
sprite_sheet_size_frames: Vector2
}
impl ComplexAnimationTool {
pub fn render_loop(&self, context_2d: &mut RaylibMode2D<RaylibDrawHandle>, bounds: Rectangle, rotation: f32, range: &FrameRange) {
}
pub fn render_frame(&self, context_2d: &mut RaylibMode2D<RaylibDrawHandle>, bounds: Rectangle, rotation: f32, id: usize) {
// Convert the ID to an xy
let col_id = id % self.sprite_sheet_size_frames.x as usize;
let row_id = id / self.sprite_sheet_size_frames.y as usize;
}
}

View File

@ -1,3 +1,2 @@
pub mod audio; pub mod audio;
pub mod animation; pub mod animation;
pub mod complexanimation;

View File

@ -22,7 +22,7 @@ impl Screen for GameEndScreen {
&mut self, &mut self,
draw_handle: &mut RaylibDrawHandle, draw_handle: &mut RaylibDrawHandle,
_thread: &RaylibThread, _thread: &RaylibThread,
audio_system: &mut AudioPlayer, _audio_system: &mut AudioPlayer,
game_core: &mut GameCore, game_core: &mut GameCore,
) -> Option<GameState> { ) -> Option<GameState> {
draw_handle.clear_background(Color::GRAY); draw_handle.clear_background(Color::GRAY);
@ -75,7 +75,7 @@ impl Screen for GameEndScreen {
String::from("Return to shop"), String::from("Return to shop"),
Rectangle { Rectangle {
x: (((win_width / 2) - ((SCREEN_PANEL_SIZE.x as i32 + 6) / 2) + 5) x: (((win_width / 2) - ((SCREEN_PANEL_SIZE.x as i32 + 6) / 2) + 5)
+ (0.15 * SCREEN_PANEL_SIZE.x) as i32) as f32, + (0.15 * SCREEN_PANEL_SIZE.x) as i32) as f32,
y: (((win_height / 2) - (SCREEN_PANEL_SIZE.y as i32 / 2) + 90) as f32) + 100.0, y: (((win_height / 2) - (SCREEN_PANEL_SIZE.y as i32 / 2) + 90) as f32) + 100.0,
width: 210.0, width: 210.0,
height: 50.0, height: 50.0,
@ -87,78 +87,15 @@ impl Screen for GameEndScreen {
true, true,
); );
// render button // render button
go_to_menu_button.render(draw_handle); go_to_menu_button.render(draw_handle);
// If the player clicks on the button send them to shop // If the player clicks on the button send them to shop
if go_to_menu_button.is_hovered(draw_handle) && draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON){ if go_to_menu_button.is_hovered(draw_handle)
&& draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON)
game_core.switch_state(GameState::InShop, Some(draw_handle)); {
return Some(GameState::InShop);
} }
// TODO: Save game progress
// // Close and quit buttons
// let bottom_left_button_dimensions = Rectangle {
// x: (win_width as f32 / 2.0) - (SCREEN_PANEL_SIZE.x / 2.0) + 5.0,
// y: (win_height as f32 / 2.0) + (SCREEN_PANEL_SIZE.y / 2.0) - 50.0,
// width: (SCREEN_PANEL_SIZE.x / 2.0) - 15.0,
// height: 40.0,
// };
// let bottom_right_button_dimensions = Rectangle {
// x: (win_width as f32 / 2.0) + 5.0,
// y: bottom_left_button_dimensions.y,
// width: bottom_left_button_dimensions.width,
// height: bottom_left_button_dimensions.height,
// };
// // Check if the mouse is over either button
// let mouse_over_bottom_left_button =
// bottom_left_button_dimensions.check_collision_point_rec(mouse_position);
// let mouse_over_bottom_right_button =
// bottom_right_button_dimensions.check_collision_point_rec(mouse_position);
// // Render buttons
// draw_handle.draw_rectangle_lines_ex(
// bottom_left_button_dimensions,
// 3,
// match mouse_over_bottom_left_button {
// true => Color::GRAY,
// false => Color::BLACK,
// },
// );
// draw_handle.draw_text(
// "Quit",
// bottom_left_button_dimensions.x as i32 + 15,
// bottom_left_button_dimensions.y as i32 + 5,
// 30,
// Color::BLACK,
// );
// draw_handle.draw_rectangle_lines_ex(
// bottom_right_button_dimensions,
// 3,
// match mouse_over_bottom_right_button {
// true => Color::GRAY,
// false => Color::BLACK,
// },
// );
// draw_handle.draw_text(
// "Close",
// bottom_right_button_dimensions.x as i32 + 15,
// bottom_right_button_dimensions.y as i32 + 5,
// 30,
// Color::BLACK,
// );
// // Handle click actions on the buttons
// if draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON) {
// if mouse_over_bottom_left_button {
// return Some(GameState::GameQuit);
// } else if mouse_over_bottom_right_button {
// return Some(game_core.last_state);
// }
// }
return None; return None;
} }

View File

@ -3,26 +3,19 @@ mod playerlogic;
use raylib::prelude::*; use raylib::prelude::*;
use crate::{entities::enemy::{base::EnemyBase, whirlpool::Whirlpool}, gamecore::{GameCore, GameState}, lib::wrappers::audio::player::AudioPlayer, pallette::{SKY, WATER, WATER_DARK}}; use crate::{entities::enemy::{base::EnemyBase, whirlpool::Whirlpool}, gamecore::{GameCore, GameState}, lib::wrappers::audio::player::AudioPlayer};
use super::screen::Screen; use super::screen::Screen;
use crate::entities::fish::FishEntity; use crate::entities::fish::FishEntity;
pub enum InGameState {
BUYING,
SWIMMING,
}
pub struct InGameScreen { pub struct InGameScreen {
current_state: InGameState,
shader_time_var_location: i32, shader_time_var_location: i32,
} }
impl InGameScreen { impl InGameScreen {
pub unsafe fn new(game_core: &GameCore) -> Self { pub unsafe fn new(game_core: &GameCore) -> Self {
Self { Self {
current_state: InGameState::SWIMMING,
shader_time_var_location: raylib::ffi::GetShaderLocation( shader_time_var_location: raylib::ffi::GetShaderLocation(
*game_core.resources.pixel_shader, *game_core.resources.pixel_shader,
rstr!("time").as_ptr(), rstr!("time").as_ptr(),
@ -185,8 +178,8 @@ impl Screen for InGameScreen {
fn render( fn render(
&mut self, &mut self,
draw_handle: &mut RaylibDrawHandle, draw_handle: &mut RaylibDrawHandle,
thread: &RaylibThread, _thread: &RaylibThread,
audio_system: &mut AudioPlayer, _audio_system: &mut AudioPlayer,
game_core: &mut GameCore, game_core: &mut GameCore,
) -> Option<GameState> { ) -> Option<GameState> {
// Calculate DT // Calculate DT
@ -204,7 +197,6 @@ impl Screen for InGameScreen {
x: (win_width as f32 / 2.0), x: (win_width as f32 / 2.0),
y: (win_height as f32 / 2.0), y: (win_height as f32 / 2.0),
}; };
let camera_window_center = window_center * (1.0 / game_core.master_camera.zoom);
// Update player movement // Update player movement
playerlogic::update_player_movement(draw_handle, game_core, window_center); playerlogic::update_player_movement(draw_handle, game_core, window_center);
@ -261,12 +253,6 @@ impl Screen for InGameScreen {
game_core.world.whirlpool.retain(|x| !x.should_remove()); game_core.world.whirlpool.retain(|x| !x.should_remove());

View File

@ -1,13 +1,9 @@
use raylib::prelude::*; use raylib::prelude::*;
use crate::{ use crate::gamecore::GameCore;
gamecore::GameCore,
pallette::{TRANSLUCENT_WHITE_128, TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96},
};
const NORMAL_PLAYER_SPEED: i32 = 1; const NORMAL_PLAYER_SPEED: i32 = 1;
const BOOST_PLAYER_SPEED: i32 = NORMAL_PLAYER_SPEED * 2; const BOOST_PLAYER_SPEED: i32 = NORMAL_PLAYER_SPEED * 2;
const CAMERA_FOLLOW_SPEED: f32 = 0.7;
const TURN_SPEED: f32 = 0.15; const TURN_SPEED: f32 = 0.15;
const BOOST_DECREASE_PER_SECOND: f32 = 0.65; const BOOST_DECREASE_PER_SECOND: f32 = 0.65;
const BOOST_REGEN_PER_SECOND: f32 = 0.25; const BOOST_REGEN_PER_SECOND: f32 = 0.25;
@ -79,7 +75,9 @@ pub fn update_player_movement(
let user_request_action = draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_RIGHT_BUTTON); let user_request_action = draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_RIGHT_BUTTON);
if user_request_action { if user_request_action {
game_core.player.begin_attack(&mut game_core.world, draw_handle.get_time()); game_core
.player
.begin_attack(&mut game_core.world, draw_handle.get_time());
} }
// Move the player in their direction // Move the player in their direction
@ -150,7 +148,13 @@ pub fn update_player_movement(
// Handle the player wearing flippers // Handle the player wearing flippers
if game_core.player.inventory.flippers.is_some() { if game_core.player.inventory.flippers.is_some() {
player_real_movement *= game_core.player.inventory.flippers.as_ref().unwrap().speed_increase; player_real_movement *= game_core
.player
.inventory
.flippers
.as_ref()
.unwrap()
.speed_increase;
} }
@ -256,8 +260,6 @@ pub fn update_player_movement(
// Move the camera to follow the player // Move the camera to follow the player
let direction_from_cam_to_player =
(game_core.player.position - window_center) - game_core.master_camera.target;
let player_screen_position = let player_screen_position =
draw_handle.get_world_to_screen2D(game_core.player.position, game_core.master_camera); draw_handle.get_world_to_screen2D(game_core.player.position, game_core.master_camera);

View File

@ -1,11 +1,13 @@
use raylib::prelude::*; use raylib::prelude::*;
use crate::{gamecore::{GameCore, GameState}, lib::{utils::calculate_linear_slide, wrappers::audio::player::AudioPlayer}}; use crate::{
gamecore::{GameCore, GameState},
lib::{utils::calculate_linear_slide, wrappers::audio::player::AudioPlayer},
};
use super::screen::Screen; use super::screen::Screen;
const SECONDS_PER_LOGO: f64 = 4.0; const SECONDS_PER_LOGO: f64 = 4.0;
const RUST_ORANGE: Color = Color::new(222, 165, 132, 255);
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
enum LoadingScreenState { enum LoadingScreenState {
@ -138,7 +140,7 @@ impl Screen for LoadingScreen {
fn render( fn render(
&mut self, &mut self,
draw_handle: &mut RaylibDrawHandle, draw_handle: &mut RaylibDrawHandle,
thread: &RaylibThread, _thread: &RaylibThread,
_audio_system: &mut AudioPlayer, _audio_system: &mut AudioPlayer,
game_core: &mut GameCore, game_core: &mut GameCore,
) -> Option<GameState> { ) -> Option<GameState> {

View File

@ -3,7 +3,6 @@ use raylib::prelude::*;
use crate::{ use crate::{
gamecore::{GameCore, GameState}, gamecore::{GameCore, GameState},
lib::wrappers::audio::player::AudioPlayer, lib::wrappers::audio::player::AudioPlayer,
pallette::WATER_DARK,
}; };
use super::screen::Screen; use super::screen::Screen;
@ -20,8 +19,8 @@ impl Screen for MainMenuScreen {
fn render( fn render(
&mut self, &mut self,
draw_handle: &mut RaylibDrawHandle, draw_handle: &mut RaylibDrawHandle,
thread: &RaylibThread, _thread: &RaylibThread,
audio_system: &mut AudioPlayer, _audio_system: &mut AudioPlayer,
game_core: &mut GameCore, game_core: &mut GameCore,
) -> Option<GameState> { ) -> Option<GameState> {
// Window dimensions // Window dimensions
@ -35,8 +34,8 @@ impl Screen for MainMenuScreen {
// Render title // Render title
draw_handle.draw_text( draw_handle.draw_text(
"PINK MAN SWIM", "ONE BREATH",
(win_height / 2) - 120, (win_height / 2) - 80,
win_width / 8, win_width / 8,
80, 80,
Color::BLACK, Color::BLACK,
@ -55,7 +54,7 @@ impl Screen for MainMenuScreen {
draw_handle.draw_text( draw_handle.draw_text(
"Play", "Play",
(win_height / 2) + 120, (win_height / 2) + 120,
(win_width / 4), win_width / 4,
60, 60,
match hovering_play_button { match hovering_play_button {
true => Color::BLUE, true => Color::BLUE,
@ -96,7 +95,7 @@ impl Screen for MainMenuScreen {
return Some(GameState::InGame); return Some(GameState::InGame);
} else if hovering_shop_button { } else if hovering_shop_button {
return Some(GameState::InShop); return Some(GameState::InShop);
}else if hovering_quit_button { } else if hovering_quit_button {
return Some(GameState::GameQuit); return Some(GameState::GameQuit);
} }
} }

View File

@ -1,10 +1,6 @@
use std::marker::PhantomData;
use raylib::prelude::*;
use crate::{items::ItemBase, player::Player, world::World};
use super::itemui::ShopItemUi; use super::itemui::ShopItemUi;
use crate::{items::ItemBase, player::Player};
use raylib::prelude::*;
pub struct ShopItemWrapper<T: ItemBase + Clone> { pub struct ShopItemWrapper<T: ItemBase + Clone> {
bounds: Rectangle, bounds: Rectangle,
@ -17,7 +13,7 @@ impl<T: ItemBase + Clone> ShopItemWrapper<T> {
item: T, item: T,
from_inventory: &Option<T>, from_inventory: &Option<T>,
first_item_bounds: Rectangle, first_item_bounds: Rectangle,
index: u8 index: u8,
) -> Self { ) -> Self {
// Build new bounds for the UI row // Build new bounds for the UI row
let new_bounds = Rectangle { let new_bounds = Rectangle {
@ -47,7 +43,9 @@ impl<T: ItemBase + Clone> ShopItemWrapper<T> {
} }
pub fn can_player_afford(&self, player: &Player, players_item: &Option<T>) -> bool { pub fn can_player_afford(&self, player: &Player, players_item: &Option<T>) -> bool {
return player.coins >= self.item.get_cost() && ((players_item.is_some() && players_item.as_ref().unwrap().get_level() < 3) || players_item.is_none()); return player.coins >= self.item.get_cost()
&& ((players_item.is_some() && players_item.as_ref().unwrap().get_level() < 3)
|| players_item.is_none());
} }
pub fn purchase(&self, player: &mut Player) -> T { pub fn purchase(&self, player: &mut Player) -> T {
@ -59,14 +57,26 @@ impl<T: ItemBase + Clone> ShopItemWrapper<T> {
} }
pub fn user_clicked_buy(&self, draw_handle: &mut RaylibDrawHandle) -> bool { pub fn user_clicked_buy(&self, draw_handle: &mut RaylibDrawHandle) -> bool {
return self.ui.buy_button_hovered && draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON); return self.ui.buy_button_hovered
&& draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON);
} }
pub fn user_hovering_row(&self, draw_handle: &mut RaylibDrawHandle) -> bool { pub fn user_hovering_row(&self, draw_handle: &mut RaylibDrawHandle) -> bool {
return self.bounds.check_collision_point_rec(draw_handle.get_mouse_position()); return self
.bounds
.check_collision_point_rec(draw_handle.get_mouse_position());
} }
pub fn render(&mut self, draw_handle: &mut RaylibDrawHandle, player: &Player, players_item: &Option<T>) { pub fn render(
self.ui.render(draw_handle, self.bounds, self.can_player_afford(player, players_item)); &mut self,
draw_handle: &mut RaylibDrawHandle,
player: &Player,
players_item: &Option<T>,
) {
self.ui.render(
draw_handle,
self.bounds,
self.can_player_afford(player, players_item),
);
} }
} }

View File

@ -1,17 +1,15 @@
use raylib::prelude::*; use super::item::ShopItemWrapper;
use crate::{ use crate::{
gamecore::{GameCore, GameState}, gamecore::{GameCore, GameState},
items::{AirBag, Flashlight, Flippers, ItemBase, StunGun}, items::{AirBag, Flashlight, Flippers, ItemBase, StunGun},
lib::{utils::button::OnScreenButton, wrappers::audio::player::AudioPlayer}, lib::{utils::button::OnScreenButton, wrappers::audio::player::AudioPlayer},
}; };
use raylib::prelude::*;
use super::{item::ShopItemWrapper, itemui::ShopItemUi};
pub fn render_shop( pub fn render_shop(
draw_handle: &mut RaylibDrawHandle, draw_handle: &mut RaylibDrawHandle,
_thread: &RaylibThread, _thread: &RaylibThread,
audio_system: &mut AudioPlayer, _audio_system: &mut AudioPlayer,
game_core: &mut GameCore, game_core: &mut GameCore,
bounds: Rectangle, bounds: Rectangle,
) -> Option<GameState> { ) -> Option<GameState> {
@ -87,10 +85,26 @@ pub fn render_shop(
); );
// Render items // Render items
stun_gun_buy_ui.render(draw_handle, &game_core.player, &game_core.player.inventory.stun_gun); stun_gun_buy_ui.render(
air_bag_buy_ui.render(draw_handle, &game_core.player, &game_core.player.inventory.air_bag); draw_handle,
flashlight_buy_ui.render(draw_handle, &game_core.player, &game_core.player.inventory.flashlight); &game_core.player,
flippers_buy_ui.render(draw_handle, &game_core.player, &game_core.player.inventory.flippers); &game_core.player.inventory.stun_gun,
);
air_bag_buy_ui.render(
draw_handle,
&game_core.player,
&game_core.player.inventory.air_bag,
);
flashlight_buy_ui.render(
draw_handle,
&game_core.player,
&game_core.player.inventory.flashlight,
);
flippers_buy_ui.render(
draw_handle,
&game_core.player,
&game_core.player.inventory.flippers,
);
// Handle buying items // Handle buying items
if stun_gun_buy_ui.can_player_afford(&game_core.player, &game_core.player.inventory.stun_gun) if stun_gun_buy_ui.can_player_afford(&game_core.player, &game_core.player.inventory.stun_gun)
@ -105,7 +119,8 @@ pub fn render_shop(
let item = air_bag_buy_ui.purchase(&mut game_core.player); let item = air_bag_buy_ui.purchase(&mut game_core.player);
game_core.player.inventory.air_bag = Some(item); game_core.player.inventory.air_bag = Some(item);
} }
if flashlight_buy_ui.can_player_afford(&game_core.player, &game_core.player.inventory.flashlight) if flashlight_buy_ui
.can_player_afford(&game_core.player, &game_core.player.inventory.flashlight)
&& flashlight_buy_ui.user_clicked_buy(draw_handle) && flashlight_buy_ui.user_clicked_buy(draw_handle)
{ {
let item = flashlight_buy_ui.purchase(&mut game_core.player); let item = flashlight_buy_ui.purchase(&mut game_core.player);
@ -151,8 +166,7 @@ pub fn render_shop(
draw_handle.draw_rectangle_rec(box_bounds, Color::WHITE); draw_handle.draw_rectangle_rec(box_bounds, Color::WHITE);
draw_handle.draw_rectangle_lines_ex(box_bounds, 3, Color::BLACK); draw_handle.draw_rectangle_lines_ex(box_bounds, 3, Color::BLACK);
hovered_item.get_texture(
hovered_item.get_texture(
draw_handle, draw_handle,
&game_core.resources, &game_core.resources,
Rectangle { Rectangle {
@ -160,9 +174,8 @@ pub fn render_shop(
y: box_bounds.y + 10.0, y: box_bounds.y + 10.0,
width: (80.0), width: (80.0),
height: (80.0), height: (80.0),
} },
); );
// Render item description // Render item description
draw_handle.draw_text( draw_handle.draw_text(

View File

@ -2,22 +2,16 @@ mod item;
mod itemui; mod itemui;
mod mainui; mod mainui;
use raylib::prelude::*; use self::mainui::{render_shop, render_stats};
use super::screen::Screen;
use crate::{ use crate::{
gamecore::{GameCore, GameState}, gamecore::{GameCore, GameState},
lib::wrappers::audio::player::AudioPlayer, lib::wrappers::audio::player::AudioPlayer,
}; };
use raylib::prelude::*;
use self::mainui::{render_shop, render_stats};
use super::screen::Screen;
const SCREEN_PANEL_SIZE: Vector2 = Vector2 { x: 300.0, y: 380.0 };
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct ShopScreen { pub struct ShopScreen {
// shop_items: Vec<Item>,
} }
impl ShopScreen { impl ShopScreen {
@ -36,8 +30,6 @@ impl Screen for ShopScreen {
audio_system: &mut AudioPlayer, audio_system: &mut AudioPlayer,
game_core: &mut GameCore, game_core: &mut GameCore,
) -> Option<GameState> { ) -> Option<GameState> {
let mouse_position = draw_handle.get_mouse_position();
// Render the background // Render the background
draw_handle.draw_texture(&game_core.resources.shop_background, 0, 0, Color::WHITE); draw_handle.draw_texture(&game_core.resources.shop_background, 0, 0, Color::WHITE);

View File

@ -22,8 +22,8 @@ impl Screen for WinScreen {
fn render( fn render(
&mut self, &mut self,
draw_handle: &mut RaylibDrawHandle, draw_handle: &mut RaylibDrawHandle,
thread: &RaylibThread, _thread: &RaylibThread,
audio_system: &mut AudioPlayer, _audio_system: &mut AudioPlayer,
game_core: &mut GameCore, game_core: &mut GameCore,
) -> Option<GameState> { ) -> Option<GameState> {
let win_height = draw_handle.get_screen_height(); let win_height = draw_handle.get_screen_height();
@ -57,7 +57,8 @@ impl Screen for WinScreen {
// Render message // Render message
draw_handle.draw_text( draw_handle.draw_text(
"You can use the transponder to \ncontact help!", "You can use the transponder to \ncontact help!",
((win_width / 2) - ((SCREEN_PANEL_SIZE.x as i32 + 6) / 2)) + (0.15 * SCREEN_PANEL_SIZE.x)as i32, ((win_width / 2) - ((SCREEN_PANEL_SIZE.x as i32 + 6) / 2))
+ (0.15 * SCREEN_PANEL_SIZE.x) as i32,
(win_height / 2) - (SCREEN_PANEL_SIZE.y as i32 / 2) + 80, (win_height / 2) - (SCREEN_PANEL_SIZE.y as i32 / 2) + 80,
15, 15,
Color::BLACK, Color::BLACK,
@ -87,7 +88,7 @@ impl Screen for WinScreen {
{ {
game_core.switch_state(GameState::MainMenu, Some(draw_handle)); game_core.switch_state(GameState::MainMenu, Some(draw_handle));
} }
return None; return None;
} }
} }

View File

@ -10,16 +10,10 @@ mod world;
use gamecore::{GameCore, GameProgress, GameState}; use gamecore::{GameCore, GameProgress, GameState};
use lib::{utils::profiler::GameProfiler, wrappers::audio::player::AudioPlayer}; use lib::{utils::profiler::GameProfiler, wrappers::audio::player::AudioPlayer};
use log::info;
use logic::{ use logic::{
gameend::GameEndScreen, gameend::GameEndScreen, ingame::InGameScreen, loadingscreen::LoadingScreen,
ingame::InGameScreen, mainmenu::MainMenuScreen, pausemenu::PauseMenuScreen, screen::Screen, shop::ShopScreen,
loadingscreen::LoadingScreen, winscreen::WinScreen,
mainmenu::MainMenuScreen,
pausemenu::PauseMenuScreen,
screen::Screen,
shop::ShopScreen,
winscreen::{self, WinScreen},
}; };
use raylib::prelude::*; use raylib::prelude::*;
use world::{load_world_colliders, World}; use world::{load_world_colliders, World};
@ -33,9 +27,6 @@ const WINDOW_TITLE: &str = r"One Breath";
const MAX_FPS: u32 = 60; const MAX_FPS: u32 = 60;
fn main() { fn main() {
// Configure the logger
env_logger::init();
// Configure a window // Configure a window
let (mut raylib, raylib_thread) = raylib::init() let (mut raylib, raylib_thread) = raylib::init()
.size( .size(
@ -151,7 +142,6 @@ fn main() {
// For now, just quit // For now, just quit
// This also throws a SEGFAULT.. yay for unsafe code.. // This also throws a SEGFAULT.. yay for unsafe code..
info!("User quit game");
unsafe { unsafe {
raylib::ffi::CloseWindow(); raylib::ffi::CloseWindow();
} }

View File

@ -21,27 +21,6 @@ pub const TRANSLUCENT_WHITE_64: Color = Color {
a: 64, a: 64,
}; };
pub const SKY: Color = Color {
r: 15,
g: 193,
b: 217,
a: 255
};
pub const WATER: Color = Color {
r: 24,
g: 66,
b: 143,
a: 255
};
pub const WATER_DARK: Color = Color {
r: 8,
g: 24,
b: 54,
a: 255
};
pub const TRANSLUCENT_RED_64: Color = Color { pub const TRANSLUCENT_RED_64: Color = Color {
r: 230, r: 230,
g: 41, g: 41,

View File

@ -10,9 +10,6 @@ use crate::{
use raylib::prelude::*; use raylib::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
const AOE_RING_MAX_RADIUS: f32 = 60.0;
const STUN_ATTACK_TIME: f64 = 0.75;
#[derive(Debug, Serialize, Deserialize, Default, Clone)] #[derive(Debug, Serialize, Deserialize, Default, Clone)]
pub struct PlayerInventory { pub struct PlayerInventory {
pub stun_gun: Option<StunGun>, pub stun_gun: Option<StunGun>,
@ -74,33 +71,6 @@ impl Player {
} }
pub fn collides_with_rec(&self, rectangle: &Rectangle) -> bool { pub fn collides_with_rec(&self, rectangle: &Rectangle) -> bool {
// // Build a bounding box of the player by their corners
// let top_left_corner = self.position - (self.size / 2.0);
// let bottom_right_corner = self.position + (self.size / 2.0);
// let top_right_corner = Vector2 {
// x: bottom_right_corner.x,
// y: top_left_corner.y,
// };
// let bottom_left_corner = Vector2 {
// x: top_left_corner.x,
// y: bottom_right_corner.y,
// };
// // Get the rotation
// let rotation = Vector2::zero().angle_to(self.direction);
// // Rotate the bounds
// let top_left_corner = rotate_vector(top_left_corner, rotation);
// let bottom_right_corner = rotate_vector(bottom_right_corner, rotation);
// let top_right_corner = rotate_vector(top_right_corner, rotation);
// let bottom_left_corner = rotate_vector(bottom_left_corner, rotation);
// // Check for collisions
// return rectangle.check_collision_point_rec(top_left_corner)
// || rectangle.check_collision_point_rec(bottom_right_corner)
// || rectangle.check_collision_point_rec(top_right_corner)
// || rectangle.check_collision_point_rec(bottom_left_corner);
return rectangle.check_collision_circle_rec(self.position, self.radius); return rectangle.check_collision_circle_rec(self.position, self.radius);
} }

View File

@ -1,5 +1,9 @@
use failure::Error; use raylib::{
use raylib::{RaylibHandle, RaylibThread, math::Vector2, shaders::Shader, texture::{Image, RenderTexture2D, Texture2D}}; math::Vector2,
shaders::Shader,
texture::{Image, RenderTexture2D, Texture2D},
RaylibHandle, RaylibThread,
};
use crate::lib::wrappers::animation::FrameAnimationWrapper; use crate::lib::wrappers::animation::FrameAnimationWrapper;
@ -13,7 +17,7 @@ pub struct GlobalResources {
pub player_animation_boost_charge: FrameAnimationWrapper, pub player_animation_boost_charge: FrameAnimationWrapper,
pub player_animation_boost: FrameAnimationWrapper, pub player_animation_boost: FrameAnimationWrapper,
pub player_animation_stunned: FrameAnimationWrapper, pub player_animation_stunned: FrameAnimationWrapper,
// Fish // Fish
pub fish_animation_idle: FrameAnimationWrapper, pub fish_animation_idle: FrameAnimationWrapper,
pub fish_animation_swim: FrameAnimationWrapper, pub fish_animation_swim: FrameAnimationWrapper,
@ -31,7 +35,7 @@ pub struct GlobalResources {
// Darkness layer // Darkness layer
pub darkness_overlay: Texture2D, pub darkness_overlay: Texture2D,
// Backgrounds // Backgrounds
pub background_front: Texture2D, pub background_front: Texture2D,
pub background_back: Texture2D, pub background_back: Texture2D,
@ -39,25 +43,24 @@ pub struct GlobalResources {
// Shop & items // Shop & items
pub shop_background: Texture2D, pub shop_background: Texture2D,
pub flashlight_one: Texture2D, pub flashlight_one: Texture2D,
pub flashlight_two: Texture2D, pub flashlight_two: Texture2D,
pub flashlight_three: Texture2D, pub flashlight_three: Texture2D,
pub stun_gun_one: Texture2D, pub stun_gun_one: Texture2D,
pub stun_gun_two: Texture2D, pub stun_gun_two: Texture2D,
pub stun_gun_three: Texture2D, pub stun_gun_three: Texture2D,
pub air_one: Texture2D, pub air_one: Texture2D,
pub air_two: Texture2D, pub air_two: Texture2D,
pub air_three: Texture2D, pub air_three: Texture2D,
pub flippers_one: Texture2D, pub flippers_one: Texture2D,
pub flippers_two: Texture2D, pub flippers_two: Texture2D,
pub flippers_three: Texture2D, pub flippers_three: Texture2D,
// Treasure // Treasure
pub transponder: FrameAnimationWrapper, pub transponder: FrameAnimationWrapper,
} }
impl GlobalResources { impl GlobalResources {
@ -130,7 +133,11 @@ impl GlobalResources {
&Image::load_image("./assets/img/map/cave.png")?, &Image::load_image("./assets/img/map/cave.png")?,
)?, )?,
pixel_shader: raylib.load_shader(&thread, None, Some("./assets/shaders/pixel.fs"))?, pixel_shader: raylib.load_shader(&thread, None, Some("./assets/shaders/pixel.fs"))?,
shader_texture: raylib.load_render_texture(&thread, raylib.get_screen_width() as u32, raylib.get_screen_height() as u32)?, shader_texture: raylib.load_render_texture(
&thread,
raylib.get_screen_width() as u32,
raylib.get_screen_height() as u32,
)?,
jellyfish_animation_regular: FrameAnimationWrapper::new( jellyfish_animation_regular: FrameAnimationWrapper::new(
raylib.load_texture_from_image( raylib.load_texture_from_image(
&thread, &thread,
@ -240,7 +247,6 @@ impl GlobalResources {
6, 6,
2, 2,
), ),
}) })
} }
} }

View File

@ -1,11 +1,17 @@
use std::{fs::File, io::BufReader}; use std::{fs::File, io::BufReader};
use failure::Error;
use raylib::math::{Rectangle, Vector2}; use raylib::math::{Rectangle, Vector2};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::io::Read;
use failure::Error;
use crate::{entities::{enemy::{jellyfish::JellyFish, octopus::Octopus, whirlpool::Whirlpool}, fish::FishEntity}, player::Player}; use crate::{
entities::{
enemy::{jellyfish::JellyFish, octopus::Octopus, whirlpool::Whirlpool,},
fish::FishEntity,
},
player::Player,
};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct World { pub struct World {
@ -42,7 +48,7 @@ impl World {
// Init colliders // Init colliders
result.colliders = Vec::new(); result.colliders = Vec::new();
for collider in colliders.iter(){ for collider in colliders.iter() {
result.colliders.push(Rectangle { result.colliders.push(Rectangle {
x: collider.x - (collider.width / 2.0), x: collider.x - (collider.width / 2.0),
y: collider.y - (collider.height / 2.0), y: collider.y - (collider.height / 2.0),
@ -71,7 +77,6 @@ impl World {
} }
} }
pub fn load_world_colliders(file: String) -> Result<Vec<Rectangle>, Error> { pub fn load_world_colliders(file: String) -> Result<Vec<Rectangle>, Error> {
// Load the file // Load the file
let file = File::open(file)?; let file = File::open(file)?;
@ -79,4 +84,4 @@ pub fn load_world_colliders(file: String) -> Result<Vec<Rectangle>, Error> {
// Deserialize // Deserialize
Ok(serde_json::from_reader(reader)?) Ok(serde_json::from_reader(reader)?)
} }