Skip to content

Commit 64ee6e1

Browse files
committed
learn some rust and wasm
1 parent 0c3d6b4 commit 64ee6e1

File tree

7 files changed

+411
-123
lines changed

7 files changed

+411
-123
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
node_modules
44

55
dist
6-
.next
6+
.next
7+
8+
target

web/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ COPY ./ ./
77

88
EXPOSE ${PORT}
99

10-
RUN npm run build
10+
RUN yarn build
1111
CMD ["yarn", "dev"]

web/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"scripts": {
66
"dev": "next dev",
77
"build": "next build",
8+
"build:wasm": "cd wasm && wasm-pack build --target web --out-name wasm --out-dir ./main",
89
"start": "next start",
910
"lint": "next lint"
1011
},

web/util/Canvas.tsx

+51-121
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
// inspired collision detection system from implementation in https://github.com/JBreidfjord/particle-sim
33
// lol looks like we didn't use particle collision in the end
44

5-
import React, { useRef, useEffect } from 'react'
5+
import React, { useRef, useEffect } from 'react';
6+
import init, { check_on_image_map, calculate_position } from "../wasm/main"
67

7-
const GRAVITY: number = 9.81;
8-
const GRAVITY_MULTIPLIER: number = 0.01;
98
const RADIUS: number = 2;
109
const SPACING: number = 35;
11-
const MAX_VELOCITY: number = 100;
1210
const EXTERNAL_PADDING_PERCENT: number = 0.05;
1311
let X_PADDING: number = 0;
1412
let Y_PADDING: number = 0;
@@ -19,11 +17,11 @@ interface ICanvasProps {
1917
}
2018

2119
export const Canvas = (props: ICanvasProps) => {
22-
2320
const { style, ...rest } = props
24-
const canvasRef = useCanvas()
21+
22+
let canvasRef: React.MutableRefObject<HTMLCanvasElement | null> | null = useCanvas();
2523
return <>
26-
<canvas style={style} ref={canvasRef} {...rest}></canvas>
24+
{canvasRef && <canvas style={style} ref={canvasRef} {...rest}></canvas>}
2725
</>
2826
}
2927

@@ -37,6 +35,12 @@ var mouse = {
3735

3836
const useCanvas = () => {
3937
const canvasRef: React.MutableRefObject<HTMLCanvasElement | null> = useRef(null);
38+
const [wasmInstantiated, setWasmInstantiated] = React.useState(false);
39+
useEffect(() => {
40+
init().then(() => {
41+
setWasmInstantiated(true);
42+
});
43+
}, []);
4044

4145
addEventListener("resize", () => {
4246
const canvas = canvasRef.current;
@@ -49,6 +53,9 @@ const useCanvas = () => {
4953
});
5054

5155
useEffect(() => {
56+
if (!wasmInstantiated) {
57+
return;
58+
}
5259

5360
const canvas = canvasRef.current
5461
const context = canvas!.getContext('2d')!
@@ -86,9 +93,9 @@ const useCanvas = () => {
8693
return () => {
8794
window.cancelAnimationFrame(animationFrameId)
8895
}
89-
}, [])
96+
}, [wasmInstantiated])
9097

91-
return canvasRef
98+
return wasmInstantiated ? canvasRef : null;
9299
}
93100

94101
export const resizeCanvasToDisplaySize = (canvas: HTMLCanvasElement) => {
@@ -213,7 +220,7 @@ class Square {
213220
y_gravity: number = 0;
214221
x_velocity: number = 0;
215222
y_velocity: number = 0;
216-
isResetting: boolean = false;
223+
is_resetting: boolean = false;
217224

218225
constructor(ctx: CanvasRenderingContext2D, initial_x: number, initial_y: number) {
219226
this.ctx = ctx;
@@ -223,7 +230,7 @@ class Square {
223230
this.initial_y = initial_y;
224231
this.reset_from_x = this.x;
225232
this.reset_from_y = this.y;
226-
this.color = checkOnImageMap(initial_x, initial_y)
233+
this.color = check_on_image_map(initial_x, initial_y, innerHeight, innerWidth)
227234
? `#${(Math.random() * 70 + 100).toString(16).slice(0, 2)}${(Math.random() * 100 + 100).toString(16).slice(0, 2)}${(Math.random() * 155 + 100).toString(16).slice(0, 2)}`
228235
: "#FFFFFF22"
229236
console.log(this.initial_x, this.initial_y);
@@ -234,131 +241,54 @@ class Square {
234241
this.ctx.beginPath();
235242
this.ctx.rect(this.x - RADIUS, this.y - RADIUS, RADIUS * 2, RADIUS * 2);
236243
this.ctx.fillStyle = this.color;
237-
this.ctx.shadowColor = this.color;
238-
this.ctx.shadowBlur = 5;
239244
this.ctx.fill();
240245
this.ctx.lineWidth = 3;
241246
}
242247

243-
calculateGravity = () => {
244-
if (this.isResetting) {
245-
this.x_gravity = GRAVITY * (this.initial_x - this.x) / window.innerWidth * GRAVITY_MULTIPLIER * 100;
246-
this.y_gravity = GRAVITY * (this.initial_y - this.y) / window.innerHeight * GRAVITY_MULTIPLIER * 100;
247-
// this.x_gravity = 0;
248-
// this.y_gravity = 0;
249-
} else {
250-
const x_relative_to_center = (this.x - window.innerWidth / 2) / window.innerWidth * 3
251-
const y_relative_to_center = (this.y - window.innerHeight / 2) / window.innerHeight * 3
252-
this.x_gravity = GRAVITY * (window.innerWidth > window.innerHeight ? window.innerWidth / window.innerHeight : 1) * GRAVITY_MULTIPLIER * -(x_relative_to_center - mouse.x) * (mouse.down ? 1 : 0);
253-
this.y_gravity = GRAVITY * (window.innerHeight > window.innerWidth ? window.innerHeight / window.innerWidth : 1) * GRAVITY_MULTIPLIER * -(y_relative_to_center - mouse.y) * (mouse.down ? 1 : 0);
254-
}
255-
}
256-
257-
calculateVelocity = () => {
258-
259-
if (this.isResetting) {
260-
// set velocity to start slow, then speed up, then slow down, then stop from reset_from to initial
261-
const x_distance = this.reset_from_x - this.initial_x;
262-
const y_distance = this.reset_from_y - this.initial_y;
263-
const x_distance_from_initial = this.x - this.initial_x;
264-
const y_distance_from_initial = this.y - this.initial_y;
265-
266-
const x_distance_from_initial_percent = Math.abs(x_distance_from_initial / x_distance);
267-
const y_distance_from_initial_percent = Math.abs(y_distance_from_initial / y_distance);
268-
269-
this.x_velocity = x_distance_from_initial_percent * -x_distance_from_initial;
270-
this.y_velocity = y_distance_from_initial_percent * -y_distance_from_initial;
271-
} else {
272-
this.x_velocity += this.x_gravity;
273-
this.y_velocity += this.y_gravity;
274-
this.x_velocity *= 1 - this.friction;
275-
this.y_velocity *= 1 - this.friction;
276-
}
277-
278-
if (Math.abs(this.x_velocity) > MAX_VELOCITY) {
279-
this.x_velocity = MAX_VELOCITY * (this.x_velocity > 0 ? 1 : -1);
280-
}
281-
if (Math.abs(this.y_velocity) > MAX_VELOCITY) {
282-
this.y_velocity = MAX_VELOCITY * (this.y_velocity > 0 ? 1 : -1);
283-
}
284-
}
285-
286-
calculatePosition = () => {
287-
this.x += this.x_velocity; // what about this
288-
this.y += this.y_velocity; // okay this kinda looks
289-
290-
if (this.x > window.innerWidth - EXTERNAL_PADDING_PERCENT * window.innerWidth / 2) {
291-
this.x = window.innerWidth - EXTERNAL_PADDING_PERCENT * window.innerWidth / 2;
292-
this.x_velocity *= -this.restitution;
293-
}
294-
if (this.x < EXTERNAL_PADDING_PERCENT * window.innerWidth / 2) {
295-
this.x = EXTERNAL_PADDING_PERCENT * window.innerWidth / 2;
296-
this.x_velocity *= -this.restitution;
297-
}
298-
if (this.y > window.innerHeight - EXTERNAL_PADDING_PERCENT * window.innerHeight / 2) {
299-
this.y = window.innerHeight - EXTERNAL_PADDING_PERCENT * window.innerHeight / 2;
300-
this.y_velocity *= -this.restitution * 0.9;
301-
}
302-
if (this.y < EXTERNAL_PADDING_PERCENT * window.innerHeight / 2) {
303-
this.y = EXTERNAL_PADDING_PERCENT * window.innerHeight / 2;
304-
this.y_velocity *= -this.restitution * 0.9;
305-
}
306-
307-
if (this.isResetting) {
308-
if (Math.abs(this.x - this.initial_x) < 1 && Math.abs(this.y - this.initial_y) < 1 && Math.abs(this.x_velocity) < 0.1 && Math.abs(this.y_velocity) < 0.1) {
309-
this.isResetting = false;
310-
this.x = this.initial_x;
311-
this.y = this.initial_y;
312-
this.x_gravity = 0;
313-
this.y_gravity = 0;
314-
this.x_velocity = 0;
315-
this.y_velocity = 0;
316-
}
317-
}
318-
}
319-
320248
prepareAnimation = () => {
321-
this.calculateGravity();
322-
this.calculateVelocity();
323-
this.calculatePosition();
249+
try {
250+
let s = calculate_position(
251+
mouse.x,
252+
mouse.y,
253+
mouse.down,
254+
this.x,
255+
this.y,
256+
this.x_velocity,
257+
this.y_velocity,
258+
this.x_gravity,
259+
this.y_gravity,
260+
this.is_resetting,
261+
this.reset_from_x,
262+
this.reset_from_y,
263+
this.friction,
264+
this.restitution,
265+
this.initial_x,
266+
this.initial_y,
267+
window.innerWidth,
268+
window.innerHeight
269+
) as Square;
270+
this.x = s.x;
271+
this.y = s.y;
272+
this.x_velocity = s.x_velocity;
273+
this.y_velocity = s.y_velocity;
274+
this.x_gravity = s.x_gravity;
275+
this.y_gravity = s.y_gravity;
276+
this.is_resetting = s.is_resetting;
277+
} catch (e) {
278+
console.log(e);
279+
}
324280
}
325281

326282
reset = () => {
327-
this.isResetting = true;
283+
this.is_resetting = true;
328284
this.reset_from_x = this.x;
329285
this.reset_from_y = this.y;
330286
this.x_gravity = 0;
331287
this.y_gravity = 0;
332288
}
333289

334290
cancelReset = () => {
335-
this.isResetting = false;
291+
this.is_resetting = false;
336292
}
337293

338-
}
339-
340-
const checkOnImageMap = (x: number, y: number) => {
341-
const smallestDimension = window.innerWidth > window.innerHeight ? window.innerHeight : window.innerWidth;
342-
const x_offset = (window.innerWidth - smallestDimension) / 2;
343-
const y_offset = (window.innerHeight - smallestDimension) / 2;
344-
const x_center = window.innerWidth / 2;
345-
const y_center = window.innerHeight / 2;
346-
347-
const unit = smallestDimension / 100;
348-
349-
// borders
350-
if (x < x_offset || x > window.innerWidth - x_offset || y < y_offset || y > window.innerHeight - y_offset) {
351-
return false;
352-
}
353-
354-
// center triangle
355-
if ((Math.abs(x - x_center) / -(y - y_center / 1.5) > 1 || y > y_center / 1.5) && (Math.abs(x - x_center) / -(y - y_center- y_center * 0.25) < 1 && y < y_center*1.25)) {
356-
return true;
357-
}
358-
359-
// bars
360-
if (Math.abs(x - x_center) >= unit * 30) {
361-
return true;
362-
}
363-
return false;
364294
}

0 commit comments

Comments
 (0)