Skip to content

Commit c0cea99

Browse files
Privatech38Lulu13022002olijeffers0nzlataovceStrokkur424
authored
feat: Particles guide (#625)
Co-authored-by: Lulu13022002 <[email protected]> Co-authored-by: Ollie <[email protected]> Co-authored-by: Matouš Kučera <[email protected]> Co-authored-by: Strokkur424 <[email protected]>
1 parent f493a0a commit c0cea99

17 files changed

+862
-0
lines changed

astro.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ export default defineConfig({
235235
"paper/dev/lifecycle",
236236
"paper/dev/registries",
237237
"paper/dev/recipes",
238+
"paper/dev/particles",
238239
"paper/dev/folia-support",
239240
"paper/dev/roadmap",
240241
],
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<script lang="ts">
2+
let offsetX: number = $state(0.0);
3+
let color = $derived(
4+
`rgb(${noteColorRGB(offsetX)
5+
.map((c) => c * 100 + "%")
6+
.join(", ")})`
7+
);
8+
let mainCanvas: HTMLCanvasElement;
9+
let compositingCanvas: HTMLCanvasElement;
10+
let noteImg: HTMLImageElement;
11+
12+
// Run only once
13+
$effect(() => {
14+
const context: CanvasRenderingContext2D | null = mainCanvas.getContext("2d");
15+
if (!context) {
16+
return;
17+
}
18+
context.imageSmoothingEnabled = false;
19+
});
20+
21+
$effect(() => {
22+
const compositingContext: CanvasRenderingContext2D | null = compositingCanvas.getContext("2d");
23+
if (!compositingContext || !noteImg.complete) {
24+
return;
25+
}
26+
compositingContext.globalCompositeOperation = "source-over";
27+
compositingContext.clearRect(0, 0, 8, 8);
28+
compositingContext.drawImage(noteImg, 0, 0, 8, 8);
29+
compositingContext.globalCompositeOperation = "multiply";
30+
compositingContext.fillStyle = color;
31+
compositingContext.fillRect(0, 0, 8, 8);
32+
compositingContext.globalCompositeOperation = "destination-atop";
33+
compositingContext.drawImage(noteImg, 0, 0, 8, 8);
34+
// Draw on the main canvas
35+
const mainContext: CanvasRenderingContext2D | null = mainCanvas.getContext("2d");
36+
if (mainContext) {
37+
mainContext.clearRect(0, 0, mainCanvas.width, mainCanvas.height);
38+
mainContext.drawImage(compositingCanvas, 0, 0, 8, 8, 0, 0, mainCanvas.width, mainCanvas.height);
39+
}
40+
});
41+
42+
/**
43+
* Calculates RGB color based on the offsetX value, just like the Minecraft client.
44+
* @param offsetX Offset for X coordinate.
45+
* @return RGB color floats (in range from 0.0 to 1.0).
46+
*/
47+
function noteColorRGB(offsetX: number): [number, number, number] {
48+
return [
49+
Math.max(0.0, Math.sin(offsetX * 6.2831855) * 0.65 + 0.35),
50+
Math.max(0.0, Math.sin((offsetX + 0.33333334) * 6.2831855) * 0.65 + 0.35),
51+
Math.max(0.0, Math.sin((offsetX + 0.6666667) * 6.2831855) * 0.65 + 0.35),
52+
];
53+
}
54+
</script>
55+
56+
<div class="picker">
57+
<img
58+
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAQAAABuBnYAAAAALElEQVR42mOAgc3/J/0H0UgCGahCm4GcQGQBiCzRAp//A41EFsj4H/gfZiAAXXUYtS3tm1IAAAAASUVORK5CYII="
59+
alt="Note particle"
60+
class="note-image"
61+
bind:this={noteImg}
62+
/>
63+
<canvas class="compositing-canvas" bind:this={compositingCanvas}></canvas>
64+
<canvas class="note-canvas" bind:this={mainCanvas}></canvas>
65+
<p><span class="value">offsetX = {offsetX}</span></p>
66+
<input class="offset-slider" type="range" min={-1.0} max={1.0} step={0.01} bind:value={offsetX} />
67+
</div>
68+
69+
<style>
70+
.picker {
71+
display: flex;
72+
flex-direction: column;
73+
justify-content: center;
74+
align-items: center;
75+
width: 30rem;
76+
max-width: 100%;
77+
padding: 1rem;
78+
text-align: center;
79+
}
80+
81+
.note-image {
82+
image-rendering: pixelated;
83+
width: 1rem;
84+
height: auto;
85+
display: none;
86+
}
87+
88+
.note-canvas {
89+
height: 5rem;
90+
width: 5rem;
91+
}
92+
93+
.compositing-canvas {
94+
width: 8px;
95+
height: 8px;
96+
display: none;
97+
}
98+
99+
.value {
100+
font-size: 1.5rem;
101+
font-weight: bold;
102+
}
103+
104+
.offset-slider {
105+
width: 100%;
106+
}
107+
</style>
678 KB
Loading
541 KB
Loading
321 KB
Loading
480 KB
Loading
305 KB
Loading
466 KB
Loading
301 KB
Loading
31.3 KB
Loading

0 commit comments

Comments
 (0)