support for dt (naive)
This commit is contained in:
parent
d6b8e589fb
commit
b221f65748
5 changed files with 82 additions and 44 deletions
|
@ -4,8 +4,12 @@ members = [
|
|||
"client",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
opt-level = 3
|
||||
|
||||
[profile.minsized]
|
||||
inherits = "release"
|
||||
lto = true
|
||||
opt-level = 'z'
|
||||
opt-level = 's'
|
||||
strip = true
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use minifb::{Key, ScaleMode, Window, WindowOptions, Scale};
|
||||
extern crate pirates;
|
||||
use pirates::{WIDTH, HEIGHT};
|
||||
|
@ -45,9 +47,16 @@ fn main() {
|
|||
#[cfg(feature = "gamepad")]
|
||||
let mut gamepad_handle = None;
|
||||
|
||||
let mut frame_start: SystemTime = SystemTime::now();
|
||||
|
||||
while window.is_open() && !window.is_key_down(Key::Escape) {
|
||||
let last_frame = frame_start.elapsed().unwrap().as_micros();
|
||||
frame_start = SystemTime::now();
|
||||
|
||||
buffer.clear();
|
||||
unsafe {
|
||||
pirates::LAST_FRAME_TIME = last_frame as f32 / 1000.0;
|
||||
|
||||
pirates::frame_entry();
|
||||
for pix in pirates::BUFFER {
|
||||
// AABBGGRR to 00RRGGBB
|
||||
|
|
|
@ -6,7 +6,18 @@ const width = 160;
|
|||
const height = 144;
|
||||
|
||||
function blit_frame() {
|
||||
ctx.putImageData(image, 0, 0);
|
||||
// this has an insane performance impact, but it is required when using an
|
||||
// allocator from wasm, as there is no way to update the internal pointer
|
||||
image = new ImageData(
|
||||
new Uint8ClampedArray(
|
||||
memory.buffer,
|
||||
exports.BUFFER.value,
|
||||
4 * width * height,
|
||||
),
|
||||
width,
|
||||
);
|
||||
|
||||
ctx.putImageData(image, 0, 0, 0, 0, width-1, height-1);
|
||||
}
|
||||
|
||||
function blit_text(text, len, x, y, size) {
|
||||
|
@ -47,21 +58,27 @@ async function init() {
|
|||
document.getElementById("body").onkeydown=keyboard_callback;
|
||||
|
||||
memory = instance.exports.memory
|
||||
const buffer_address = instance.exports.BUFFER.value;
|
||||
image = new ImageData(
|
||||
new Uint8ClampedArray(
|
||||
memory.buffer,
|
||||
buffer_address,
|
||||
4 * width * height,
|
||||
),
|
||||
width,
|
||||
);
|
||||
|
||||
instance.exports.frame_entry();
|
||||
ctx.textBaseline = 'top'
|
||||
ctx.textAlign = 'left';
|
||||
|
||||
const render = () => {
|
||||
var last;
|
||||
var elapsed;
|
||||
|
||||
const render = (time) => {
|
||||
if(!last) { elapsed = 0; }
|
||||
else {
|
||||
elapsed = time-last;
|
||||
}
|
||||
last=time;
|
||||
|
||||
if(!elapsed) {
|
||||
elapsed = 0.0;
|
||||
}
|
||||
|
||||
const FRAME_TIME = new Float32Array(exports.memory.buffer, exports.LAST_FRAME_TIME, 1);
|
||||
FRAME_TIME[0] = elapsed;
|
||||
|
||||
instance.exports.frame_entry();
|
||||
|
||||
requestAnimationFrame(render);
|
||||
|
|
|
@ -7,10 +7,6 @@ edition = "2021"
|
|||
default = ["wasm"]
|
||||
wasm = ["wee_alloc"]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
opt-level = 's'
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
||||
|
|
|
@ -45,6 +45,9 @@ fn draw_text(text: &str, x: i32, y: i32, size: u8) {
|
|||
pub const WIDTH: usize = 160;
|
||||
pub const HEIGHT: usize = 144;
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut LAST_FRAME_TIME: f32 = 0.0;
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut BUFFER: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT];
|
||||
|
||||
|
@ -75,7 +78,12 @@ static MAP: [u8; MAP_WIDTH * MAP_HEIGHT] = [ // should deflate to smaller than b
|
|||
|
||||
static CAMERA: Mutex<[f32; 3]> = Mutex::new([0.0, 0.0, 0.18]);
|
||||
|
||||
static BOAT: Mutex<Boat> = Mutex::new(Boat { x: 0.0, y: 0.0, theta: 0.0, vel: 0.0 });
|
||||
static BOAT: Mutex<Boat> = Mutex::new(Boat {
|
||||
x: 0.0, y: 0.0,
|
||||
theta: 0.0,
|
||||
vel: 0.0,
|
||||
sail: 1.0,
|
||||
});
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn keyboard_input() {
|
||||
|
@ -103,24 +111,31 @@ fn render_frame(buffer: &mut [u32; WIDTH*HEIGHT]) {
|
|||
let mut camera = CAMERA.lock();
|
||||
let mut boat = BOAT.lock();
|
||||
|
||||
//camera[0] += 1.0;
|
||||
|
||||
let gain = unsafe { // very much an approximation of constant-velocity animation
|
||||
LAST_FRAME_TIME.min(100.0) / (1000.0 / 20.0) // normalize to 20fps, cap simulation at 10fps
|
||||
};
|
||||
while let Some(key) = INPUTS.lock().pop() {
|
||||
match key[0] { // [tag:input_handler]
|
||||
38 => camera[1] -= 10.0*camera[2], // up
|
||||
40 => camera[1] += 10.0*camera[2], // down
|
||||
37 => camera[0] -= 10.0*camera[2], // left
|
||||
39 => camera[0] += 10.0*camera[2], // right
|
||||
191 => *camera = [0.0, 0.0, 0.18], // reset camera (/)
|
||||
38 => camera[1] -= gain*10.0*camera[2], // up
|
||||
40 => camera[1] += gain*10.0*camera[2], // down
|
||||
37 => camera[0] -= gain*10.0*camera[2], // left
|
||||
39 => camera[0] += gain*10.0*camera[2], // right
|
||||
191 => {
|
||||
*camera = [
|
||||
noise::lerp(camera[0], 0.00, (gain * 0.25).min(1.0)),
|
||||
noise::lerp(camera[1], 0.00, (gain * 0.25).min(1.0)),
|
||||
noise::lerp(camera[2], 0.18, (gain * 0.25).min(1.0)),
|
||||
]
|
||||
}, // reset camera (/)
|
||||
82 => boat.set_pos(Vector2::zeros()), // reset boat (r)
|
||||
61 => camera[2] *= 0.9, // +
|
||||
173 => camera[2] *= 1.1, // -
|
||||
65 => boat.theta -= 10.0, // A
|
||||
68 => boat.theta += 10.0, // D
|
||||
0 => camera[2] *= 1.0 - (key[1] as f32 - 127.0) * 0.0004, // analog zoom
|
||||
1 => boat.theta += (key[1] as f32 - 127.0) * 0.031, // analog rudder
|
||||
3 => camera[1] -= (key[1] as f32 - 127.0) * 0.004, // pan[y]
|
||||
4 => camera[0] += (key[1] as f32 - 127.0) * 0.004, // pan[x]
|
||||
61 => camera[2] *= 1.0 - 0.1*gain, // +
|
||||
173 => camera[2] *= 1.0 + 0.1*gain, // -
|
||||
65 => boat.theta -= gain*10.0, // A
|
||||
68 => boat.theta += gain*10.0, // D
|
||||
0 => camera[2] *= 1.0 - (key[1] as f32 - 127.0) * 0.0004 * gain, // analog zoom
|
||||
1 => boat.theta += gain * (key[1] as f32 - 127.0) * 0.062, // analog rudder
|
||||
3 => camera[1] -= gain * (key[1] as f32 - 127.0) * 0.1 * camera[2], // pan[y]
|
||||
4 => camera[0] += gain * (key[1] as f32 - 127.0) * 0.1 * camera[2], // pan[x]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -135,11 +150,12 @@ fn render_frame(buffer: &mut [u32; WIDTH*HEIGHT]) {
|
|||
if depth < -0.04 {
|
||||
boat.vel = 0.0;
|
||||
} else if depth < 0.0 {
|
||||
boat.vel *= (1.0 - depth) * 0.25;
|
||||
boat.vel *= 1.0 + (depth * gain * 30.2).min(0.0);
|
||||
}
|
||||
|
||||
if depth > -0.04 {
|
||||
boat.go_smooth(-vel * 0.42);
|
||||
boat.vel = noise::lerp(boat.vel, vel * 0.82, 0.13 * gain);
|
||||
boat.go(gain);
|
||||
}
|
||||
|
||||
// draw sea
|
||||
|
@ -256,6 +272,8 @@ struct Boat {
|
|||
y: f32,
|
||||
theta: f32,
|
||||
vel: f32,
|
||||
/// sail height 0-1
|
||||
sail: f32,
|
||||
}
|
||||
|
||||
impl Boat {
|
||||
|
@ -269,26 +287,20 @@ impl Boat {
|
|||
}
|
||||
|
||||
fn get_intensity(self: &Self, wind_direction: f32) -> f32 {
|
||||
libm::sinf((self.theta-wind_direction)/RAD_TO_DEG)
|
||||
libm::sinf((self.theta-wind_direction)/RAD_TO_DEG) * self.sail
|
||||
}
|
||||
|
||||
fn get_velocity(self: &Self, wind_direction: f32) -> f32 {
|
||||
libm::fabsf(self.get_intensity(wind_direction))
|
||||
}
|
||||
|
||||
fn go_smooth(self: &mut Self, vel: f32) {
|
||||
self.vel = noise::lerp(self.vel, vel, 0.09);
|
||||
|
||||
self.go(self.vel);
|
||||
}
|
||||
|
||||
fn go(self: &mut Self, velocity: f32) {
|
||||
fn go(self: &mut Self, gain: f32) {
|
||||
let cos = libm::cosf((self.theta+ 45.0)/RAD_TO_DEG);
|
||||
let sin = libm::sinf((self.theta+ 45.0)/RAD_TO_DEG);
|
||||
let unit = Vector2::new(
|
||||
cos - sin,
|
||||
sin + cos);
|
||||
self.set_pos(self.get_pos() + unit * velocity);
|
||||
self.set_pos(self.get_pos() + unit * -self.vel * gain);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue