From 2978ea95ca28f8c40a4cd8665bed3e327fee3d11 Mon Sep 17 00:00:00 2001 From: c0repwn3r Date: Fri, 30 Jun 2023 10:42:34 -0400 Subject: [PATCH] particle system --- client/src/index.ts | 210 +++++++++++++++++++++++++++++++++- client/src/particle.ts | 76 ++++++++++++ server/src/orbit/constants.rs | 2 +- 3 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 client/src/particle.ts diff --git a/client/src/index.ts b/client/src/index.ts index 3f42faff63fa02a4c2cfff574613682d1d17ff96..4607ec6dc1ca5fc7f8b42dae2180bc18cd25c3b4 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -19,6 +19,7 @@ import { } from "./protocol/message_c2s"; import {encode} from "./serde"; import {InputType} from "./protocol/input"; +import {createParticle, tickAndDrawParticles} from "./particle"; logSetup(); const logger = new Logger("client"); @@ -290,7 +291,14 @@ async function client_main(server: string, username: string, texture_quality: st global.client?.socket.send(encode(MessageC2SInput_packetInfo.type, msg)); } - let render = () => { + let t = performance.now(); + let delta = 0.0; + + let render = (newT: DOMHighResTimeStamp) => { + + delta = newT - t; + t = newT; + let viewer_size_x = global.canvas.width; let viewer_size_y = global.canvas.height; @@ -494,6 +502,206 @@ async function client_main(server: string, username: string, texture_quality: st } } + function calculateRotated(x: number, y: number, rotation: number): [number, number] { + let x2 = x * Math.cos(rotation) - y * Math.sin(rotation); + let y2 = x * Math.sin(rotation) + y * Math.cos(rotation); + return [x2, y2]; + } + + const thruster_r = 52; + const thruster_g = 189; + const thruster_b = 235; + + let thruster_counter = 0; + + if (global.me !== null) { + console.log(thruster_counter); + thruster_counter += 1; + if (thruster_counter > 200) { + console.log("resetting counter"); + thruster_counter = 0; + } else if (thruster_counter == 1) { + console.log("drawing particle"); + if (global.keys.up) { + // two backward thrusters + // this one is blue + createParticle({ + x: global.me.x + calculateRotated(-25, 25, global.me.rotation)[0], + y: global.me.y + calculateRotated(-25, 25, global.me.rotation)[1], + lifetime: 500, + timer: 0, + startSize: 10, + finalSize: 50, + startRotation: 0, + finalRotation: 180, + startOpacity: 40, + endOpacity: 0, + startR: thruster_r, + startG: thruster_g, + startB: thruster_b, + endR: thruster_r, + endG: thruster_g, + endB: thruster_b + }); + + // two backward thrusters + // this one is pink + createParticle({ + x: global.me.x + calculateRotated(25, -25, global.me.rotation + Math.PI/2)[0], + y: global.me.y + calculateRotated(25, -25, global.me.rotation + Math.PI/2)[1], + lifetime: 500, + timer: 0, + startSize: 10, + finalSize: 50, + startRotation: 0, + finalRotation: 180, + startOpacity: 40, + endOpacity: 0, + startR: thruster_r, + startG: thruster_g, + startB: thruster_b, + endR: thruster_r, + endG: thruster_g, + endB: thruster_b + }); + } + + if (global.keys.down) { + // two backward thrusters + // this one is blue + createParticle({ + x: global.me.x + calculateRotated(25, -25, global.me.rotation)[0], + y: global.me.y + calculateRotated(25, -25, global.me.rotation)[1], + lifetime: 500, + timer: 0, + startSize: 10, + finalSize: 50, + startRotation: 0, + finalRotation: 180, + startOpacity: 40, + endOpacity: 0, + startR: thruster_r, + startG: thruster_g, + startB: thruster_b, + endR: thruster_r, + endG: thruster_g, + endB: thruster_b + }); + + // two backward thrusters + // this one is pink + createParticle({ + x: global.me.x + calculateRotated(-25, 25, global.me.rotation + Math.PI/2)[0], + y: global.me.y + calculateRotated(-25, 25, global.me.rotation + Math.PI/2)[1], + lifetime: 500, + timer: 0, + startSize: 10, + finalSize: 50, + startRotation: 0, + finalRotation: 180, + startOpacity: 40, + endOpacity: 0, + startR: thruster_r, + startG: thruster_g, + startB: thruster_b, + endR: thruster_r, + endG: thruster_g, + endB: thruster_b + }); + } + + if (global.keys.left) { + // two backward thrusters + // this one is blue + createParticle({ + x: global.me.x + calculateRotated(25, 25, global.me.rotation)[0], + y: global.me.y + calculateRotated(25, 25, global.me.rotation)[1], + lifetime: 500, + timer: 0, + startSize: 10, + finalSize: 50, + startRotation: 0, + finalRotation: 180, + startOpacity: 40, + endOpacity: 0, + startR: thruster_r, + startG: thruster_g, + startB: thruster_b, + endR: thruster_r, + endG: thruster_g, + endB: thruster_b + }); + + // two backward thrusters + // this one is pink + createParticle({ + x: global.me.x + calculateRotated(-25, 25, global.me.rotation + Math.PI/2)[0], + y: global.me.y + calculateRotated(-25, 25, global.me.rotation + Math.PI/2)[1], + lifetime: 500, + timer: 0, + startSize: 10, + finalSize: 50, + startRotation: 0, + finalRotation: 180, + startOpacity: 40, + endOpacity: 0, + startR: thruster_r, + startG: thruster_g, + startB: thruster_b, + endR: thruster_r, + endG: thruster_g, + endB: thruster_b + }); + } + + if (global.keys.right) { + // two backward thrusters + // this one is blue + createParticle({ + x: global.me.x + calculateRotated(-25, 25, global.me.rotation)[0], + y: global.me.y + calculateRotated(-25, 25, global.me.rotation)[1], + lifetime: 500, + timer: 0, + startSize: 10, + finalSize: 50, + startRotation: 0, + finalRotation: 180, + startOpacity: 40, + endOpacity: 0, + startR: thruster_r, + startG: thruster_g, + startB: thruster_b, + endR: thruster_r, + endG: thruster_g, + endB: thruster_b + }); + + // two backward thrusters + // this one is pink + createParticle({ + x: global.me.x + calculateRotated(-25, -25, global.me.rotation + Math.PI/2)[0], + y: global.me.y + calculateRotated(-25, -25, global.me.rotation + Math.PI/2)[1], + lifetime: 500, + timer: 0, + startSize: 10, + finalSize: 50, + startRotation: 0, + finalRotation: 180, + startOpacity: 40, + endOpacity: 0, + startR: thruster_r, + startG: thruster_g, + startB: thruster_b, + endR: thruster_r, + endG: thruster_g, + endB: thruster_b + }); + } + } + + tickAndDrawParticles(delta); + } + requestAnimationFrame(render); } requestAnimationFrame(render); diff --git a/client/src/particle.ts b/client/src/particle.ts new file mode 100644 index 0000000000000000000000000000000000000000..ee35c5fb0c469485a930589def4abc48024a68eb --- /dev/null +++ b/client/src/particle.ts @@ -0,0 +1,76 @@ +import {global} from "./index"; + +export interface Particle { + x: number, + y: number, + lifetime: number, + timer: number, + startSize: number, + finalSize: number, + startRotation: number, + finalRotation: number, + startOpacity: number, + endOpacity: number, + startR: number, + endR: number, + startG: number, + endG: number, + startB: number, + endB: number +} + +let particles: Particle[] = []; + +export function createParticle(particle: Particle) { + particles.push(particle); +} + +function lerp(start: number, end: number, time: number): number { + return start + time * (end - start); +} + +export function drawParticle(particle: Particle) { + let t = particle.timer / particle.lifetime; + let size = lerp(particle.startSize, particle.finalSize, t); + let rotation = lerp(particle.startRotation, particle.finalRotation, t); + + global.context.save(); + + global.context.translate(particle.x - global.me!.x, particle.y - global.me!.y); + + global.context.rotate(rotation); + + let opacity = Math.trunc(lerp(particle.startOpacity, particle.endOpacity, t)); + let r = Math.trunc(lerp(particle.startR, particle.endR, t)); + let g = Math.trunc(lerp(particle.startG, particle.endG, t)); + let b = Math.trunc(lerp(particle.startB, particle.endB, t)); + + global.context.fillStyle = `rgb(${r} ${g} ${b} / ${opacity}%)`; + global.context.fillRect(-size/2, -size/2, size, size); + + global.context.restore(); +} + +export function drawParticles() { + for (let i = 0; i < particles.length; i++) { + drawParticle(particles[i]); + } +} + +export function tickParticles(delta: number) { + let keptParticles = [] + for (let i = 0; i < particles.length; i++) { + particles[i].timer += delta; + if (!(particles[i].timer > particles[i].lifetime)) { + keptParticles.push(particles[i]); + } else { + console.log("dropping particle"); + } + } + particles = keptParticles; +} + +export function tickAndDrawParticles(delta: number) { + tickParticles(delta); + drawParticles(); +} \ No newline at end of file diff --git a/server/src/orbit/constants.rs b/server/src/orbit/constants.rs index 8e0236e7d26de9b9cea0ed442317e7212ca4c703..991a2b30ea6632e238038c71fc7b5743b212b2c0 100644 --- a/server/src/orbit/constants.rs +++ b/server/src/orbit/constants.rs @@ -1,7 +1,7 @@ pub const GAME_SCALE_DISTANCE: f64 = 0.000_156_786_5; // 1000 / EARTH_RADIUS_RL pub const GAME_SCALE_MASS: f64 = 0.000_000_000_000_000_000_000_669_792_364_367_046_3; // 4000 / EARTH_MASS_RL pub const GAME_SCALE_TIME: f64 = 0.000_514_403_292_181_07; // 1200 / MOON_ORBIT_TIME_RL -pub const GAME_ORBITS_ENABLED: bool = false; +pub const GAME_ORBITS_ENABLED: bool = true; pub const EARTH_RADIUS_BIAS: f64 = 1.0; pub const EARTH_MASS_BIAS: f64 = 1.0;