lightmap thing

This commit is contained in:
Alula 2020-09-25 21:25:40 +02:00
parent 449a503fc5
commit e2cfc898ac
No known key found for this signature in database
GPG Key ID: 3E00485503A1D8BA
9 changed files with 181 additions and 11 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -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")),
]),
])
],
}

View File

@ -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 {

View File

@ -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];

View File

@ -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 {

View File

@ -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() {

View File

@ -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;
}
_ => {}

View File

@ -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,

View File

@ -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(())