fyrox-platformer/game/src/lib.rs

364 lines
13 KiB
Rust

#[macro_use]
extern crate lazy_static;
use fyrox::core::color::Color;
use fyrox::graph::SceneGraph;
use fyrox::gui::Thickness;
use fyrox::{
asset::manager::ResourceManager,
core::{
log::Log,
pool::Handle,
visitor::{Visit, VisitResult, Visitor},
},
engine::GraphicsContext,
event::{Event, WindowEvent},
gui::{
brush::Brush,
button::ButtonMessage,
font::Font,
grid::{Column, GridBuilder, Row},
message::{MessageDirection, UiMessage},
text::TextBuilder,
widget::WidgetBuilder,
widget::WidgetMessage,
UiNode, UserInterface, UiContainer,
},
keyboard::{KeyCode, PhysicalKey},
plugin::{Plugin, PluginContext},
scene::{graph::Graph, Scene},
};
use std::path::Path;
mod enemies;
mod map;
mod msg;
mod player;
mod sound;
use enemies::archer::{enemy::Archer, spawn::ArcherSpawn};
use enemies::swordsman::{enemy::Swordman, spawn::SwordmanSpawn};
use map::build_map;
use msg::ScreenSizeMessage;
use player::Player;
use sound::Sound;
const START_LEVEL: u32 = 1;
pub struct GameConstructor;
// impl PluginConstructor for GameConstructor {
// fn register(&self, context: PluginRegistrationContext) {
// // Register your scripts here.
// let script_constructors = &context.serialization_context.script_constructors;
// script_constructors.add::<Swordman>("Enemy");
// script_constructors.add::<Player>("Player");
// script_constructors.add::<Sound>("Sound");
// }
// fn create_instance(&self, scene_path: Option<&str>, context: PluginContext) -> Box<dyn Plugin> {
// Box::new(Game::new(scene_path, context))
// }
// }
#[derive(Visit, Default)]
pub struct Game {
scene: Handle<Scene>,
new_game: Handle<UiNode>,
new_game_with_plot: Handle<UiNode>,
next: Handle<UiNode>,
new_game_after_plot: Handle<UiNode>,
exit: Handle<UiNode>,
level_node: Handle<UiNode>,
level: u32,
need_change_level: bool,
need_show_menu: bool,
show_menu_time: f32,
change_level_time: f32,
need_show_end: bool,
}
impl Game {
pub fn default() -> Self {
return Game {
level: START_LEVEL,
..Default::default()
};
}
pub fn init_game(&self, ctx: PluginContext) -> Self {
ctx.task_pool.spawn_plugin_task(
UserInterface::load_from_file("data/menu.ui", ctx.resource_manager.clone()),
|result, game: &mut Game, ctx| match result {
Ok(menu) => {
let mut ui_container = UiContainer::new();
ui_container.add(menu);
*ctx.user_interfaces = ui_container;
(game.new_game, _) = ctx
.user_interfaces.first()
.find_by_name_from_root("NewGame")
.unwrap();
(game.new_game_with_plot, _) = ctx
.user_interfaces.first()
.find_by_name_from_root("NewGameWithPlot")
.unwrap();
(game.next, _) = ctx
.user_interfaces.first()
.find_by_name_from_root("NextPlotScreen")
.unwrap();
(game.new_game_after_plot, _) = ctx
.user_interfaces.first()
.find_by_name_from_root("NewGamePlotScreen")
.unwrap();
(game.exit, _) = ctx.user_interfaces.first().find_by_name_from_root("Exit").unwrap();
}
Err(e) => Log::err(format!("Unable to load main menu! Reason: {:?}", e)),
// let ui = ctx.user_interfaces.clone();
// *ui = result.unwrap();
},
);
Self {
level_node: Handle::NONE,
scene: Handle::NONE,
new_game: Handle::NONE,
new_game_with_plot: Handle::NONE,
new_game_after_plot: Handle::NONE,
next: Handle::NONE,
exit: Handle::NONE,
level: START_LEVEL,
need_change_level: false,
need_show_menu: false,
need_show_end: false,
show_menu_time: 0.0,
change_level_time: 0.0,
}
}
pub fn next_level(&mut self, change_level_time: f32) {
self.need_change_level = true;
self.change_level_time = change_level_time;
}
pub fn show_menu(&mut self, show_menu_time: f32) {
self.show_menu_time = show_menu_time;
self.need_show_menu = true;
}
pub fn end_game(&mut self) {
self.need_show_end = true;
}
}
impl Plugin for Game {
fn register(
&self,
#[allow(unused_variables)] context: fyrox::plugin::PluginRegistrationContext,
) {
let script_constructors = &context.serialization_context.script_constructors;
script_constructors.add::<Swordman>("Enemy");
script_constructors.add::<Player>("Player");
script_constructors.add::<Sound>("Sound");
}
fn init(&mut self, _scene_path: Option<&str>, context: PluginContext) {
self.init_game(context);
}
fn on_deinit(&mut self, _context: PluginContext) {
// Do a cleanup here.
}
fn update(&mut self, context: &mut PluginContext) {
if self.need_change_level && self.change_level_time < context.elapsed_time {
self.need_change_level = false;
self.level += 1;
context.async_scene_loader.request("data/scene.rgs");
}
//println!("{} {} ", context.elapsed_time, self.show_menu_time);
if self.need_show_menu && self.show_menu_time < context.elapsed_time {
self.need_show_menu = false;
self.show_menu_time = 0.0;
context
.user_interfaces.first()
.send_message(WidgetMessage::visibility(
context
.user_interfaces.first()
.find_handle_by_name_from_root("MenuScreen"),
MessageDirection::ToWidget,
true,
));
}
if self.need_show_end {
context
.user_interfaces.first()
.send_message(WidgetMessage::visibility(
context
.user_interfaces.first()
.find_handle_by_name_from_root("EndScreen"),
MessageDirection::ToWidget,
true,
));
}
}
fn on_os_event(&mut self, event: &Event<()>, context: PluginContext) {
if let Event::WindowEvent { event, .. } = event {
if let WindowEvent::KeyboardInput { event, .. } = event {
if let PhysicalKey::Code(keycode) = event.physical_key {
if keycode == KeyCode::Escape {
context
.user_interfaces.first()
.send_message(WidgetMessage::visibility(
context
.user_interfaces.first()
.find_handle_by_name_from_root("MenuScreen"),
MessageDirection::ToWidget,
true,
));
}
}
}
}
if let Event::Resumed {} = event {
if let GraphicsContext::Initialized(ref graphics_context) = context.graphics_context {
let window_size = graphics_context.window.inner_size();
for script_scene in &context.script_processor.scripted_scenes {
script_scene
.message_sender
.send_global(ScreenSizeMessage::Resize {
width: window_size.width,
height: window_size.height,
});
}
}
}
if let Event::WindowEvent { event, .. } = event {
if let WindowEvent::Resized(size) = event {
for script_scene in &context.script_processor.scripted_scenes {
script_scene
.message_sender
.send_global(ScreenSizeMessage::Resize {
width: size.width,
height: size.height,
});
}
}
}
}
fn on_ui_message(&mut self, ctx: &mut PluginContext, message: &UiMessage) {
if let Some(ButtonMessage::Click) = message.data() {
if message.destination() == self.new_game || message.destination() == self.new_game_after_plot {
ctx.user_interfaces.first().send_message(WidgetMessage::visibility(
ctx.user_interfaces.first()
.find_handle_by_name_from_root("Start2Screen"),
MessageDirection::ToWidget,
false,
));
ctx.user_interfaces.first().send_message(WidgetMessage::visibility(
ctx.user_interfaces
.first().find_handle_by_name_from_root("MenuScreen"),
MessageDirection::ToWidget,
false,
));
ctx.async_scene_loader.request("data/scene.rgs");
} else if message.destination() == self.new_game_with_plot {
ctx.user_interfaces.first().send_message(WidgetMessage::visibility(
ctx.user_interfaces
.first().find_handle_by_name_from_root("MenuScreen"),
MessageDirection::ToWidget,
false,
));
ctx.user_interfaces.first().send_message(WidgetMessage::visibility(
ctx.user_interfaces
.first().find_handle_by_name_from_root("StartScreen"),
MessageDirection::ToWidget,
true,
));
} else if message.destination() == self.next {
ctx.user_interfaces.first().send_message(WidgetMessage::visibility(
ctx.user_interfaces
.first().find_handle_by_name_from_root("StartScreen"),
MessageDirection::ToWidget,
false,
));
ctx.user_interfaces.first().send_message(WidgetMessage::visibility(
ctx.user_interfaces
.first().find_handle_by_name_from_root("Start2Screen"),
MessageDirection::ToWidget,
true,
));
} else if message.destination() == self.exit {
if let Some(window_target) = ctx.window_target {
window_target.exit();
}
}
}
}
fn on_scene_begin_loading(&mut self, _path: &Path, ctx: &mut PluginContext) {
if self.scene.is_some() {
ctx.scenes.remove(self.scene);
}
ctx.user_interfaces.first().send_message(WidgetMessage::visibility(
self.level_node,
MessageDirection::ToWidget,
false,
));
}
fn on_scene_loaded(
&mut self,
_path: &Path,
scene: Handle<Scene>,
_data: &[u8],
context: &mut PluginContext,
) {
context
.user_interfaces.first()
.send_message(WidgetMessage::visibility(
context
.user_interfaces.first()
.find_handle_by_name_from_root("MenuScreen"),
MessageDirection::ToWidget,
false,
));
self.scene = scene;
let graph: &mut Graph = &mut context.scenes[self.scene].graph;
let resource_manager: &ResourceManager = &context.resource_manager;
build_map(graph, resource_manager, self.level);
Sound::new(graph);
if self.level == 1 {
SwordmanSpawn::new().spawn_enemy(graph, resource_manager, -5.0);
}
if self.level == 2 {
ArcherSpawn::new().spawn_enemy(graph, resource_manager, -25.0);
}
let ui_ctx = &mut context.user_interfaces.first_mut().build_ctx();
let font_to_level =
resource_manager.request::<Font>("data/cd2f1-36d91_sunday.ttf".to_owned());
self.level_node = GridBuilder::new(
WidgetBuilder::new()
.with_child(
TextBuilder::new(
WidgetBuilder::new()
.with_foreground(Brush::Solid(Color::opaque(192, 34, 9))),
)
.with_text(format!("Уровень: {}", self.level))
.with_font_size(20.0)
.with_font(font_to_level)
.with_shadow_brush(Brush::Solid(Color::RED))
.build(ui_ctx),
)
.with_margin(Thickness::top_left(10.0)),
)
.add_row(Row::stretch())
.add_column(Column::auto())
.add_column(Column::stretch())
.build(ui_ctx);
}
}