mod resource_parser;
use crate::{
communication::{Message, MessageQueue, Sprite, DOUBLE_BUFFER, SYNCHRONIZATION_MEMORY},
error::ClientError,
};
use rask_engine::{
engine::{GameEngine, RaskEngine},
events::{Event, Key},
resources::registry,
resources::GetStore,
};
use resource_parser::ResourceParser;
pub struct LogicContext {
engine: RaskEngine,
last_timestamp: i32,
state: Vec<Sprite>,
tick_nr: u64,
pub message_queue: MessageQueue,
res_parser: ResourceParser,
angle: i32,
angle_mod: i32,
anim_tick_nr: u32,
}
impl LogicContext {
pub fn new(pool: rayon::ThreadPool) -> Result<Self, ClientError> {
let mut res_parser = ResourceParser::new();
res_parser.fetch_resource(registry::EMPTY)?;
res_parser.fetch_resource(registry::THIEF)?;
res_parser.fetch_resource(registry::SOUND)?;
res_parser.fetch_character_resource(registry::CHAR)?;
Ok(Self {
engine: RaskEngine::new(std::sync::Arc::new(pool)),
last_timestamp: unsafe { SYNCHRONIZATION_MEMORY.elapsed_ms },
state: Vec::new(),
tick_nr: 0,
message_queue: MessageQueue::new(),
res_parser,
angle: 0,
angle_mod: 0,
anim_tick_nr: 0,
})
}
fn push_state(&mut self) {
let mut writer = DOUBLE_BUFFER.lock();
*writer = self.state.clone();
}
pub fn tick(&mut self) -> Result<(), ClientError> {
let mut event = None;
loop {
let msg = self.message_queue.pop();
if let Message::None = msg {
break;
}
log::debug!("{:?}", msg);
event = self.handle_message(msg)?;
}
if let Some(ref event) = event {
self.engine.handle_event(event.clone())?;
}
match event {
Some(Event::KeyDown(_, Key::ARROW_LEFT)) => self.angle_mod = -1,
Some(Event::KeyDown(_, Key::ARROW_RIGHT)) => self.angle_mod = 1,
Some(Event::KeyUp(_, Key::ARROW_RIGHT)) => self.angle_mod = 0,
Some(Event::KeyUp(_, Key::ARROW_LEFT)) => self.angle_mod = 0,
Some(Event::KeyDown(_, Key::KEY_P)) => Message::PlaySound(registry::SOUND.id).send(),
Some(Event::KeyDown(_, Key::KEY_S)) => Message::StopSound(registry::SOUND.id).send(),
Some(Event::KeyDown(_, Key::DIGIT1)) => log::set_max_level(log::LevelFilter::Info),
Some(Event::KeyDown(_, Key::DIGIT2)) => log::set_max_level(log::LevelFilter::Debug),
Some(Event::KeyDown(_, Key::DIGIT3)) => log::set_max_level(log::LevelFilter::Trace),
Some(Event::KeyDown(_, Key::ENTER)) => {
self.res_parser.fetch_resource(registry::EMPTY)?;
self.res_parser.fetch_resource(registry::THIEF)?;
self.res_parser.fetch_character_resource(registry::CHAR)?;
self.res_parser.fetch_resource(registry::SOUND)?;
}
Some(Event::KeyDown(_, Key::KEY_W)) => {
let mut src = crate::communication::SCREEN_RECT_SCALE.write();
if *src > 1.025 {
*src -= 0.05;
}
}
Some(Event::KeyDown(_, Key::KEY_E)) => {
let mut src = crate::communication::SCREEN_RECT_SCALE.write();
if *src < 1.975 {
*src += 0.05;
}
}
_ => (),
}
self.angle += self.angle_mod;
if self.state.len() < 2 {
let res = crate::communication::RESOURCE_TABLE.read();
let texid1 = registry::EMPTY.id;
let texid2 = registry::THIEF.id;
let charid = registry::CHAR.id;
let tex1: Result<&rask_engine::resources::Texture, _> = res.get(texid1 as usize);
let tex2: Result<&rask_engine::resources::Texture, _> = res.get(texid2 as usize);
let charc: Result<&Box<rask_engine::resources::Character>, _> =
res.get(charid as usize);
if let (Ok(_), Ok(_), Ok(charc)) = (tex1, tex2, charc) {
log::info!("loaded all resoucres");
let mut guard = crate::communication::TEXTURE_IDS.lock();
for &(id, mat) in &[
(texid1, rask_engine::math::Mat3::identity()),
(texid2, rask_engine::math::Mat3::identity()),
] {
guard.ids.push(id);
self.state
.push(crate::communication::Sprite::new(mat, id, 0));
}
let sprites = charc.interpolate(0.0, "walking")?;
guard.ids.push(charid);
for sprite in sprites {
self.state
.push(crate::communication::Sprite::from_animation_state(
sprite?, charid,
));
}
guard.reset_notify = 1;
}
}
log::trace!("angle: {}", self.angle);
if self.state.len() >= 3 {
self.state[1].transform = rask_engine::math::Mat3::rotation(0.02 * self.angle as f32)
* rask_engine::math::Mat3::scaling(0.0, 0.0);
let res = crate::communication::RESOURCE_TABLE.read();
let charid = rask_engine::resources::registry::CHAR.id;
let charc: &Box<rask_engine::resources::Character> = res.get(charid as usize).unwrap();
let sprites = charc.interpolate(self.tick_nr as f32 * 0.018, "walking")?;
for (i, sprite) in sprites.enumerate() {
self.state[2 + i] =
crate::communication::Sprite::from_animation_state(sprite?, charid);
self.state[2 + i].transform = rask_engine::math::Mat3::translation(
self.tick_nr as f32 / (90.0 * 2.0) % 2.2 - 1.1,
-0.72,
) * self.state[2 + i].transform;
}
}
let now = unsafe { SYNCHRONIZATION_MEMORY.elapsed_ms };
self.engine.tick(core::time::Duration::from_millis(
(now - self.last_timestamp) as u64,
));
self.last_timestamp = now;
self.push_state();
self.tick_nr += 1;
Ok(())
}
fn handle_message(&mut self, message: Message) -> Result<Option<Event>, ClientError> {
match message {
Message::KeyDown(modifier, hash) => Ok(Some(Event::KeyDown(modifier, Key::from(hash)))),
Message::KeyUp(modifier, hash) => Ok(Some(Event::KeyUp(modifier, Key::from(hash)))),
Message::MouseDown(event) => Ok(Some(Event::MouseDown(event))),
Message::MouseUp(event) => Ok(Some(Event::MouseUp(event))),
Message::KeyPress(t, code) => Ok(Some(Event::KeyPress(t as u16, code))),
Message::AudioLoaded(id) => {
let mut res = crate::communication::RESOURCE_TABLE.write();
res.store(rask_engine::resources::Sound, id as usize)?;
Ok(None)
}
Message::RequestAlloc { id, size } => self.res_parser.alloc(id, size).map(|_| None),
Message::DoneWritingResource(id) => self.res_parser.parse(id).map(|_| None),
_ => Err(ClientError::EngineError("Unknown Message Type".into())),
}
}
}