mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2024-09-20 17:18:50 +00:00
lightmap thing
This commit is contained in:
parent
449a503fc5
commit
e2cfc898ac
BIN
src/builtin/lightmap/spot.png
Normal file
BIN
src/builtin/lightmap/spot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
|
@ -111,6 +111,9 @@ impl BuiltinFS {
|
|||
FSNode::File("builtin_font_0.png", include_bytes!("builtin/builtin_font_0.png")),
|
||||
FSNode::File("builtin_font_1.png", include_bytes!("builtin/builtin_font_1.png")),
|
||||
FSNode::File("pixtone.pcm", include_bytes!("builtin/pixtone.pcm")),
|
||||
FSNode::Directory("lightmap", vec![
|
||||
FSNode::File("spot.png", include_bytes!("builtin/lightmap/spot.png")),
|
||||
]),
|
||||
])
|
||||
],
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::ggez::{Context, ContextBuilder, filesystem, GameResult};
|
|||
use crate::ggez::conf::{WindowMode, WindowSetup};
|
||||
use crate::ggez::event::{KeyCode, KeyMods};
|
||||
use crate::ggez::graphics;
|
||||
use crate::ggez::graphics::DrawParam;
|
||||
use crate::ggez::graphics::{Canvas, DrawParam};
|
||||
use crate::ggez::input::keyboard;
|
||||
use crate::ggez::mint::ColumnMatrix4;
|
||||
use crate::ggez::nalgebra::Vector2;
|
||||
|
@ -217,6 +217,7 @@ pub fn main() -> GameResult {
|
|||
WindowEvent::CloseRequested => { game.state.shutdown(); }
|
||||
WindowEvent::Resized(_) => {
|
||||
game.state.handle_resize(ctx).unwrap();
|
||||
game.state.lightmap_canvas = Canvas::with_window_size(ctx).unwrap();
|
||||
gfx_window_glutin::update_views(graphics::window(ctx), &mut game.ui.main_color, &mut game.ui.main_depth);
|
||||
}
|
||||
WindowEvent::KeyboardInput {
|
||||
|
|
|
@ -19,10 +19,10 @@ pub struct Menu {
|
|||
pub y: isize,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
selected: usize,
|
||||
pub selected: usize,
|
||||
pub entries: Vec<MenuEntry>,
|
||||
anim_num: u16,
|
||||
anim_wait: u16,
|
||||
entries: Vec<MenuEntry>,
|
||||
}
|
||||
|
||||
static QUOTE_FRAMES: [usize; 4] = [0, 1, 0, 2];
|
||||
|
|
|
@ -190,6 +190,7 @@ impl NPC {
|
|||
}
|
||||
2 => {
|
||||
self.anim_rect = state.constants.npc.n017_health_refill[0];
|
||||
self.anim_num = 0;
|
||||
|
||||
if self.action_counter > 0 {
|
||||
self.action_counter -= 1;
|
||||
|
@ -201,8 +202,10 @@ impl NPC {
|
|||
self.anim_counter += 1;
|
||||
|
||||
if self.anim_counter % 2 == 0 {
|
||||
self.anim_num = 1;
|
||||
self.anim_rect = state.constants.npc.n017_health_refill[1];
|
||||
} else {
|
||||
self.anim_num = 0;
|
||||
self.anim_rect = state.constants.npc.n017_health_refill[0];
|
||||
}
|
||||
|
||||
|
@ -213,6 +216,7 @@ impl NPC {
|
|||
}
|
||||
}
|
||||
4 => {
|
||||
self.anim_num = 1;
|
||||
self.anim_rect = state.constants.npc.n017_health_refill[1];
|
||||
|
||||
if self.action_counter > 0 {
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::common::{Direction, FadeDirection, FadeState, Rect};
|
|||
use crate::entity::GameEntity;
|
||||
use crate::frame::Frame;
|
||||
use crate::ggez::{Context, GameResult, graphics, timer};
|
||||
use crate::ggez::graphics::Color;
|
||||
use crate::ggez::graphics::{BlendMode, Color, Drawable, DrawParam, FilterMode, Vector2};
|
||||
use crate::ggez::nalgebra::clamp;
|
||||
use crate::inventory::{Inventory, TakeExperienceResult};
|
||||
use crate::npc::NPCMap;
|
||||
|
@ -16,6 +16,7 @@ use crate::scene::Scene;
|
|||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::stage::{BackgroundType, Stage};
|
||||
use crate::text_script::{ConfirmSelection, TextScriptExecutionState, TextScriptVM};
|
||||
use crate::texture_set::SizedBatch;
|
||||
use crate::ui::Components;
|
||||
use crate::weapon::WeaponType;
|
||||
|
||||
|
@ -518,6 +519,136 @@ impl GameScene {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_light(&self, x: f32, y: f32, size: f32, color: (u8, u8, u8), batch: &mut SizedBatch) {
|
||||
batch.add_rect_scaled_tinted(x - size * 32.0, y - size * 32.0, color,
|
||||
size,
|
||||
size,
|
||||
&Rect::new(0, 0, 64, 64))
|
||||
}
|
||||
|
||||
fn draw_light_map(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
graphics::set_canvas(ctx, Some(&state.lightmap_canvas));
|
||||
graphics::set_blend_mode(ctx, BlendMode::Add)?;
|
||||
|
||||
graphics::clear(ctx, Color::from_rgb(130, 130, 130));
|
||||
{
|
||||
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "builtin/lightmap/spot")?;
|
||||
|
||||
if state.control_flags.control_enabled() {
|
||||
self.draw_light(((self.player.x - self.frame.x) / 0x200) as f32,
|
||||
((self.player.y - self.frame.y) / 0x200) as f32,
|
||||
3.0, (255, 255, 255), batch);
|
||||
}
|
||||
|
||||
for bullet in self.bullet_manager.bullets.iter() {
|
||||
self.draw_light(((bullet.x - self.frame.x) / 0x200) as f32,
|
||||
((bullet.y - self.frame.y) / 0x200) as f32,
|
||||
1.0, (200, 200, 200), batch);
|
||||
}
|
||||
|
||||
for caret in state.carets.iter() {
|
||||
match caret.ctype {
|
||||
CaretType::ProjectileDissipation | CaretType::Shoot => {
|
||||
self.draw_light(((caret.x - self.frame.x) / 0x200) as f32,
|
||||
((caret.y - self.frame.y) / 0x200) as f32,
|
||||
1.0, (200, 200, 200), batch);
|
||||
}
|
||||
CaretType::LevelUp if caret.direction == Direction::Left => {
|
||||
self.draw_light(((caret.x - self.frame.x) / 0x200) as f32,
|
||||
((caret.y - self.frame.y) / 0x200) as f32,
|
||||
2.0, (0, 100, 160), batch);
|
||||
}
|
||||
CaretType::LevelUp if caret.direction == Direction::Right => {
|
||||
self.draw_light(((caret.x - self.frame.x) / 0x200) as f32,
|
||||
((caret.y - self.frame.y) / 0x200) as f32,
|
||||
2.0, (255, 30, 30), batch);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
for npc_cell in self.npc_map.npcs.values() {
|
||||
let npc = npc_cell.borrow();
|
||||
|
||||
if npc.x < (self.frame.x - 128 * 0x200) || npc.x > (self.frame.x + (state.canvas_size.0 as isize + 128) * 0x200)
|
||||
&& npc.y < (self.frame.y - 128 * 0x200) || npc.y > (self.frame.y + (state.canvas_size.1 as isize + 128) * 0x200) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match npc.npc_type {
|
||||
1 => self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
0.5, (255, 150, 0), batch),
|
||||
4 | 7 => self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
1.0, (200, 200, 200), batch),
|
||||
17 if npc.anim_num == 0 =>
|
||||
self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
2.0, (255, 30, 30), batch),
|
||||
20 if npc.direction == Direction::Right => {
|
||||
self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
2.0, (0, 0, 255), batch);
|
||||
|
||||
if npc.anim_num < 2 {
|
||||
self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
0.5, (0, 0, 255), batch);
|
||||
}
|
||||
}
|
||||
22 if npc.action_num == 1 && npc.anim_num == 1 =>
|
||||
self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
3.0, (0, 0, 255), batch),
|
||||
32 => {
|
||||
self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
3.0, (255, 0, 0), batch);
|
||||
self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
2.0, (255, 0, 0), batch);
|
||||
}
|
||||
38 => {
|
||||
let flicker = 200 + state.effect_rng.range(0..55) as u8;
|
||||
self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
2.0, (flicker, flicker - 80, 0), batch);
|
||||
}
|
||||
66 if npc.action_num == 1 && npc.anim_counter % 2 == 0 =>
|
||||
self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
3.0, (0, 100, 255), batch),
|
||||
67 => self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
2.0, (0, 100, 200), batch),
|
||||
70 => {
|
||||
let flicker = 100 + npc.anim_num as u8 * 50;
|
||||
self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
2.0, (flicker, flicker, flicker), batch);
|
||||
}
|
||||
75 | 77 => self.draw_light(((npc.x - self.frame.x) / 0x200) as f32,
|
||||
((npc.y - self.frame.y) / 0x200) as f32,
|
||||
3.0, (255, 100, 0), batch),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
batch.draw_filtered(FilterMode::Linear, ctx)?;
|
||||
}
|
||||
|
||||
graphics::set_canvas(ctx, None);
|
||||
graphics::set_blend_mode(ctx, BlendMode::Multiply)?;
|
||||
state.lightmap_canvas.set_filter(FilterMode::Linear);
|
||||
state.lightmap_canvas.draw(ctx, DrawParam::new()
|
||||
.scale(Vector2::new(1.0 / state.scale, 1.0 / state.scale)))?;
|
||||
|
||||
graphics::set_blend_mode(ctx, BlendMode::Alpha)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_tiles(&self, state: &mut SharedGameState, ctx: &mut Context, layer: TileLayer) -> GameResult {
|
||||
let tex = match layer {
|
||||
TileLayer::Snack => "Npc/NpcSym",
|
||||
|
@ -849,6 +980,9 @@ impl Scene for GameScene {
|
|||
self.draw_tiles(state, ctx, TileLayer::Foreground)?;
|
||||
self.draw_tiles(state, ctx, TileLayer::Snack)?;
|
||||
self.draw_carets(state, ctx)?;
|
||||
if state.enhanced_graphics {
|
||||
self.draw_light_map(state, ctx)?;
|
||||
}
|
||||
self.draw_black_bars(state, ctx)?;
|
||||
|
||||
if state.control_flags.control_enabled() {
|
||||
|
|
|
@ -26,8 +26,8 @@ impl TitleScene {
|
|||
Self {
|
||||
tick: 0,
|
||||
current_menu: CurrentMenu::MainMenu,
|
||||
main_menu: Menu::new(0, 0, 100, 5 * 14 + 6),
|
||||
option_menu: Menu::new(0, 0, 180, 5 * 14 + 6),
|
||||
main_menu: Menu::new(0, 0, 100, 1 * 14 + 6),
|
||||
option_menu: Menu::new(0, 0, 180, 1 * 14 + 6),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,13 +89,16 @@ impl Scene for TitleScene {
|
|||
self.main_menu.push_entry(MenuEntry::Active("Options".to_string()));
|
||||
self.main_menu.push_entry(MenuEntry::Disabled("Editor".to_string()));
|
||||
self.main_menu.push_entry(MenuEntry::Active("Quit".to_string()));
|
||||
self.main_menu.height = self.main_menu.entries.len() * 14 + 6;
|
||||
|
||||
self.option_menu.push_entry(MenuEntry::Toggle("50 FPS timing".to_string(), state.timing_mode == TimingMode::_50Hz));
|
||||
self.option_menu.push_entry(MenuEntry::Toggle("Linear scaling".to_string(), ctx.filter_mode == FilterMode::Linear));
|
||||
self.option_menu.push_entry(MenuEntry::Toggle("Enhanced graphics".to_string(), state.enhanced_graphics));
|
||||
self.option_menu.push_entry(MenuEntry::Toggle("2x Speed hack".to_string(), state.speed_hack));
|
||||
self.option_menu.push_entry(MenuEntry::Active("Join our Discord".to_string()));
|
||||
self.option_menu.push_entry(MenuEntry::Disabled(DISCORD_LINK.to_owned()));
|
||||
self.option_menu.push_entry(MenuEntry::Active("Back".to_string()));
|
||||
self.option_menu.height = self.option_menu.entries.len() * 14 + 6;
|
||||
}
|
||||
|
||||
self.main_menu.x = ((state.canvas_size.0 - self.main_menu.width as f32) / 2.0).floor() as isize;
|
||||
|
@ -152,16 +155,24 @@ impl Scene for TitleScene {
|
|||
}
|
||||
MenuSelectionResult::Selected(2, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
*value = !(*value);
|
||||
state.set_speed_hack(*value);
|
||||
state.enhanced_graphics = !state.enhanced_graphics;
|
||||
|
||||
*value = state.enhanced_graphics;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(3, _) => {
|
||||
MenuSelectionResult::Selected(3, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.set_speed_hack(!state.speed_hack);
|
||||
|
||||
*value = state.speed_hack;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(4, _) => {
|
||||
if let Err(e) = webbrowser::open(DISCORD_LINK) {
|
||||
log::warn!("Error opening web browser: {}", e);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(5, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(6, _) | MenuSelectionResult::Canceled => {
|
||||
self.current_menu = CurrentMenu::MainMenu;
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -18,6 +18,7 @@ use crate::stage::StageData;
|
|||
use crate::str;
|
||||
use crate::text_script::{TextScriptExecutionState, TextScriptVM};
|
||||
use crate::texture_set::TextureSet;
|
||||
use crate::ggez::graphics::Canvas;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||
pub enum TimingMode {
|
||||
|
@ -58,6 +59,8 @@ pub struct SharedGameState {
|
|||
pub scale: f32,
|
||||
pub god_mode: bool,
|
||||
pub speed_hack: bool,
|
||||
pub enhanced_graphics: bool,
|
||||
pub lightmap_canvas: Canvas,
|
||||
pub canvas_size: (f32, f32),
|
||||
pub screen_size: (f32, f32),
|
||||
pub next_scene: Option<Box<dyn Scene>>,
|
||||
|
@ -115,6 +118,8 @@ impl SharedGameState {
|
|||
scale,
|
||||
god_mode: false,
|
||||
speed_hack: false,
|
||||
enhanced_graphics: true,
|
||||
lightmap_canvas: Canvas::with_window_size(ctx)?,
|
||||
screen_size,
|
||||
canvas_size,
|
||||
next_scene: None,
|
||||
|
|
|
@ -26,26 +26,32 @@ pub struct SizedBatch {
|
|||
}
|
||||
|
||||
impl SizedBatch {
|
||||
#[inline(always)]
|
||||
pub fn width(&self) -> usize {
|
||||
self.width
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn height(&self) -> usize {
|
||||
self.height
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn dimensions(&self) -> (usize, usize) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn real_dimensions(&self) -> (usize, usize) {
|
||||
(self.real_width, self.real_height)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn to_rect(&self) -> common::Rect<usize> {
|
||||
common::Rect::<usize>::new(0, 0, self.width, self.height)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn clear(&mut self) {
|
||||
self.batch.clear();
|
||||
}
|
||||
|
@ -58,6 +64,7 @@ impl SizedBatch {
|
|||
self.batch.add(param);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn add_rect(&mut self, x: f32, y: f32, rect: &common::Rect<usize>) {
|
||||
self.add_rect_scaled(x, y, self.scale_x, self.scale_y, rect)
|
||||
}
|
||||
|
@ -95,8 +102,13 @@ impl SizedBatch {
|
|||
self.batch.add(param);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn draw(&mut self, ctx: &mut Context) -> GameResult {
|
||||
self.batch.set_filter(ctx.filter_mode);
|
||||
self.draw_filtered(ctx.filter_mode, ctx)
|
||||
}
|
||||
|
||||
pub fn draw_filtered(&mut self, filter: FilterMode, ctx: &mut Context) -> GameResult {
|
||||
self.batch.set_filter(filter);
|
||||
self.batch.draw(ctx, DrawParam::new())?;
|
||||
self.batch.clear();
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in a new issue