Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c59e6434c1 | ||
|
8a174918c8 | ||
|
69efde83a8 | ||
|
7a481421f6 | ||
|
e6b8d4f407 | ||
|
315a487cdf | ||
|
eedc1c5966 | ||
|
f77a8755b8 | ||
|
2628c0d740 | ||
|
2844e5ac0b |
File diff suppressed because one or more lines are too long
@ -1,14 +1,7 @@
|
|||||||
use raylib::prelude::*;
|
|
||||||
|
|
||||||
use crate::{player::Player, resources::GlobalResources};
|
|
||||||
|
|
||||||
pub trait EnemyBase {
|
pub trait EnemyBase {
|
||||||
fn render(
|
fn render();
|
||||||
&mut self,
|
fn handle_logic();
|
||||||
context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
|
fn handle_getting_attacked();
|
||||||
resources: &mut GlobalResources,
|
|
||||||
dt: f64,
|
|
||||||
);
|
|
||||||
fn handle_logic(&mut self, player: &mut Player, dt: f64);
|
|
||||||
fn handle_getting_attacked(&mut self, stun_duration: f64);
|
|
||||||
}
|
}
|
@ -1,2 +1 @@
|
|||||||
pub mod base;
|
pub mod base;
|
||||||
pub mod jellyfish;
|
|
123
src/items.rs
123
src/items.rs
@ -10,22 +10,68 @@ impl StunGun {
|
|||||||
pub fn lvl1() -> Self {
|
pub fn lvl1() -> Self {
|
||||||
Self {
|
Self {
|
||||||
range: 30.0,
|
range: 30.0,
|
||||||
duration: 0.75,
|
duration: 0.5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn lvl2() -> Self {
|
pub fn lvl2() -> Self {
|
||||||
Self {
|
Self {
|
||||||
range: 60.0,
|
range: 60.0,
|
||||||
duration: 1.25,
|
duration: 0.75,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn lvl3() -> Self {
|
||||||
|
Self {
|
||||||
|
range: 80.0,
|
||||||
|
duration: 1.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
pub struct AirBag;
|
pub struct AirBag{
|
||||||
|
extra_oxygen: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AirBag {
|
||||||
|
pub fn lvl1() -> Self {
|
||||||
|
Self {
|
||||||
|
extra_oxygen: 15,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn lvl2() -> Self {
|
||||||
|
Self {
|
||||||
|
extra_oxygen: 30,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn lvl3() -> Self {
|
||||||
|
Self {
|
||||||
|
extra_oxygen: 45,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
pub struct Flashlight;
|
pub struct Flashlight{
|
||||||
|
power_level: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Flashlight{
|
||||||
|
pub fn lvl1() -> Self {
|
||||||
|
Self {
|
||||||
|
power_level: 0.25,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn lvl2() -> Self {
|
||||||
|
Self {
|
||||||
|
power_level: 0.5,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn lvl3() -> Self {
|
||||||
|
Self {
|
||||||
|
power_level: 1.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
pub struct Flippers {
|
pub struct Flippers {
|
||||||
@ -43,4 +89,73 @@ impl Flippers {
|
|||||||
speed_increase: 1.5
|
speed_increase: 1.5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn lvl3() -> Self {
|
||||||
|
Self {
|
||||||
|
speed_increase: 1.8
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "t", content = "c")]
|
||||||
|
pub enum ShopItems {
|
||||||
|
StunGun(u8, u8, String),
|
||||||
|
AirBag(u8, u8, String),
|
||||||
|
Flashlight(u8, u8, String),
|
||||||
|
Flippers(u8, u8, String)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShopItems{
|
||||||
|
|
||||||
|
pub fn get_inital_items() -> [ShopItems; 4]{
|
||||||
|
|
||||||
|
[ShopItems::StunGun(0, 5, String::from("Stun Gun")), ShopItems::AirBag(0, 5, String::from("Air Bag")),
|
||||||
|
ShopItems::Flashlight(0, 5, String::from("Flash Light")), ShopItems::Flippers(0, 5, String::from("Flippers"))]
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_level(item: &ShopItems) -> u8{
|
||||||
|
|
||||||
|
|
||||||
|
match item {
|
||||||
|
ShopItems::StunGun(x, _, _) => *x,
|
||||||
|
ShopItems::AirBag(x, _, _) => *x,
|
||||||
|
ShopItems::Flashlight(x, _, _) => *x,
|
||||||
|
ShopItems::Flippers(x, _, _) => *x
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn get_cost(item: &ShopItems) -> u8{
|
||||||
|
|
||||||
|
match item {
|
||||||
|
ShopItems::StunGun(_, x, _) => *x,
|
||||||
|
ShopItems::AirBag(_, x, _) => *x,
|
||||||
|
ShopItems::Flashlight(_, x, _) => *x,
|
||||||
|
ShopItems::Flippers(_, x, _) => *x
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_name(item: &ShopItems) -> String{
|
||||||
|
|
||||||
|
match item {
|
||||||
|
ShopItems::StunGun(_, _, x) => x.to_string(),
|
||||||
|
ShopItems::AirBag(_, _, x) => x.to_string(),
|
||||||
|
ShopItems::Flashlight(_, _, x) => x.to_string(),
|
||||||
|
ShopItems::Flippers(_, _, x) => x.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use raylib::{core::color::Color, math::{Rectangle, Vector2}, prelude::{RaylibDra
|
|||||||
|
|
||||||
/// A wrapper around an animation spritesheet
|
/// A wrapper around an animation spritesheet
|
||||||
pub struct FrameAnimationWrapper {
|
pub struct FrameAnimationWrapper {
|
||||||
pub sprite_sheet: Texture2D,
|
sprite_sheet: Texture2D,
|
||||||
size: Vector2,
|
size: Vector2,
|
||||||
frame_count: u32,
|
frame_count: u32,
|
||||||
frames_per_second: u8,
|
frames_per_second: u8,
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
mod hud;
|
mod hud;
|
||||||
mod playerlogic;
|
mod playerlogic;
|
||||||
|
mod shop;
|
||||||
|
|
||||||
use raylib::prelude::*;
|
use raylib::prelude::*;
|
||||||
|
|
||||||
|
use crate::{gamecore::{self, GameCore, GameState}, lib::wrappers::audio::player::AudioPlayer};
|
||||||
|
|
||||||
|
use self::shop::Shop;
|
||||||
use crate::{
|
use crate::{
|
||||||
entities::enemy::base::EnemyBase,
|
pallette::{WATER},
|
||||||
gamecore::{GameCore, GameState},
|
|
||||||
lib::wrappers::audio::player::AudioPlayer,
|
|
||||||
pallette::{SKY, WATER},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::screen::Screen;
|
use super::screen::Screen;
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
pub enum InGameState {
|
pub enum InGameState {
|
||||||
BUYING,
|
BUYING,
|
||||||
SWIMMING,
|
SWIMMING,
|
||||||
@ -19,12 +21,14 @@ pub enum InGameState {
|
|||||||
|
|
||||||
pub struct InGameScreen {
|
pub struct InGameScreen {
|
||||||
current_state: InGameState,
|
current_state: InGameState,
|
||||||
|
shop: Shop,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InGameScreen {
|
impl InGameScreen {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
current_state: InGameState::SWIMMING,
|
current_state: InGameState::BUYING,
|
||||||
|
shop: Shop::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +36,6 @@ impl InGameScreen {
|
|||||||
&mut self,
|
&mut self,
|
||||||
context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
|
context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
|
||||||
game_core: &mut GameCore,
|
game_core: &mut GameCore,
|
||||||
dt: f64
|
|
||||||
) {
|
) {
|
||||||
// Build source bounds
|
// Build source bounds
|
||||||
let source_bounds = Rectangle {
|
let source_bounds = Rectangle {
|
||||||
@ -51,13 +54,6 @@ impl InGameScreen {
|
|||||||
// Clear the background
|
// Clear the background
|
||||||
context_2d.draw_rectangle_rec(world_bounds, WATER);
|
context_2d.draw_rectangle_rec(world_bounds, WATER);
|
||||||
|
|
||||||
// Render fish
|
|
||||||
let fish_clone = game_core.world.fish.clone();
|
|
||||||
for fish in game_core.world.fish.iter_mut() {
|
|
||||||
fish.update_position(&mut game_core.player, dt, &fish_clone);
|
|
||||||
fish.render(context_2d);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the world texture
|
// Render the world texture
|
||||||
context_2d.draw_texture_rec(
|
context_2d.draw_texture_rec(
|
||||||
&game_core.resources.cave_mid_layer,
|
&game_core.resources.cave_mid_layer,
|
||||||
@ -77,7 +73,11 @@ impl InGameScreen {
|
|||||||
) {
|
) {
|
||||||
// Render every collider
|
// Render every collider
|
||||||
for collider in game_core.world.colliders.iter() {
|
for collider in game_core.world.colliders.iter() {
|
||||||
context_2d.draw_rectangle_lines_ex(collider, 1, Color::RED);
|
context_2d.draw_rectangle_lines_ex(
|
||||||
|
collider,
|
||||||
|
1,
|
||||||
|
Color::RED,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,6 +93,22 @@ impl Screen for InGameScreen {
|
|||||||
// Calculate DT
|
// Calculate DT
|
||||||
let dt = draw_handle.get_time() - game_core.last_frame_time;
|
let dt = draw_handle.get_time() - game_core.last_frame_time;
|
||||||
|
|
||||||
|
// Window dimensions
|
||||||
|
let win_height = draw_handle.get_screen_height();
|
||||||
|
let win_width = draw_handle.get_screen_width();
|
||||||
|
let window_center = Vector2 {
|
||||||
|
x: (win_width as f32 / 2.0),
|
||||||
|
y: (win_height as f32 / 2.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Creates items for shop
|
||||||
|
if draw_handle.get_time() - game_core.last_state_change_time <= 0.05{
|
||||||
|
self.shop.create_items(Vector2::new(win_width as f32, win_height as f32));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Clear frame
|
// Clear frame
|
||||||
draw_handle.clear_background(Color::BLACK);
|
draw_handle.clear_background(Color::BLACK);
|
||||||
|
|
||||||
@ -110,34 +126,48 @@ impl Screen for InGameScreen {
|
|||||||
};
|
};
|
||||||
let camera_window_center = window_center * (1.0 / game_core.master_camera.zoom);
|
let camera_window_center = window_center * (1.0 / game_core.master_camera.zoom);
|
||||||
|
|
||||||
// Update player movement
|
|
||||||
playerlogic::update_player_movement(draw_handle, game_core, window_center);
|
|
||||||
|
|
||||||
// Open a 2D context
|
// Open a 2D context
|
||||||
{
|
{
|
||||||
let mut context_2d = draw_handle.begin_mode2D(game_core.master_camera);
|
let mut context_2d = draw_handle.begin_mode2D(game_core.master_camera);
|
||||||
|
|
||||||
// Render the world
|
// Render the world
|
||||||
self.render_world(&mut context_2d, game_core, dt);
|
self.render_world(&mut context_2d, game_core);
|
||||||
if game_core.show_simple_debug_info{
|
if game_core.show_simple_debug_info{
|
||||||
self.render_colliders(&mut context_2d, game_core);
|
self.render_colliders(&mut context_2d, game_core);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render entities
|
// Render entities
|
||||||
for jellyfish in game_core.world.jellyfish.iter_mut() {
|
let fish_clone = game_core.world.fish.clone();
|
||||||
jellyfish.handle_logic(&mut game_core.player, dt);
|
for fish in game_core.world.fish.iter_mut() {
|
||||||
jellyfish.render(&mut context_2d, &mut game_core.resources, dt);
|
fish.update_position(&mut game_core.player, dt, &fish_clone);
|
||||||
|
fish.render(&mut context_2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render Player
|
// Render Player
|
||||||
game_core
|
// playerlogic::render_player(&mut context_2d, game_core);
|
||||||
.player
|
game_core.player.render(&mut context_2d, &mut game_core.resources, dt);
|
||||||
.render(&mut context_2d, &mut game_core.resources, dt);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Only render shop in shop period, otherwise allow player movement
|
||||||
|
if draw_handle.get_time() - game_core.last_state_change_time >= 0.05
|
||||||
|
&& self.current_state == InGameState::BUYING{
|
||||||
|
|
||||||
|
shop::render_shop(draw_handle, game_core, self);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
// Update player movement
|
||||||
|
playerlogic::update_player_movement(draw_handle, game_core, window_center);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the hud
|
// Render the hud
|
||||||
hud::render_hud(draw_handle, game_core, window_center);
|
hud::render_hud(draw_handle, game_core, window_center);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Handle player out of breath
|
// Handle player out of breath
|
||||||
if game_core.player.breath_percent == 0.0 {
|
if game_core.player.breath_percent == 0.0 {
|
||||||
return Some(GameState::GameEnd);
|
return Some(GameState::GameEnd);
|
||||||
|
@ -5,13 +5,13 @@ use crate::{
|
|||||||
pallette::{TRANSLUCENT_WHITE_128, TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96},
|
pallette::{TRANSLUCENT_WHITE_128, TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96},
|
||||||
};
|
};
|
||||||
|
|
||||||
const NORMAL_PLAYER_SPEED: i32 = 1;
|
const NORMAL_PLAYER_SPEED: i32 = 3;
|
||||||
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 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;
|
||||||
const BREATH_DECREASE_PER_SECOND: f32 = 0.02;
|
const BREATH_DECREASE_PER_SECOND: f32 = 0.01;
|
||||||
|
|
||||||
pub fn update_player_movement(
|
pub fn update_player_movement(
|
||||||
draw_handle: &mut RaylibDrawHandle,
|
draw_handle: &mut RaylibDrawHandle,
|
||||||
@ -65,9 +65,7 @@ pub fn update_player_movement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set angle
|
// set angle
|
||||||
if !game_core.player.is_stunned() {
|
|
||||||
game_core.player.direction = Vector2::new(f32::cos(player_angle), f32::sin(player_angle));
|
game_core.player.direction = Vector2::new(f32::cos(player_angle), f32::sin(player_angle));
|
||||||
}
|
|
||||||
|
|
||||||
// In the case the player is in "null", just jump the camera to them
|
// In the case the player is in "null", just jump the camera to them
|
||||||
if game_core.player.position == Vector2::zero() {
|
if game_core.player.position == Vector2::zero() {
|
||||||
@ -79,11 +77,11 @@ 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);
|
game_core.player.begin_attack();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the player in their direction
|
// Move the player in their direction
|
||||||
let mut speed_multiplier;
|
let speed_multiplier;
|
||||||
if user_request_boost && game_core.player.boost_percent >= 0.0 {
|
if user_request_boost && game_core.player.boost_percent >= 0.0 {
|
||||||
// Set the speed multiplier
|
// Set the speed multiplier
|
||||||
speed_multiplier = BOOST_PLAYER_SPEED as f32;
|
speed_multiplier = BOOST_PLAYER_SPEED as f32;
|
||||||
@ -130,14 +128,7 @@ pub fn update_player_movement(
|
|||||||
|
|
||||||
// Handle flippers doing a speed increase
|
// Handle flippers doing a speed increase
|
||||||
if game_core.player.inventory.flippers.is_some() {
|
if game_core.player.inventory.flippers.is_some() {
|
||||||
speed_multiplier = speed_multiplier
|
let speed_multiplier = speed_multiplier * game_core.player.inventory.flippers.as_ref().unwrap().speed_increase;
|
||||||
* game_core
|
|
||||||
.player
|
|
||||||
.inventory
|
|
||||||
.flippers
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.speed_increase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the player's breath
|
// Update the player's breath
|
||||||
@ -145,42 +136,31 @@ pub fn update_player_movement(
|
|||||||
(game_core.player.breath_percent - BREATH_DECREASE_PER_SECOND * dt as f32).clamp(0.0, 1.0);
|
(game_core.player.breath_percent - BREATH_DECREASE_PER_SECOND * dt as f32).clamp(0.0, 1.0);
|
||||||
|
|
||||||
// Only do this if the mouse is far enough away
|
// Only do this if the mouse is far enough away
|
||||||
|
let player_real_movement = game_core.player.direction * speed_multiplier;
|
||||||
let player_stunned = game_core.player.stun_timer > 0.0;
|
let player_stunned = game_core.player.stun_timer > 0.0;
|
||||||
let mut player_real_movement = game_core.player.direction * speed_multiplier;
|
if raw_movement_direction.distance_to(Vector2::zero()) > game_core.player.size.y / 2.0 || player_stunned{
|
||||||
if raw_movement_direction.distance_to(Vector2::zero()) > game_core.player.size.y / 2.0
|
game_core.player.is_moving = true;
|
||||||
&& !game_core.player.is_stunned()
|
game_core.player.position += player_real_movement;
|
||||||
{
|
|
||||||
if game_core.player.is_moving {
|
|
||||||
// move in x
|
|
||||||
game_core.player.position.x += player_real_movement.x;
|
|
||||||
|
|
||||||
// Check for any collisions
|
// Check for any collisions
|
||||||
for collider in game_core.world.colliders.iter() {
|
for collider in game_core.world.colliders.iter() {
|
||||||
if game_core.player.collides_with_rec(collider) {
|
if game_core.player.collides_with_rec(collider) {
|
||||||
game_core.player.position.x -= player_real_movement.x;
|
game_core.player.is_moving = false;
|
||||||
player_real_movement.x = 0.0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// move in y
|
if !game_core.player.is_moving {
|
||||||
game_core.player.position.y += player_real_movement.y;
|
game_core.player.position -= player_real_movement;
|
||||||
|
|
||||||
// Check for any collisions
|
|
||||||
for collider in game_core.world.colliders.iter() {
|
|
||||||
if game_core.player.collides_with_rec(collider) {
|
|
||||||
game_core.player.position.y -= player_real_movement.y;
|
|
||||||
player_real_movement.y = 0.0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
game_core.player.is_moving = false;
|
||||||
|
|
||||||
// Handle updating the stun timer
|
// Handle updating the stun timer
|
||||||
if player_stunned {
|
if player_stunned {
|
||||||
game_core.player.stun_timer -= dt;
|
game_core.player.stun_timer -= dt;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Move the camera to follow the player
|
// Move the camera to follow the player
|
||||||
let direction_from_cam_to_player =
|
let direction_from_cam_to_player =
|
||||||
@ -203,3 +183,4 @@ pub fn update_player_movement(
|
|||||||
// game_core.master_camera.target.y = -100.0;
|
// game_core.master_camera.target.y = -100.0;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
205
src/logic/ingame/shop.rs
Normal file
205
src/logic/ingame/shop.rs
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
use std::u8;
|
||||||
|
|
||||||
|
use raylib::prelude::*;
|
||||||
|
|
||||||
|
use crate::{gamecore::GameCore, items, items::ShopItems};
|
||||||
|
|
||||||
|
use super::{InGameScreen, InGameState};
|
||||||
|
|
||||||
|
pub struct Item {
|
||||||
|
x_pose: i32,
|
||||||
|
y_pose: i32,
|
||||||
|
width: i32,
|
||||||
|
height: i32,
|
||||||
|
cost: u8,
|
||||||
|
level: u8,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Shop {
|
||||||
|
shop_items: Vec<Item>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shop {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
shop_items: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates all the items
|
||||||
|
pub fn create_items(&mut self, screen_dimension: Vector2) {
|
||||||
|
// gets every item.. hacky
|
||||||
|
let items = ShopItems::get_inital_items();
|
||||||
|
|
||||||
|
// sets sizes any random number is just a number I think looks good
|
||||||
|
let screen_width = screen_dimension.x as f32;
|
||||||
|
let screen_height = screen_dimension.y as f32;
|
||||||
|
|
||||||
|
let box_height = screen_height * 0.15;
|
||||||
|
let box_width = screen_width * 0.1;
|
||||||
|
|
||||||
|
let start_width = screen_width - (box_width * 4.0) - 40.0;
|
||||||
|
let draw_height = screen_height - 20.0 - box_height;
|
||||||
|
|
||||||
|
let mut item_vec = Vec::new();
|
||||||
|
|
||||||
|
for box_num in 0..4 {
|
||||||
|
let x_pose = start_width + box_width * box_num as f32;
|
||||||
|
|
||||||
|
// adds an item struct to the item list
|
||||||
|
item_vec.push(Item {
|
||||||
|
x_pose: ((x_pose + (5 * box_num) as f32) as i32),
|
||||||
|
y_pose: (draw_height as i32),
|
||||||
|
width: (box_width as i32),
|
||||||
|
height: (box_height as i32),
|
||||||
|
// Crazy hacky but this gets the data from the enum
|
||||||
|
cost: (ShopItems::get_cost(&items.get(box_num).unwrap())),
|
||||||
|
level: (ShopItems::get_level(&items.get(box_num).unwrap())),
|
||||||
|
name: (ShopItems::get_name(&items.get(box_num).unwrap())),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.shop_items = item_vec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_shop(
|
||||||
|
draw_handle: &mut RaylibDrawHandle,
|
||||||
|
game_core: &mut GameCore,
|
||||||
|
inGameScreen: &mut InGameScreen,
|
||||||
|
) {
|
||||||
|
// Pressing F exits from buying
|
||||||
|
if draw_handle.is_key_pressed(KeyboardKey::KEY_F) {
|
||||||
|
inGameScreen.current_state = InGameState::SWIMMING;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mouse_position = draw_handle.get_mouse_position();
|
||||||
|
|
||||||
|
draw_handle.draw_text(
|
||||||
|
&format!("Coins: {}", game_core.player.coins),
|
||||||
|
15,
|
||||||
|
15,
|
||||||
|
30,
|
||||||
|
Color::WHITE,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Draws shop boxes
|
||||||
|
for mut item in inGameScreen.shop.shop_items.iter_mut() {
|
||||||
|
|
||||||
|
|
||||||
|
// If hovering on square draw full
|
||||||
|
if mouse_position.x >= item.x_pose as f32
|
||||||
|
&& mouse_position.x <= item.x_pose as f32 + item.width as f32
|
||||||
|
&& mouse_position.y >= item.y_pose as f32
|
||||||
|
&& mouse_position.y <= item.y_pose as f32 + item.width as f32
|
||||||
|
{
|
||||||
|
// Draw rect
|
||||||
|
draw_handle.draw_rectangle(
|
||||||
|
item.x_pose,
|
||||||
|
item.y_pose,
|
||||||
|
item.width,
|
||||||
|
item.height,
|
||||||
|
Color::BLACK,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Preform purchasing functions
|
||||||
|
if draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON)
|
||||||
|
&& game_core.player.coins >= item.cost as u32
|
||||||
|
{
|
||||||
|
|
||||||
|
// Remove currency
|
||||||
|
game_core.world.spend_coins(item.cost.into());
|
||||||
|
game_core.player.coins -= item.cost as u32;
|
||||||
|
|
||||||
|
// Upgrade item in inventory
|
||||||
|
match &(item.name)[..] {
|
||||||
|
"Stun Gun" => {
|
||||||
|
match item.level {
|
||||||
|
0 => {
|
||||||
|
game_core.player.inventory.stun_gun = Some(items::StunGun::lvl1())
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
game_core.player.inventory.stun_gun = Some(items::StunGun::lvl2())
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
game_core.player.inventory.stun_gun = Some(items::StunGun::lvl3())
|
||||||
|
}
|
||||||
|
_ => (return),
|
||||||
|
};
|
||||||
|
item.cost += 5;
|
||||||
|
item.level += 1;
|
||||||
|
}
|
||||||
|
"Air Bag" => {
|
||||||
|
match item.level {
|
||||||
|
0 => {
|
||||||
|
game_core.player.inventory.air_bag = Some(items::AirBag::lvl1());
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
game_core.player.inventory.air_bag = Some(items::AirBag::lvl2());
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
game_core.player.inventory.air_bag = Some(items::AirBag::lvl3());
|
||||||
|
}
|
||||||
|
_ => (return),
|
||||||
|
};
|
||||||
|
item.cost += 5;
|
||||||
|
item.level += 1;
|
||||||
|
}
|
||||||
|
"Flash Light" => {
|
||||||
|
match item.level {
|
||||||
|
0 => {
|
||||||
|
game_core.player.inventory.flashlight = Some(items::Flashlight::lvl1());
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
game_core.player.inventory.flashlight = Some(items::Flashlight::lvl2());
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
game_core.player.inventory.flashlight = Some(items::Flashlight::lvl3());
|
||||||
|
}
|
||||||
|
_ => (return),
|
||||||
|
};
|
||||||
|
item.cost += 5;
|
||||||
|
item.level += 1;
|
||||||
|
},
|
||||||
|
"Flippers" => {
|
||||||
|
match item.level {
|
||||||
|
0 => {
|
||||||
|
game_core.player.inventory.flippers = Some(items::Flippers::lvl1());
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
game_core.player.inventory.flippers = Some(items::Flippers::lvl2());
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
game_core.player.inventory.flippers = Some(items::Flippers::lvl3());
|
||||||
|
}
|
||||||
|
_ => (return),
|
||||||
|
};
|
||||||
|
item.cost += 5;
|
||||||
|
item.level += 1;
|
||||||
|
},
|
||||||
|
_ => (return),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// outlines if not hovered
|
||||||
|
draw_handle.draw_rectangle_lines(
|
||||||
|
item.x_pose,
|
||||||
|
item.y_pose,
|
||||||
|
item.width,
|
||||||
|
item.height,
|
||||||
|
Color::BLACK,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Draw text about object
|
||||||
|
draw_handle.draw_text(
|
||||||
|
&format!("{}: ${}", item.name, item.cost),
|
||||||
|
item.x_pose + 5,
|
||||||
|
item.y_pose + 5,
|
||||||
|
12,
|
||||||
|
Color::BLACK,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -34,10 +34,3 @@ pub const WATER: Color = Color {
|
|||||||
b: 143,
|
b: 143,
|
||||||
a: 255
|
a: 255
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const TRANSLUCENT_RED_64: Color = Color {
|
|
||||||
r: 230,
|
|
||||||
g: 41,
|
|
||||||
b: 55,
|
|
||||||
a: 64,
|
|
||||||
};
|
|
@ -1,14 +1,6 @@
|
|||||||
use crate::{
|
|
||||||
entities::enemy::base::EnemyBase,
|
|
||||||
gamecore::{GameCore, GameProgress},
|
|
||||||
items::{AirBag, Flashlight, Flippers, StunGun},
|
|
||||||
lib::utils::calculate_linear_slide,
|
|
||||||
pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96},
|
|
||||||
resources::GlobalResources,
|
|
||||||
world::World,
|
|
||||||
};
|
|
||||||
use raylib::prelude::*;
|
use raylib::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
use crate::{gamecore::{GameCore, GameProgress}, items::{AirBag, Flashlight, Flippers, StunGun}, lib::utils::{calculate_linear_slide}, pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96}, resources::GlobalResources, world::World};
|
||||||
|
|
||||||
const AOE_RING_MAX_RADIUS: f32 = 60.0;
|
const AOE_RING_MAX_RADIUS: f32 = 60.0;
|
||||||
const STUN_ATTACK_TIME: f64 = 0.75;
|
const STUN_ATTACK_TIME: f64 = 0.75;
|
||||||
@ -18,16 +10,7 @@ pub struct PlayerInventory {
|
|||||||
pub stun_gun: Option<StunGun>,
|
pub stun_gun: Option<StunGun>,
|
||||||
pub air_bag: Option<AirBag>,
|
pub air_bag: Option<AirBag>,
|
||||||
pub flashlight: Option<Flashlight>,
|
pub flashlight: Option<Flashlight>,
|
||||||
pub flippers: Option<Flippers>,
|
pub flippers: Option<Flippers>
|
||||||
}
|
|
||||||
|
|
||||||
impl PlayerInventory {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
stun_gun: Some(StunGun::lvl1()), //TMP
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -35,7 +18,6 @@ pub struct Player {
|
|||||||
pub position: Vector2,
|
pub position: Vector2,
|
||||||
pub direction: Vector2,
|
pub direction: Vector2,
|
||||||
pub size: Vector2,
|
pub size: Vector2,
|
||||||
pub radius: f32,
|
|
||||||
pub coins: u32,
|
pub coins: u32,
|
||||||
pub boost_percent: f32,
|
pub boost_percent: f32,
|
||||||
pub breath_percent: f32,
|
pub breath_percent: f32,
|
||||||
@ -53,10 +35,7 @@ impl Player {
|
|||||||
boost_percent: 1.0,
|
boost_percent: 1.0,
|
||||||
size: Vector2 { x: 11.0, y: 21.0 },
|
size: Vector2 { x: 11.0, y: 21.0 },
|
||||||
breath_percent: 1.0,
|
breath_percent: 1.0,
|
||||||
is_moving: true,
|
|
||||||
radius: 4.5,
|
|
||||||
position: spawn.clone(),
|
position: spawn.clone(),
|
||||||
inventory: PlayerInventory::new(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,7 +68,7 @@ impl Player {
|
|||||||
// || rectangle.check_collision_point_rec(top_right_corner)
|
// || rectangle.check_collision_point_rec(top_right_corner)
|
||||||
// || rectangle.check_collision_point_rec(bottom_left_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.size.y * 0.5) / 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stun the player
|
/// Stun the player
|
||||||
@ -98,28 +77,11 @@ impl Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Try to attack with the stun gun
|
/// Try to attack with the stun gun
|
||||||
pub fn begin_attack(&mut self, world: &mut World) {
|
pub fn begin_attack(&mut self) {
|
||||||
if self.inventory.stun_gun.is_some() && !self.is_stunned() {
|
if self.inventory.stun_gun.is_some() && self.stun_timer == 0.0 {
|
||||||
self.attacking_timer = self.inventory.stun_gun.as_ref().unwrap().duration;
|
self.attacking_timer = self.inventory.stun_gun.as_ref().unwrap().duration;
|
||||||
|
|
||||||
// Stun everything in reach
|
|
||||||
let stun_reach = self.inventory.stun_gun.as_ref().unwrap().range;
|
|
||||||
|
|
||||||
for jellyfish in world.jellyfish.iter_mut() {
|
|
||||||
if jellyfish.position.distance_to(self.position).abs() <= stun_reach {
|
|
||||||
jellyfish.handle_getting_attacked(self.attacking_timer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_stun_gun_active(&self) -> bool {
|
|
||||||
return self.attacking_timer != 0.0 && self.inventory.stun_gun.is_some();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_stunned(&self) -> bool {
|
|
||||||
return self.stun_timer > 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calculate how far the player is
|
/// Calculate how far the player is
|
||||||
pub fn calculate_depth_percent(&self, world: &World) -> f32 {
|
pub fn calculate_depth_percent(&self, world: &World) -> f32 {
|
||||||
@ -172,38 +134,21 @@ impl Player {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Calculate AOE ring
|
// Calculate AOE ring
|
||||||
if self.is_stun_gun_active() {
|
if self.attacking_timer != 0.0 && self.inventory.stun_gun.is_some() {
|
||||||
let animation_progression =
|
let aoe_ring = calculate_linear_slide( self.attacking_timer / self.inventory.stun_gun.as_ref().unwrap().duration) as f32;
|
||||||
self.attacking_timer / self.inventory.stun_gun.as_ref().unwrap().duration;
|
|
||||||
let aoe_ring = calculate_linear_slide(animation_progression) as f32;
|
|
||||||
self.attacking_timer = (self.attacking_timer - dt).max(0.0);
|
self.attacking_timer = (self.attacking_timer - dt).max(0.0);
|
||||||
|
|
||||||
// Render attack AOE
|
// Render attack AOE
|
||||||
if animation_progression >= 0.5 {
|
|
||||||
context_2d.draw_circle_lines(
|
context_2d.draw_circle_lines(
|
||||||
self.position.x as i32,
|
self.position.x as i32,
|
||||||
self.position.y as i32,
|
self.position.y as i32,
|
||||||
self.inventory.stun_gun.as_ref().unwrap().range * aoe_ring,
|
self.inventory.stun_gun.as_ref().unwrap().range * aoe_ring,
|
||||||
TRANSLUCENT_WHITE_64.fade(aoe_ring),
|
TRANSLUCENT_WHITE_64,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
context_2d.draw_circle_lines(
|
|
||||||
self.position.x as i32,
|
|
||||||
self.position.y as i32,
|
|
||||||
self.inventory.stun_gun.as_ref().unwrap().range,
|
|
||||||
TRANSLUCENT_WHITE_64.fade(aoe_ring),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the player based on what is happening
|
// Render the player based on what is happening
|
||||||
if self.is_stunned() {
|
if self.is_boost_charging {
|
||||||
resources.player_animation_stunned.draw(
|
|
||||||
context_2d,
|
|
||||||
self.position,
|
|
||||||
player_rotation.to_degrees() - 90.0,
|
|
||||||
);
|
|
||||||
} else if self.is_boost_charging {
|
|
||||||
resources.player_animation_boost_charge.draw(
|
resources.player_animation_boost_charge.draw(
|
||||||
context_2d,
|
context_2d,
|
||||||
self.position,
|
self.position,
|
||||||
|
@ -16,14 +16,9 @@ pub struct GlobalResources {
|
|||||||
pub player_animation_regular: FrameAnimationWrapper,
|
pub player_animation_regular: FrameAnimationWrapper,
|
||||||
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,
|
|
||||||
|
|
||||||
// Cave
|
// Cave
|
||||||
pub cave_mid_layer: Texture2D,
|
pub cave_mid_layer: Texture2D
|
||||||
|
|
||||||
// Enemies
|
|
||||||
pub jellyfish_animation_regular: FrameAnimationWrapper,
|
|
||||||
pub jellyfish_animation_attack: FrameAnimationWrapper,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalResources {
|
impl GlobalResources {
|
||||||
@ -64,37 +59,10 @@ impl GlobalResources {
|
|||||||
21,
|
21,
|
||||||
30,
|
30,
|
||||||
),
|
),
|
||||||
player_animation_stunned: FrameAnimationWrapper::new(
|
|
||||||
raylib.load_texture_from_image(
|
|
||||||
&thread,
|
|
||||||
&Image::load_image("./assets/img/character/stunned.png")?,
|
|
||||||
)?,
|
|
||||||
Vector2 { x: 12.0, y: 22.0 },
|
|
||||||
4,
|
|
||||||
100 / 8,
|
|
||||||
),
|
|
||||||
cave_mid_layer: raylib.load_texture_from_image(
|
cave_mid_layer: raylib.load_texture_from_image(
|
||||||
&thread,
|
&thread,
|
||||||
&Image::load_image("./assets/img/map/cave.png")?,
|
&Image::load_image("./assets/img/map/cave.png")?,
|
||||||
)?,
|
)?,
|
||||||
jellyfish_animation_regular: FrameAnimationWrapper::new(
|
|
||||||
raylib.load_texture_from_image(
|
|
||||||
&thread,
|
|
||||||
&Image::load_image("./assets/img/enemies/jelly.png")?,
|
|
||||||
)?,
|
|
||||||
Vector2 { x: 10.0, y: 10.0 },
|
|
||||||
6,
|
|
||||||
4,
|
|
||||||
),
|
|
||||||
jellyfish_animation_attack: FrameAnimationWrapper::new(
|
|
||||||
raylib.load_texture_from_image(
|
|
||||||
&thread,
|
|
||||||
&Image::load_image("./assets/img/enemies/jellyAttack.png")?,
|
|
||||||
)?,
|
|
||||||
Vector2 { x: 20.0, y: 20.0 },
|
|
||||||
15,
|
|
||||||
4,
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
use crate::entities::{enemy::jellyfish::JellyFish, fish::FishEntity};
|
use crate::entities::fish::FishEntity;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct World {
|
pub struct World {
|
||||||
@ -19,9 +19,7 @@ pub struct World {
|
|||||||
pub fish: Vec<FishEntity>,
|
pub fish: Vec<FishEntity>,
|
||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub colliders: Vec<Rectangle>,
|
pub colliders: Vec<Rectangle>
|
||||||
|
|
||||||
pub jellyfish: Vec<JellyFish>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
|
Reference in New Issue
Block a user