Particle system

This commit is contained in:
2024-10-02 16:49:54 +02:00
parent 1debe1b94d
commit 691b32c6e4
9 changed files with 91 additions and 2 deletions
+4
View File
@@ -0,0 +1,4 @@
* Saving the game data to a file, so high scores, unlocked levels
etc. can be shared across updates. Or, someone unfair can cheat.
* Randomly rotate, tint, etc., cells to add variety
* Refractor the code
+14
View File
@@ -32,6 +32,7 @@ function restart_game() {
mines_placed = false;
field_height = 8 + Math.floor(current_level / 2);
minefield_initialize();
update_particle_canvas_size();
// The amount of mines, meanwhile, increases by one I
// think. Just a quick thought. This makes it so the amount of
// mines is around four times less than the amount of cells.
@@ -191,7 +192,20 @@ function reveal_mines(cell) {
cell.innerText = "" + n_mines;
cell.classList.add("n" + n_mines);
}
reveal_cell_cosmetic(cell);
}
function reveal_cell_cosmetic(cell) {
sound_reveal.play();
let r = cell.getBoundingClientRect();
let w = r.right - r.left;
let h = r.bottom - r.top;
let x = cell.offsetLeft - cell.scrollLeft;
let y = cell.offsetTop - cell.scrollTop;
spawn_particle(x, y, (Math.random() * 2 - 1) / 16, -0.3, 0, 1, dummy_image, w, h);
}
// Shows the game won/over popup.
+2
View File
@@ -5,6 +5,7 @@
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="particle-canvas"></canvas>
<div id="main-menu">
<span id="game-title">Gravedigger</span>
<span id="subtitle">a CFPI-FPSI creation</span>
@@ -30,6 +31,7 @@
<div id="bottom-fade"></div>
</div>
<script src="game.js"></script>
<script src="particles.js"></script>
<script src="main-menu.js"></script>
</body>
</html>
+66
View File
@@ -0,0 +1,66 @@
const particle_canvas = $("#particle-canvas");
const particle_ctx = particle_canvas.getContext("2d");
let last_time;
let particles = new Set;
let dummy_image = new Image;
dummy_image.src = "res/gravedigger/unknown-1.png";
update_particle_canvas_size();
window.requestAnimationFrame(particle_loop);
function update_particle_canvas_size() {
particle_canvas.width = document.body.clientWidth;
// Whatever's bigger, we use.
particle_canvas.height = Math.max(document.body.clientHeight, window.innerHeight);
}
function spawn_particle(x, y, vel_x, vel_y, rot, vel_rot, img, w, h) {
particles.add({
x: x,
y: y,
vel_x: vel_x,
vel_y: vel_y,
rot: rot,
vel_rot: vel_rot,
img: img,
w: w,
h: h
});
}
function update_particles(delta_time) {
particle_ctx.clearRect(0, 0, particle_canvas.width, particle_canvas.height);
for (particle of particles) {
// Delete off-screen particles, more or less. For now, it's
// designed so that particles go down with the force of
// gravity, so we just check if the particle goes below the
// screen.
if (particle.y > particle_canvas.height) {
particles.delete(particle);
continue;
}
// Update the position and rotation of the particle.
particle.x += particle.vel_x * delta_time;
particle.y += particle.vel_y * delta_time;
particle.rot += particle.vel_rot * delta_time;
// Update the velocity to take into account "gravity" and "air
// resistance".
particle.vel_y += 0.001 * delta_time;
// Render particle.
particle_ctx.save();
// particle_ctx.translate(-particle.width / 2, -particle.height / 2);
// particle_ctx.rotate(particle.rot * Math.PI / 180);
particle_ctx.drawImage(particle.img, particle.x, particle.y, particle.w, particle.h)
particle_ctx.restore();
}
}
function particle_loop(timestamp) {
// Calculate the times needed for updating.
update_particles(timestamp - last_time);
last_time = timestamp;
window.requestAnimationFrame(particle_loop);
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.
+5 -2
View File
@@ -18,8 +18,6 @@ body {
image-rendering: crisp-edges;
image-rendering: pixelated;
background: linear-gradient(
rgba(0, 0, 0, 0.7),
rgba(0, 0, 0, 0.7)
@@ -29,6 +27,11 @@ body {
font-family: serif;
}
#particle-canvas {
position: absolute;
pointer-events: none;
}
#main-menu {
display: flex;
flex-flow: column;