1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2025-07-27 15:31:49 +00:00

Compare commits

...

5 commits

Author SHA1 Message Date
Alula ad4fc4b481
recolor the water 2020-12-06 20:31:36 +01:00
Alula 035b2c2848
Do not process NPC collissions if player isn't alive 2020-12-06 16:48:43 +01:00
Alula 20be51bb72
no thx 2020-12-06 16:42:05 +01:00
Alula 203a4a1180
Let CI override version displayed in menu 2020-12-06 16:41:12 +01:00
Alula 5f259b572e
rect serialization 2020-12-06 15:53:14 +01:00
9 changed files with 87 additions and 12 deletions

View file

@ -35,6 +35,7 @@ cache:
# - cargo test --verbose --all --no-fail-fast
build_script:
- set DRS_BUILD_VERSION_OVERRIDE=%APPVEYOR_BUILD_VERSION%
- cargo build --release --bin doukutsu-rs
- mkdir release
- copy target\release\doukutsu-rs.exe release

View file

@ -1,5 +1,5 @@
[package]
authors = ["Alula <julekonopinska@gmail.com>"]
authors = ["Alula"]
edition = "2018"
name = "doukutsu-rs"
version = "0.1.0"

View file

@ -11,16 +11,18 @@ layout (std140) uniform Globals {
layout (std140) uniform WaterShaderParams {
vec2 u_Resolution;
vec2 u_FramePos;
float u_Tick;
};
void main() {
vec2 wave = v_Uv;
wave.x += sin(v_Uv.x * 40.0 + u_Tick / 20.0) * (sin(u_Tick / 10.0) * 0.01);
wave.y -= cos(v_Uv.y * 20.0 + u_Tick / 5.0) * (sin(u_Tick / 20.0) * 0.01);
wave.x += sin((-u_FramePos.y / u_Resolution.y + v_Uv.x * 16.0) + u_Tick / 20.0) * 2.0 / u_Resolution.x;
wave.y -= cos((-u_FramePos.x / u_Resolution.x + v_Uv.y * 16.0) + u_Tick / 5.0) * 2.0 / u_Resolution.y;
float off = 0.4 / u_Resolution.y;
vec4 color = texture(t_Texture, wave);
color.r = texture(t_Texture, wave + off).r;
color.b = texture(t_Texture, wave - off).b;
Target0 = vec4(0.7, 0.8, 1.2, 1.0) * color * v_Color;
Target0 = (vec4(0.4, 0.6, 0.8, 1.0) * 0.3) + (color * v_Color * 0.7);
}

View file

@ -1,13 +1,23 @@
use std::cmp::Ordering;
use std::fmt;
use lazy_static::lazy_static;
use num_traits::{AsPrimitive, Num};
use serde::{Deserialize, Serialize};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use serde::de::{SeqAccess, Visitor};
use serde::ser::SerializeTupleStruct;
use crate::bitfield;
/// Multiply cave story degrees (0-255, which corresponds to 0°-360°) with this to get
/// respective value in radians.
pub const CDEG_RAD: f64 = std::f64::consts::PI / 128.0;
lazy_static! {
pub static ref VERSION_BANNER: String = {
let version = option_env!("DRS_BUILD_VERSION_OVERRIDE").unwrap_or(env!("CARGO_PKG_VERSION"));
format!("doukutsu-rs {}", version)
};
}
bitfield! {
#[derive(Clone, Copy)]
@ -217,7 +227,7 @@ impl Direction {
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy)]
pub struct Rect<T: Num + PartialOrd + Copy = isize> {
pub left: T,
pub top: T,
@ -279,6 +289,63 @@ impl<T: Num + PartialOrd + Copy + AsPrimitive<f32>> Into<ggez::graphics::Rect> f
}
}
impl<T: Num + PartialOrd + Copy + Serialize> Serialize for Rect<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_tuple_struct("Rect", 4)?;
state.serialize_field(&self.left)?;
state.serialize_field(&self.top)?;
state.serialize_field(&self.right)?;
state.serialize_field(&self.bottom)?;
state.end()
}
}
macro_rules! rect_deserialze {
($num_type: ident) => {
impl<'de> Deserialize<'de> for Rect<$num_type> {
fn deserialize<D>(deserializer: D) -> Result<Rect<$num_type>, D::Error>
where
D: Deserializer<'de>,
{
struct RectVisitor;
impl<'de> Visitor<'de> for RectVisitor {
type Value = Rect<$num_type>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("Expected Rect structure.")
}
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
where
V: SeqAccess<'de>
{
let invalid_length = || {
de::Error::invalid_length(0, &self)
};
let left = seq.next_element()?.ok_or_else(invalid_length)?;
let top = seq.next_element()?.ok_or_else(invalid_length)?;
let right = seq.next_element()?.ok_or_else(invalid_length)?;
let bottom = seq.next_element()?.ok_or_else(invalid_length)?;
Ok(Rect { left, top, right, bottom })
}
}
deserializer.deserialize_tuple_struct("Rect", 4, RectVisitor)
}
}
};
}
rect_deserialze!(u8);
rect_deserialze!(u16);
rect_deserialze!(isize);
rect_deserialze!(usize);
#[inline(always)]
pub fn fix9_scale(val: isize, scale: f32) -> f32 {
(val as f64 * scale as f64 / 512.0).floor() as f32 / scale

View file

@ -163,7 +163,6 @@ impl Game {
fn key_down_event(&mut self, key_code: KeyCode, _key_mod: KeyMods, repeat: bool) {
if repeat { return; }
// todo: proper keymaps?
let state = &mut self.state;
match key_code {
KeyCode::F7 => { state.set_speed(1.0) }

View file

@ -318,6 +318,10 @@ impl Player {
}
pub fn tick_npc_collisions(&mut self, id: TargetPlayer, state: &mut SharedGameState, npc_map: &mut NPCMap, inventory: &mut Inventory) {
if !self.cond.alive() {
return;
}
for npc_cell in npc_map.npcs.values() {
let mut npc = npc_cell.borrow_mut();
if !npc.cond.alive() { continue; }

View file

@ -649,8 +649,11 @@ impl GameScene {
}
fn draw_water(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
let (frame_x, frame_y) = self.frame.xy_interpolated(state.frame_time, state.scale);
{
state.shaders.water_shader_params.resolution = [state.canvas_size.0, state.canvas_size.1];
state.shaders.water_shader_params.frame_pos = [frame_x, frame_y];
state.shaders.water_shader_params.t = self.tick as f32;
let _lock = graphics::use_shader(ctx, &state.shaders.water_shader);
state.shaders.water_shader.send(ctx, state.shaders.water_shader_params)?;
@ -666,8 +669,6 @@ impl GameScene {
// cheap, clones a reference underneath
let mut tmp_batch = SpriteBatch::new(state.tmp_canvas.image().clone());
let (frame_x, frame_y) = self.frame.xy_interpolated(state.frame_time, state.scale);
let tile_start_x = clamp(self.frame.x / 0x200 / 16, 0, self.stage.map.width as isize) as usize;
let tile_start_y = clamp(self.frame.y / 0x200 / 16, 0, self.stage.map.height as isize) as usize;
let tile_end_x = clamp((self.frame.x / 0x200 + 8 + state.canvas_size.0 as isize) / 16 + 1, 0, self.stage.map.width as isize) as usize;

View file

@ -1,7 +1,7 @@
use ggez::{Context, GameResult, graphics};
use ggez::graphics::Color;
use crate::common::Rect;
use crate::common::{Rect, VERSION_BANNER};
use crate::menu::{Menu, MenuEntry, MenuSelectionResult};
use crate::scene::Scene;
use crate::shared_game_state::{SharedGameState, TimingMode};
@ -75,7 +75,6 @@ impl TitleScene {
}
}
static ENGINE_VERSION: &str = "doukutsu-rs 0.1.0";
// asset copyright for freeware version
static COPYRIGHT_PIXEL: &str = "2004.12 Studio Pixel";
// asset copyright for Nicalis
@ -235,7 +234,7 @@ impl Scene for TitleScene {
batch.draw(ctx)?;
}
self.draw_text_centered(ENGINE_VERSION, state.canvas_size.1 - 15.0, state, ctx)?;
self.draw_text_centered(VERSION_BANNER.as_str(), state.canvas_size.1 - 15.0, state, ctx)?;
if state.constants.is_switch {
self.draw_text_centered(COPYRIGHT_NICALIS_SWITCH, state.canvas_size.1 - 30.0, state, ctx)?;

View file

@ -5,6 +5,7 @@ use ggez::{Context, GameResult};
gfx_defines! {
constant WaterShaderParams {
resolution: [f32; 2] = "u_Resolution",
frame_pos: [f32; 2] = "u_FramePos",
t: f32 = "u_Tick",
}
}
@ -19,6 +20,7 @@ impl Shaders {
let water_shader_params = WaterShaderParams {
t: 0.0,
resolution: [0.0, 0.0],
frame_pos: [0.0, 0.0],
};
Ok(Shaders {