Merge pull request #8 from Ewpratten/ingame_hud

Ingame hud
This commit is contained in:
Evan Pratten 2021-04-24 09:52:57 -04:00 committed by GitHub
commit 556a9696cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 494 additions and 109 deletions

View File

@ -6,7 +6,9 @@ edition = "2018"
description = "" description = ""
[dependencies] [dependencies]
raylib = { version = "3.5", git = "https://github.com/ewpratten/raylib-rs", branch = "master" } raylib = { version = "3.5", git = "https://github.com/ewpratten/raylib-rs", branch = "master", features = [
"with_serde"
] }
serialstudio = "0.1.0" serialstudio = "0.1.0"
serde = "1.0.125" serde = "1.0.125"
serde_json = "1.0.64" serde_json = "1.0.64"
@ -14,4 +16,4 @@ failure = "0.1.8"
parry2d = "0.4.0" parry2d = "0.4.0"
log = "0.4.14" log = "0.4.14"
env_logger = "0.8.3" env_logger = "0.8.3"
nalgebra = "0.26.1" nalgebra = "0.26.1"

View File

@ -1,3 +1,6 @@
{ {
"end_position": {
"x": 10000.0,
"y": 10000.0
}
} }

View File

@ -17,7 +17,8 @@ pub enum GameState {
MainMenu, MainMenu,
PauseMenu, PauseMenu,
GameQuit, GameQuit,
InGame InGame,
GameEnd
} }
impl fmt::Display for GameState { impl fmt::Display for GameState {
@ -32,6 +33,7 @@ pub struct GameCore {
pub state: GameState, pub state: GameState,
pub last_state: GameState, pub last_state: GameState,
pub last_state_change_time: f64, pub last_state_change_time: f64,
pub last_frame_time: f64,
pub has_rendered_first_frame: bool, pub has_rendered_first_frame: bool,
/// Resources /// Resources
@ -56,6 +58,7 @@ impl GameCore {
state: GameState::Loading, state: GameState::Loading,
last_state: GameState::Loading, last_state: GameState::Loading,
last_state_change_time: 0.0, last_state_change_time: 0.0,
last_frame_time: 0.0,
has_rendered_first_frame: false, has_rendered_first_frame: false,
resources: GlobalResources::load_all(raylib, thread) resources: GlobalResources::load_all(raylib, thread)
.expect("Failed to load game assets. Can not launch!"), .expect("Failed to load game assets. Can not launch!"),
@ -67,7 +70,7 @@ impl GameCore {
}, },
show_simple_debug_info: false, show_simple_debug_info: false,
world: world, world: world,
player: Player::new() player: Player::new(),
} }
} }

View File

@ -16,7 +16,12 @@ pub struct ProfilerData {
pub active_sounds: i32, pub active_sounds: i32,
// Game core // Game core
pub game_state: String pub game_state: String,
// Player
pub player_coins: u32,
pub player_boost_percent: f32,
pub player_breath_percent: f32
} }
/// The development profiler /// The development profiler
@ -117,6 +122,33 @@ impl GameProfiler {
}, },
], ],
}, },
DataGroup {
title: "Player".to_string(),
widget_type: None,
datasets: vec![
DataSet {
title: Some("Coins".to_string()),
value: json!(self.data.player_coins),
graph: Some(false),
unit: Some("coins".to_string()),
w_type: None,
},
DataSet {
title: Some("Breath".to_string()),
value: json!(self.data.player_boost_percent),
graph: Some(false),
unit: Some("%".to_string()),
w_type: None,
},
DataSet {
title: Some("Breath".to_string()),
value: json!(self.data.player_breath_percent),
graph: Some(false),
unit: Some("%".to_string()),
w_type: None,
},
],
},
], ],
}; };

126
src/logic/gameend.rs Normal file
View File

@ -0,0 +1,126 @@
use raylib::prelude::*;
use crate::{
gamecore::{GameCore, GameState},
lib::wrappers::audio::player::AudioPlayer,
};
use super::screen::Screen;
const SCREEN_PANEL_SIZE: Vector2 = Vector2 { x: 300.0, y: 300.0 };
pub struct GameEndScreen {}
impl GameEndScreen {
pub fn new() -> Self {
Self {}
}
}
impl Screen for GameEndScreen {
fn render(
&mut self,
draw_handle: &mut RaylibDrawHandle,
_thread: &RaylibThread,
audio_system: &mut AudioPlayer,
game_core: &mut GameCore,
) -> Option<GameState> {
let mouse_position = draw_handle.get_mouse_position();
draw_handle.clear_background(Color::GRAY);
// TODO: Maybe we can stick some art here?
// Window dimensions
let win_height = draw_handle.get_screen_height();
let win_width = draw_handle.get_screen_width();
// Render the backing to the menu itself
draw_handle.draw_rectangle(
(win_width / 2) - ((SCREEN_PANEL_SIZE.x as i32 + 6) / 2),
(win_height / 2) - ((SCREEN_PANEL_SIZE.y as i32 + 6) / 2),
SCREEN_PANEL_SIZE.x as i32 + 6,
SCREEN_PANEL_SIZE.y as i32 + 6,
Color::BLACK,
);
draw_handle.draw_rectangle(
(win_width / 2) - (SCREEN_PANEL_SIZE.x as i32 / 2),
(win_height / 2) - (SCREEN_PANEL_SIZE.y as i32 / 2),
SCREEN_PANEL_SIZE.x as i32,
SCREEN_PANEL_SIZE.y as i32,
Color::WHITE,
);
// Render heading text
draw_handle.draw_text(
"OUT OF BREATH",
(win_width / 2) - 80,
(win_height / 2) - (SCREEN_PANEL_SIZE.y as i32 / 2) + 10,
40,
Color::BLACK,
);
// // 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;
}
}

101
src/logic/ingame/hud.rs Normal file
View File

@ -0,0 +1,101 @@
use raylib::prelude::*;
use crate::{gamecore::GameCore, pallette::TRANSLUCENT_WHITE_96};
pub fn render_hud(
draw_handle: &mut RaylibDrawHandle,
game_core: &mut GameCore,
window_center: Vector2,
) {
// Get the relevant data
let dist_from_player_to_end = game_core
.player
.position
.distance_to(game_core.world.end_position);
let dist_from_start_to_end = Vector2::zero().distance_to(game_core.world.end_position);
let progress = ((dist_from_start_to_end - dist_from_player_to_end) / dist_from_start_to_end)
.clamp(0.0, 1.0);
// Determine the progress slider position
let slider_bound_height = 20.0;
let progress_slider_position = Vector2 {
x: window_center.x * 2.0,
y: (((window_center.y * 2.0) - (slider_bound_height * 2.0)) * progress)
+ slider_bound_height,
};
// Render the base of the slider
draw_handle.draw_rectangle(
(progress_slider_position.x - slider_bound_height) as i32,
(progress_slider_position.y - slider_bound_height / 2.0) as i32,
slider_bound_height as i32,
slider_bound_height as i32,
TRANSLUCENT_WHITE_96,
);
draw_handle.draw_triangle(
Vector2 {
x: (progress_slider_position.x - slider_bound_height),
y: (progress_slider_position.y - slider_bound_height / 2.0),
},
Vector2 {
x: (progress_slider_position.x - slider_bound_height - (slider_bound_height / 2.0)),
y: progress_slider_position.y,
},
Vector2 {
x: (progress_slider_position.x - slider_bound_height),
y: (progress_slider_position.y + slider_bound_height / 2.0),
},
TRANSLUCENT_WHITE_96,
);
// Render the outline of the slider
draw_handle.draw_line_ex(
Vector2 {
x: (progress_slider_position.x - slider_bound_height),
y: (progress_slider_position.y - slider_bound_height / 2.0),
},
Vector2 {
x: progress_slider_position.x,
y: (progress_slider_position.y - slider_bound_height / 2.0),
},
3.0,
Color::BLACK,
);
draw_handle.draw_line_ex(
Vector2 {
x: (progress_slider_position.x - slider_bound_height),
y: (progress_slider_position.y + slider_bound_height / 2.0),
},
Vector2 {
x: progress_slider_position.x,
y: (progress_slider_position.y + slider_bound_height / 2.0),
},
3.0,
Color::BLACK,
);
draw_handle.draw_line_ex(
Vector2 {
x: (progress_slider_position.x - slider_bound_height),
y: (progress_slider_position.y - slider_bound_height / 2.0),
},
Vector2 {
x: (progress_slider_position.x - slider_bound_height - (slider_bound_height / 2.0)),
y: progress_slider_position.y,
},
3.0,
Color::BLACK,
);
draw_handle.draw_line_ex(
Vector2 {
x: (progress_slider_position.x - slider_bound_height),
y: (progress_slider_position.y + slider_bound_height / 2.0),
},
Vector2 {
x: (progress_slider_position.x - slider_bound_height - (slider_bound_height / 2.0)),
y: progress_slider_position.y,
},
3.0,
Color::BLACK,
);
}

View File

@ -1,12 +0,0 @@
pub enum ingame_states{
BUYING,
SWIMMING,
DEAD,
}

View File

@ -1,3 +1,6 @@
mod playerlogic;
mod hud;
use raylib::prelude::*; use raylib::prelude::*;
use crate::{ use crate::{
@ -7,14 +10,9 @@ use crate::{
use super::screen::Screen; use super::screen::Screen;
const NORMAL_PLAYER_SPEED: i32 = 4;
const BOOST_PLAYER_SPEED: i32 = NORMAL_PLAYER_SPEED * 2;
const CAMERA_FOLLOW_SPEED: f32 = 0.7;
pub enum InGameState { pub enum InGameState {
BUYING, BUYING,
SWIMMING, SWIMMING,
DEAD,
} }
pub struct InGameScreen { pub struct InGameScreen {
@ -28,89 +26,15 @@ impl InGameScreen {
} }
} }
fn update_player_movement(
&mut self,
draw_handle: &mut RaylibDrawHandle,
game_core: &mut GameCore,
window_center: Vector2,
) {
// Handle player movement
let mouse_pose = draw_handle.get_mouse_position();
let mouse_world_pose = draw_handle.get_screen_to_world2D(mouse_pose, game_core.master_camera);
let raw_movement_direction = mouse_world_pose - game_core.player.position;
let mut normalized_movement_direction = raw_movement_direction;
normalized_movement_direction.normalize();
game_core.player.direction = normalized_movement_direction;
// In the case the player is in "null", just jump the camera to them
if game_core.player.position == Vector2::zero() {
game_core.master_camera.target = game_core.player.position - (window_center / 2.0);
}
// Handle action buttons
let user_request_boost = draw_handle.is_mouse_button_down(MouseButton::MOUSE_LEFT_BUTTON);
let user_request_action =
draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_RIGHT_BUTTON);
// Move the player in their direction
let speed_multiplier = match user_request_boost && game_core.player.boost_percent >= 0.0 {
true => BOOST_PLAYER_SPEED as f32,
false => NORMAL_PLAYER_SPEED as f32,
};
// Only do this if the mouse is far enough away
let player_real_movement = game_core.player.direction * speed_multiplier;
if raw_movement_direction.distance_to(Vector2::zero()) > game_core.player.size.y / 2.0 {
game_core.player.position += player_real_movement;
}
// 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 = draw_handle.get_world_to_screen2D(game_core.player.position, game_core.master_camera);
// Camera only moves if you get close to the edge of the screen
if player_screen_position.distance_to(window_center).abs() > (window_center.y - 40.0) {
game_core.master_camera.target += player_real_movement;
}
}
fn render_player(
&mut self,
context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
game_core: &mut GameCore,
) {
// Get the player
let player = &game_core.player;
// Convert the player direction to a rotation
let player_rotation = Vector2::zero().angle_to(player.direction);
// TODO: tmp rect
context_2d.draw_rectangle_pro(
Rectangle {
x: player.position.x,
y: player.position.y,
width: player.size.x,
height: player.size.y,
},
player.size / 2.0,
player_rotation.to_degrees() + 90.0,
Color::BLACK,
);
}
fn render_world( fn render_world(
&mut self, &mut self,
context_2d: &mut RaylibMode2D<RaylibDrawHandle>, context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
game_core: &mut GameCore, game_core: &mut GameCore,
) { ) {
context_2d.draw_circle(0, 0, 10.0, Color::BLACK); context_2d.draw_circle(0, 0, 10.0, Color::BLACK);
} }
} }
impl Screen for InGameScreen { impl Screen for InGameScreen {
@ -122,7 +46,7 @@ impl Screen for InGameScreen {
game_core: &mut GameCore, game_core: &mut GameCore,
) -> Option<GameState> { ) -> Option<GameState> {
// Clear frame // Clear frame
draw_handle.clear_background(Color::WHITE); draw_handle.clear_background(Color::BLUE);
// Handle the pause menu being opened // Handle the pause menu being opened
if draw_handle.is_key_pressed(KeyboardKey::KEY_ESCAPE) { if draw_handle.is_key_pressed(KeyboardKey::KEY_ESCAPE) {
@ -138,7 +62,7 @@ impl Screen for InGameScreen {
}; };
// Update player movement // Update player movement
self.update_player_movement(draw_handle, game_core, window_center); playerlogic::update_player_movement(draw_handle, game_core, window_center);
// Open a 2D context // Open a 2D context
{ {
@ -148,7 +72,15 @@ impl Screen for InGameScreen {
self.render_world(&mut context_2d, game_core); self.render_world(&mut context_2d, game_core);
// Render Player // Render Player
self.render_player(&mut context_2d, game_core); playerlogic::render_player(&mut context_2d, game_core);
}
// Render the hud
hud::render_hud(draw_handle, game_core, window_center);
// Handle player out of breath
if game_core.player.breath_percent == 0.0 {
return Some(GameState::GameEnd);
} }
return None; return None;

View File

@ -0,0 +1,159 @@
use raylib::prelude::*;
use crate::{
gamecore::GameCore,
pallette::{TRANSLUCENT_WHITE_128, TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96},
};
const NORMAL_PLAYER_SPEED: i32 = 4;
const BOOST_PLAYER_SPEED: i32 = NORMAL_PLAYER_SPEED * 2;
const CAMERA_FOLLOW_SPEED: f32 = 0.7;
const TURN_SPEED: f32 = 0.05;
const BOOST_DECREASE_PER_SECOND: f32 = 0.75;
const BOOST_REGEN_PER_SECOND: f32 = 0.25;
const BREATH_DECREASE_PER_SECOND: f32 = 0.01;
pub fn update_player_movement(
draw_handle: &mut RaylibDrawHandle,
game_core: &mut GameCore,
window_center: Vector2,
) {
// Calculate DT
let dt = draw_handle.get_time() - game_core.last_frame_time;
// Handle player movement
let mouse_pose = draw_handle.get_mouse_position();
let mouse_world_pose = draw_handle.get_screen_to_world2D(mouse_pose, game_core.master_camera);
let raw_movement_direction = mouse_world_pose - game_core.player.position;
let mut normalized_movement_direction = raw_movement_direction;
normalized_movement_direction.normalize();
let tau: f32 = PI as f32 * 2.0;
// get angles as floats
let mut player_angle: f32 = Vector2::zero().angle_to(game_core.player.direction);
let mut desired_angle: f32 = Vector2::zero().angle_to(normalized_movement_direction);
// make angle positive
if desired_angle < 0.0 {
desired_angle += tau;
}
// turn towards mouse at turn speed
if player_angle % tau > desired_angle {
if (player_angle % tau) - desired_angle > PI as f32 {
player_angle += TURN_SPEED;
} else {
player_angle -= TURN_SPEED;
}
} else {
if desired_angle - (player_angle % tau) > PI as f32 {
player_angle -= TURN_SPEED;
} else {
player_angle += TURN_SPEED;
}
}
// snap to mouse if close enough
if f32::abs(player_angle - desired_angle) < (TURN_SPEED * 1.1) {
player_angle = desired_angle;
}
if player_angle > tau {
player_angle -= tau;
}
if player_angle < 0.0 {
player_angle += tau;
}
// set 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
if game_core.player.position == Vector2::zero() {
game_core.master_camera.target = game_core.player.position - (window_center / 2.0);
}
// Handle action buttons
let user_request_boost = draw_handle.is_mouse_button_down(MouseButton::MOUSE_LEFT_BUTTON);
let user_request_action = draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_RIGHT_BUTTON);
// Move the player in their direction
let speed_multiplier;
if user_request_boost && game_core.player.boost_percent >= 0.0 {
// Set the speed multiplier
speed_multiplier = BOOST_PLAYER_SPEED as f32;
// Decrease the boost
game_core.player.boost_percent -= BOOST_DECREASE_PER_SECOND * dt as f32;
} else {
// Set the speed multiplier
speed_multiplier = NORMAL_PLAYER_SPEED as f32;
// Handle boost regen
if !user_request_boost {
game_core.player.boost_percent = (game_core.player.boost_percent
+ BOOST_REGEN_PER_SECOND * dt as f32)
.clamp(0.0, 1.0);
}
}
// Update the player's breath
game_core.player.breath_percent =
(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
let player_real_movement = game_core.player.direction * speed_multiplier;
if raw_movement_direction.distance_to(Vector2::zero()) > game_core.player.size.y / 2.0 {
game_core.player.position += player_real_movement;
}
// 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 =
draw_handle.get_world_to_screen2D(game_core.player.position, game_core.master_camera);
// Camera only moves if you get close to the edge of the screen
if player_screen_position.distance_to(window_center).abs() > (window_center.y - 40.0) {
game_core.master_camera.target += player_real_movement;
}
}
pub fn render_player(context_2d: &mut RaylibMode2D<RaylibDrawHandle>, game_core: &mut GameCore) {
// Get the player
let player = &game_core.player;
// Convert the player direction to a rotation
let player_rotation = Vector2::zero().angle_to(player.direction);
// Render the player's boost ring
// This functions both as a breath meter, and as a boost meter
let boost_ring_max_radius = player.size.x + 5.0;
context_2d.draw_circle(
player.position.x as i32,
player.position.y as i32,
boost_ring_max_radius * player.boost_percent,
TRANSLUCENT_WHITE_64,
);
context_2d.draw_ring(
player.position,
boost_ring_max_radius - 2.0,
boost_ring_max_radius + 2.0,
0,
(360.0 * player.breath_percent) as i32,
0,
TRANSLUCENT_WHITE_96,
);
// TODO: tmp rect
context_2d.draw_rectangle_pro(
Rectangle {
x: player.position.x,
y: player.position.y,
width: player.size.x,
height: player.size.y,
},
player.size / 2.0,
player_rotation.to_degrees() + 90.0,
Color::BLACK,
);
}

View File

@ -2,4 +2,5 @@ pub mod screen;
pub mod loadingscreen; pub mod loadingscreen;
pub mod mainmenu; pub mod mainmenu;
pub mod pausemenu; pub mod pausemenu;
pub mod ingame; pub mod ingame;
pub mod gameend;

View File

@ -4,14 +4,12 @@ mod logic;
mod resources; mod resources;
mod player; mod player;
mod world; mod world;
mod pallette;
use gamecore::{GameCore, GameState}; use gamecore::{GameCore, GameState};
use lib::{utils::profiler::GameProfiler, wrappers::audio::player::AudioPlayer}; use lib::{utils::profiler::GameProfiler, wrappers::audio::player::AudioPlayer};
use log::info; use log::info;
use logic::{ use logic::{gameend::GameEndScreen, ingame::InGameScreen, loadingscreen::LoadingScreen, mainmenu::MainMenuScreen, pausemenu::PauseMenuScreen, screen::Screen};
ingame::InGameScreen, loadingscreen::LoadingScreen, mainmenu::MainMenuScreen,
pausemenu::PauseMenuScreen, screen::Screen,
};
use raylib::prelude::*; use raylib::prelude::*;
use world::World; use world::World;
@ -58,6 +56,7 @@ fn main() {
let mut main_menu_screen = MainMenuScreen::new(); let mut main_menu_screen = MainMenuScreen::new();
let mut pause_menu_screen = PauseMenuScreen::new(); let mut pause_menu_screen = PauseMenuScreen::new();
let mut ingame_screen = InGameScreen::new(); let mut ingame_screen = InGameScreen::new();
let mut game_end_screen = GameEndScreen::new();
// Main rendering loop // Main rendering loop
while !raylib.window_should_close() { while !raylib.window_should_close() {
@ -90,6 +89,12 @@ fn main() {
&mut audio_system, &mut audio_system,
&mut game_core, &mut game_core,
), ),
GameState::GameEnd => game_end_screen.render(
&mut draw_handle,
&raylib_thread,
&mut audio_system,
&mut game_core,
),
}; };
// If needed, update the global state // If needed, update the global state
@ -120,6 +125,9 @@ fn main() {
profiler.data.audio_volume = audio_system.get_master_volume(); profiler.data.audio_volume = audio_system.get_master_volume();
profiler.data.active_sounds = audio_system.get_sounds_playing(); profiler.data.active_sounds = audio_system.get_sounds_playing();
profiler.data.game_state = game_core.state.to_string(); profiler.data.game_state = game_core.state.to_string();
profiler.data.player_coins = game_core.player.coins;
profiler.data.player_boost_percent = game_core.player.boost_percent;
profiler.data.player_breath_percent = game_core.player.breath_percent;
// Send telemetry data // Send telemetry data
profiler.update(); profiler.update();
@ -145,6 +153,9 @@ fn main() {
// Set the first frame flag // Set the first frame flag
game_core.has_rendered_first_frame = true; game_core.has_rendered_first_frame = true;
// Update the frame time
game_core.last_frame_time = draw_handle.get_time();
} }
// Cleanup // Cleanup

22
src/pallette.rs Normal file
View File

@ -0,0 +1,22 @@
use raylib::color::Color;
pub const TRANSLUCENT_WHITE_128: Color = Color {
r: 255,
g: 255,
b: 255,
a: 128,
};
pub const TRANSLUCENT_WHITE_96: Color = Color {
r: 255,
g: 255,
b: 255,
a: 96,
};
pub const TRANSLUCENT_WHITE_64: Color = Color {
r: 255,
g: 255,
b: 255,
a: 64,
};

View File

@ -8,7 +8,8 @@ pub struct Player {
pub direction: Vector2, pub direction: Vector2,
pub size: Vector2, pub size: Vector2,
pub coins: u32, pub coins: u32,
pub boost_percent: f32 pub boost_percent: f32,
pub breath_percent: f32
} }
impl Player { impl Player {
@ -19,6 +20,7 @@ impl Player {
x: 11.0 * 4.0, x: 11.0 * 4.0,
y: 21.0 * 4.0 y: 21.0 * 4.0
}, },
breath_percent: 1.0,
..Default::default() ..Default::default()
} }

View File

@ -1,11 +1,14 @@
use std::{fs::File, io::BufReader}; use std::{fs::File, io::BufReader};
use raylib::math::Vector2;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::io::Read; use std::io::Read;
use failure::Error; use failure::Error;
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct World {} pub struct World {
pub end_position: Vector2
}
impl World { impl World {
pub fn load_from_json(file: String) -> Result<Self, Error> { pub fn load_from_json(file: String) -> Result<Self, Error> {