mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-11-26 06:08:16 +00:00
tsc: stage switching
This commit is contained in:
parent
1d8c8fe9d0
commit
af9b69c303
|
|
@ -1,4 +1,5 @@
|
|||
use num_traits::clamp;
|
||||
use std::clone::Clone;
|
||||
|
||||
use crate::bitfield;
|
||||
use crate::caret::CaretType;
|
||||
|
|
@ -10,6 +11,7 @@ use crate::SharedGameState;
|
|||
use crate::str;
|
||||
|
||||
bitfield! {
|
||||
#[derive(Clone)]
|
||||
pub struct Flags(u32);
|
||||
impl Debug;
|
||||
|
||||
|
|
@ -39,6 +41,7 @@ bitfield! {
|
|||
}
|
||||
|
||||
bitfield! {
|
||||
#[derive(Clone)]
|
||||
pub struct Equip(u16);
|
||||
impl Debug;
|
||||
|
||||
|
|
@ -54,8 +57,8 @@ bitfield! {
|
|||
// 7 bits wasted, thx pixel
|
||||
}
|
||||
|
||||
|
||||
bitfield! {
|
||||
#[derive(Clone)]
|
||||
pub struct Cond(u16);
|
||||
impl Debug;
|
||||
|
||||
|
|
@ -69,6 +72,7 @@ bitfield! {
|
|||
pub visible, set_visible: 7;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Player {
|
||||
pub x: isize,
|
||||
pub y: isize,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use crate::common::Rect;
|
|||
use crate::entity::GameEntity;
|
||||
use crate::frame::Frame;
|
||||
use crate::ggez::{Context, GameResult, timer};
|
||||
use crate::ggez::graphics::{Drawable, DrawParam, Text, TextFragment};
|
||||
use crate::ggez::nalgebra::clamp;
|
||||
use crate::player::Player;
|
||||
use crate::scene::Scene;
|
||||
|
|
@ -226,7 +227,7 @@ impl GameScene {
|
|||
for i in 1..7 {
|
||||
batch.add_rect(left_pos, top_pos + i as f32 * 8.0, &state.constants.textscript.textbox_rect_middle);
|
||||
}
|
||||
batch.add_rect(left_pos, top_pos + 64.0, &state.constants.textscript.textbox_rect_bottom);
|
||||
batch.add_rect(left_pos, top_pos + 56.0, &state.constants.textscript.textbox_rect_bottom);
|
||||
|
||||
batch.draw(ctx)?;
|
||||
}
|
||||
|
|
@ -242,6 +243,23 @@ impl GameScene {
|
|||
batch.draw(ctx)?;
|
||||
}
|
||||
|
||||
let text_offset = if state.textscript_vm.face == 0 { 0.0 } else { 56.0 };
|
||||
|
||||
// todo: proper text rendering
|
||||
if !state.textscript_vm.line_1.is_empty() {
|
||||
let line1: String = state.textscript_vm.line_1.iter().collect();
|
||||
Text::new(TextFragment::from(line1.as_str())).draw(ctx, DrawParam::new()
|
||||
.dest(nalgebra::Point2::new((left_pos + text_offset) * 2.0 + 32.0, top_pos * 2.0 + 32.0))
|
||||
.scale(nalgebra::Vector2::new(0.5, 0.5)))?;
|
||||
}
|
||||
|
||||
if !state.textscript_vm.line_2.is_empty() {
|
||||
let line2: String = state.textscript_vm.line_2.iter().collect();
|
||||
Text::new(TextFragment::from(line2.as_str())).draw(ctx, DrawParam::new()
|
||||
.dest(nalgebra::Point2::new((left_pos + text_offset) * 2.0 + 32.0, (top_pos + 24.0) * 2.0 + 32.0))
|
||||
.scale(nalgebra::Vector2::new(0.5, 0.5)))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -314,10 +332,9 @@ impl Scene for GameScene {
|
|||
fn init(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
state.textscript_vm.set_scene_script(self.stage.text_script.clone());
|
||||
self.stage.text_script = TextScript::new();
|
||||
state.textscript_vm.suspend = false;
|
||||
|
||||
//self.player.x = 700 * 0x200;
|
||||
//self.player.y = 1000 * 0x200;
|
||||
self.player.equip.set_booster_2_0(true);
|
||||
//self.player.equip.set_booster_2_0(true);
|
||||
state.control_flags.set_flag_x01(true);
|
||||
state.control_flags.set_control_enabled(true);
|
||||
Ok(())
|
||||
|
|
@ -353,7 +370,7 @@ impl Scene for GameScene {
|
|||
}
|
||||
}
|
||||
|
||||
TextScriptVM::run(state, self)?;
|
||||
TextScriptVM::run(state, self, ctx)?;
|
||||
self.tick = self.tick.wrapping_add(1);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::scene::game_scene::GameScene;
|
|||
use crate::scene::Scene;
|
||||
use crate::SharedGameState;
|
||||
use crate::stage::StageData;
|
||||
use crate::text_script::TextScript;
|
||||
use crate::text_script::{TextScript, TextScriptExecutionState};
|
||||
|
||||
pub struct LoadingScene {
|
||||
tick: usize,
|
||||
|
|
@ -25,7 +25,12 @@ impl Scene for LoadingScene {
|
|||
state.stages = stages;
|
||||
let script = TextScript::load_from(filesystem::open(ctx, [&state.base_path, "/Head.tsc"].join(""))?)?;
|
||||
state.textscript_vm.set_global_script(script);
|
||||
state.next_scene = Some(Box::new(GameScene::new(state, ctx, 0)?));
|
||||
|
||||
let mut next_scene = GameScene::new(state, ctx, 13)?;
|
||||
next_scene.player.x = 10 * 16 * 0x200;
|
||||
next_scene.player.y = 8 * 16 * 0x200;
|
||||
state.next_scene = Some(Box::new(next_scene));
|
||||
state.textscript_vm.state = TextScriptExecutionState::Running(200, 0);
|
||||
}
|
||||
|
||||
self.tick += 1;
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ pub struct Stage {
|
|||
impl Stage {
|
||||
pub fn load(ctx: &mut Context, root: &str, data: &StageData) -> GameResult<Self> {
|
||||
let map_file = filesystem::open(ctx, [root, "Stage/", &data.map, ".pxm"].join(""))?;
|
||||
let tsc_file = filesystem::open(ctx, [root, "Stage/", &data.map, ".tsc"].join(""))?;
|
||||
let attrib_file = filesystem::open(ctx, [root, "Stage/", &data.tileset.name, ".pxa"].join(""))?;
|
||||
let tsc_file = filesystem::open(ctx, [root, "Stage/", &data.tileset.name, ".tsc"].join(""))?;
|
||||
|
||||
let map = Map::load_from(map_file, attrib_file)?;
|
||||
let text_script = TextScript::load_from(tsc_file)?;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use std::borrow::BorrowMut;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::io::{Cursor, Read, Seek, SeekFrom};
|
||||
use std::io::Cursor;
|
||||
use std::io::Seek;
|
||||
use std::io::SeekFrom;
|
||||
use std::iter::Peekable;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
|
@ -13,8 +13,8 @@ use num_traits::FromPrimitive;
|
|||
|
||||
use crate::{SharedGameState, str};
|
||||
use crate::bitfield;
|
||||
use crate::ggez::{Context, GameResult};
|
||||
use crate::ggez::GameError::ParseError;
|
||||
use crate::ggez::GameResult;
|
||||
use crate::scene::game_scene::GameScene;
|
||||
|
||||
/// Engine's text script VM operation codes.
|
||||
|
|
@ -198,6 +198,7 @@ pub struct TextScriptVM {
|
|||
pub scripts: TextScriptVMScripts,
|
||||
pub state: TextScriptExecutionState,
|
||||
pub flags: TextScriptFlags,
|
||||
pub suspend: bool,
|
||||
pub face: u16,
|
||||
pub current_line: TextScriptLine,
|
||||
pub line_1: Vec<char>,
|
||||
|
|
@ -296,6 +297,7 @@ impl TextScriptVM {
|
|||
scene_script: TextScript::new(),
|
||||
},
|
||||
state: TextScriptExecutionState::Ended,
|
||||
suspend: true,
|
||||
flags: TextScriptFlags(0),
|
||||
face: 0,
|
||||
current_line: TextScriptLine::Line1,
|
||||
|
|
@ -306,12 +308,12 @@ impl TextScriptVM {
|
|||
|
||||
pub fn set_global_script(&mut self, script: TextScript) {
|
||||
self.scripts.global_script = script;
|
||||
self.reset();
|
||||
if !self.suspend { self.reset(); }
|
||||
}
|
||||
|
||||
pub fn set_scene_script(&mut self, script: TextScript) {
|
||||
self.scripts.scene_script = script;
|
||||
self.reset();
|
||||
if !self.suspend { self.reset(); }
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
|
|
@ -333,8 +335,10 @@ impl TextScriptVM {
|
|||
log::info!("Started script: #{:04}", event_num);
|
||||
}
|
||||
|
||||
pub fn run(state: &mut SharedGameState, game_scene: &mut GameScene) -> GameResult {
|
||||
pub fn run(state: &mut SharedGameState, game_scene: &mut GameScene, ctx: &mut Context) -> GameResult {
|
||||
loop {
|
||||
if state.textscript_vm.suspend { break; }
|
||||
|
||||
match state.textscript_vm.state {
|
||||
TextScriptExecutionState::Ended => {
|
||||
state.control_flags.set_flag_x04(false);
|
||||
|
|
@ -342,7 +346,7 @@ impl TextScriptVM {
|
|||
}
|
||||
TextScriptExecutionState::Running(event, ip) => {
|
||||
state.control_flags.set_flag_x04(true);
|
||||
state.textscript_vm.state = TextScriptVM::execute(event, ip, state, game_scene)?;
|
||||
state.textscript_vm.state = TextScriptVM::execute(event, ip, state, game_scene, ctx)?;
|
||||
|
||||
if state.textscript_vm.state == TextScriptExecutionState::Ended {
|
||||
state.textscript_vm.reset();
|
||||
|
|
@ -362,9 +366,12 @@ impl TextScriptVM {
|
|||
println!("char: {} {} {}", chr, remaining, consumed);
|
||||
|
||||
match chr {
|
||||
'\n' if state.textscript_vm.current_line == TextScriptLine::Line1 => {
|
||||
state.textscript_vm.current_line = TextScriptLine::Line2;
|
||||
}
|
||||
'\n' => {
|
||||
state.textscript_vm.line_1.clear();
|
||||
state.textscript_vm.line_2.append(&mut state.textscript_vm.line_1);
|
||||
state.textscript_vm.line_1.append(&mut state.textscript_vm.line_2);
|
||||
}
|
||||
'\r' => {}
|
||||
_ if state.textscript_vm.current_line == TextScriptLine::Line1 => {
|
||||
|
|
@ -406,14 +413,15 @@ impl TextScriptVM {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn execute(event: u16, ip: u32, state: &mut SharedGameState, game_scene: &mut GameScene) -> GameResult<TextScriptExecutionState> {
|
||||
pub fn execute(event: u16, ip: u32, state: &mut SharedGameState, game_scene: &mut GameScene, ctx: &mut Context) -> GameResult<TextScriptExecutionState> {
|
||||
let mut exec_state = state.textscript_vm.state;
|
||||
|
||||
if let Some(bytecode) = state.textscript_vm.scripts.find_script(event) {
|
||||
let mut cursor = Cursor::new(bytecode);
|
||||
cursor.seek(SeekFrom::Start(ip as u64))?;
|
||||
|
||||
let op_maybe: Option<OpCode> = FromPrimitive::from_i32(read_cur_varint(&mut cursor)?);
|
||||
let op_maybe: Option<OpCode> = FromPrimitive::from_i32(read_cur_varint(&mut cursor)
|
||||
.unwrap_or_else(|_| OpCode::END as i32));
|
||||
|
||||
if let Some(op) = op_maybe {
|
||||
println!("opcode: {:?}", op);
|
||||
|
|
@ -511,6 +519,13 @@ impl TextScriptVM {
|
|||
|
||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
OpCode::CLR => {
|
||||
state.textscript_vm.current_line = TextScriptLine::Line1;
|
||||
state.textscript_vm.line_1.clear();
|
||||
state.textscript_vm.line_2.clear();
|
||||
|
||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
OpCode::MSG => {
|
||||
state.textscript_vm.face = 0;
|
||||
state.textscript_vm.current_line = TextScriptLine::Line1;
|
||||
|
|
@ -523,10 +538,27 @@ impl TextScriptVM {
|
|||
|
||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
OpCode::TRA => {
|
||||
let map_id = read_cur_varint(&mut cursor)? as usize;
|
||||
let event_num = read_cur_varint(&mut cursor)? as u16;
|
||||
let pos_x = read_cur_varint(&mut cursor)? as isize * 16 * 0x200;
|
||||
let pos_y = read_cur_varint(&mut cursor)? as isize * 16 * 0x200;
|
||||
|
||||
let mut new_scene = GameScene::new(state, ctx, map_id)?;
|
||||
new_scene.player = game_scene.player.clone();
|
||||
new_scene.player.vel_x = 0;
|
||||
new_scene.player.vel_y = 0;
|
||||
new_scene.player.x = pos_x;
|
||||
new_scene.player.y = pos_y;
|
||||
|
||||
state.textscript_vm.suspend = true;
|
||||
|
||||
state.next_scene = Some(Box::new(new_scene));
|
||||
exec_state = TextScriptExecutionState::Running(event_num, 0);
|
||||
}
|
||||
// unimplemented opcodes
|
||||
// Zero operands
|
||||
OpCode::AEp | OpCode::CAT | OpCode::CIL | OpCode::CLO | OpCode::CLR | OpCode::CPS |
|
||||
OpCode::AEp | OpCode::CAT | OpCode::CIL | OpCode::CLO | OpCode::CPS |
|
||||
OpCode::CRE | OpCode::CSS | OpCode::ESC | OpCode::FLA | OpCode::FMU |
|
||||
OpCode::HMC | OpCode::INI | OpCode::LDP | OpCode::MLP |
|
||||
OpCode::MNA | OpCode::MS2 | OpCode::MS3 |
|
||||
|
|
@ -537,7 +569,7 @@ impl TextScriptVM {
|
|||
}
|
||||
// One operand codes
|
||||
OpCode::BOA | OpCode::BSL | OpCode::FOB | OpCode::FOM | OpCode::QUA | OpCode::UNI |
|
||||
OpCode::MYB | OpCode::MYD | OpCode::FAI | OpCode::FAO | OpCode::FAC |
|
||||
OpCode::MYB | OpCode::MYD | OpCode::FAI | OpCode::FAO |
|
||||
OpCode::GIT | OpCode::NUM | OpCode::DNA | OpCode::DNP |
|
||||
OpCode::MPp | OpCode::SKm | OpCode::SKp | OpCode::EQp | OpCode::EQm |
|
||||
OpCode::ITp | OpCode::ITm | OpCode::AMm | OpCode::UNJ | OpCode::MPJ | OpCode::YNJ |
|
||||
|
|
@ -564,7 +596,7 @@ impl TextScriptVM {
|
|||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
// Four operand codes
|
||||
OpCode::TRA | OpCode::MNP | OpCode::SNP => {
|
||||
OpCode::MNP | OpCode::SNP => {
|
||||
let par_a = read_cur_varint(&mut cursor)?;
|
||||
let par_b = read_cur_varint(&mut cursor)?;
|
||||
let par_c = read_cur_varint(&mut cursor)?;
|
||||
|
|
|
|||
Loading…
Reference in a new issue