mirror of
https://github.com/litruv/lit.ruv.wtf.git
synced 2026-07-24 02:36:02 +10:00
tnt
This commit is contained in:
@@ -130,7 +130,16 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
stone_pickaxe: loadItemTexture('stone_pickaxe.png'),
|
||||
iron_pickaxe: loadItemTexture('iron_pickaxe.png'),
|
||||
gold_pickaxe: loadItemTexture('gold_pickaxe.png'),
|
||||
diamond_pickaxe: loadItemTexture('diamond_pickaxe.png')
|
||||
diamond_pickaxe: loadItemTexture('diamond_pickaxe.png'),
|
||||
tnt_side: loadTexture('tnt_side.png'),
|
||||
tnt_top: loadTexture('tnt_top.png'),
|
||||
tnt_bottom: loadTexture('tnt_bottom.png'),
|
||||
particle: (() => {
|
||||
const t = new THREE.TextureLoader().load('particle/particles.png');
|
||||
t.magFilter = THREE.NearestFilter;
|
||||
t.minFilter = THREE.NearestFilter;
|
||||
return t;
|
||||
})()
|
||||
};
|
||||
|
||||
// Load destroy stages
|
||||
@@ -1619,13 +1628,80 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Particle System ---
|
||||
let particles = [];
|
||||
|
||||
function spawnExplosionParticles(pos) {
|
||||
if (!textures.particle) return;
|
||||
|
||||
const particleCount = 30;
|
||||
const material = new THREE.SpriteMaterial({
|
||||
map: textures.particle,
|
||||
color: 0xffffff,
|
||||
transparent: true,
|
||||
blending: THREE.AdditiveBlending
|
||||
});
|
||||
|
||||
for (let i = 0; i < particleCount; i++) {
|
||||
const sprite = new THREE.Sprite(material);
|
||||
sprite.position.copy(pos);
|
||||
// Add some randomness to start position
|
||||
sprite.position.x += (Math.random() - 0.5) * 0.5;
|
||||
sprite.position.y += (Math.random() - 0.5) * 0.5;
|
||||
sprite.position.z += (Math.random() - 0.5) * 0.5;
|
||||
|
||||
// Random velocity
|
||||
const speed = 0.1 + Math.random() * 0.3;
|
||||
sprite.userData.velocity = new THREE.Vector3(
|
||||
(Math.random() - 0.5) * speed,
|
||||
(Math.random() - 0.5) * speed,
|
||||
(Math.random() - 0.5) * speed
|
||||
);
|
||||
|
||||
sprite.userData.life = 1.0;
|
||||
const size = 0.3 + Math.random() * 0.4;
|
||||
sprite.scale.set(size, size, size);
|
||||
|
||||
scene.add(sprite);
|
||||
particles.push(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
function updateParticles() {
|
||||
for (let i = particles.length - 1; i >= 0; i--) {
|
||||
const p = particles[i];
|
||||
p.position.add(p.userData.velocity);
|
||||
p.userData.velocity.y -= 0.005; // Slight gravity
|
||||
p.userData.velocity.multiplyScalar(0.95); // Drag
|
||||
p.userData.life -= 0.02;
|
||||
|
||||
p.material.opacity = Math.max(0, p.userData.life);
|
||||
|
||||
if (p.userData.life <= 0) {
|
||||
scene.remove(p);
|
||||
particles.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Animation Loop ---
|
||||
function animate() {
|
||||
let lastTime = 0;
|
||||
const fpsInterval = 1000 / 60;
|
||||
|
||||
function animate(currentTime) {
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
if (!currentTime) currentTime = performance.now();
|
||||
const elapsed = currentTime - lastTime;
|
||||
|
||||
if (elapsed > fpsInterval) {
|
||||
lastTime = currentTime - (elapsed % fpsInterval);
|
||||
|
||||
processMining();
|
||||
updateDrops();
|
||||
updateSaplings();
|
||||
updateTNT();
|
||||
updateParticles();
|
||||
checkCollection();
|
||||
|
||||
// Camera offset logic
|
||||
@@ -1642,6 +1718,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
composer.render();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle resize
|
||||
window.addEventListener('resize', () => {
|
||||
@@ -1976,32 +2053,87 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
// Physics
|
||||
for (let i = tntProjectiles.length - 1; i >= 0; i--) {
|
||||
const tnt = tntProjectiles[i];
|
||||
tnt.position.y -= 0.2; // Fall speed
|
||||
tnt.rotation.x += 0.05;
|
||||
tnt.rotation.z += 0.05;
|
||||
|
||||
// Check collision
|
||||
// Simple check: if y < something and hits a block
|
||||
// Initialize fuse if not present (for existing TNTs)
|
||||
if (tnt.userData.fuse === undefined) tnt.userData.fuse = 120;
|
||||
if (tnt.userData.landed === undefined) tnt.userData.landed = false;
|
||||
|
||||
// Flashing effect
|
||||
tnt.userData.flashTimer += 1;
|
||||
// Flash faster as fuse runs out
|
||||
const flashInterval = tnt.userData.fuse < 60 ? 5 : 10;
|
||||
|
||||
if (tnt.userData.flashTimer % flashInterval === 0) {
|
||||
tnt.userData.isFlashing = !tnt.userData.isFlashing;
|
||||
if (tnt.userData.isFlashing) {
|
||||
if (!tnt.userData.whiteMaterial) {
|
||||
tnt.userData.whiteMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
|
||||
}
|
||||
tnt.material = tnt.userData.whiteMaterial;
|
||||
} else {
|
||||
tnt.material = tnt.userData.originalMaterials;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tnt.userData.landed) {
|
||||
tnt.position.y -= 0.1; // Fall speed
|
||||
|
||||
const gx = Math.round(tnt.position.x / BLOCK_SIZE + (GRID_SIZE/2 - 0.5));
|
||||
const gz = Math.round(tnt.position.z / BLOCK_SIZE + (GRID_SIZE/2 - 0.5));
|
||||
const gy = Math.round(tnt.position.y / BLOCK_SIZE);
|
||||
|
||||
// Check if we hit a block
|
||||
const block = getBlockAt(gx, gy, gz);
|
||||
if (block || gy < -depth - 1) { // Hit block or fell too far
|
||||
|
||||
if (block) {
|
||||
// Land on top
|
||||
tnt.userData.landed = true;
|
||||
tnt.position.y = block.position.y + BLOCK_SIZE;
|
||||
// Snap to grid
|
||||
tnt.position.x = (gx - (GRID_SIZE/2 - 0.5)) * BLOCK_SIZE;
|
||||
tnt.position.z = (gz - (GRID_SIZE/2 - 0.5)) * BLOCK_SIZE;
|
||||
} else if (gy < -depth - 5) {
|
||||
// Fell too far
|
||||
tntProjectiles.splice(i, 1);
|
||||
scene.remove(tnt);
|
||||
}
|
||||
} else {
|
||||
// Landed logic
|
||||
// Check if block below still exists
|
||||
const gx = Math.round(tnt.position.x / BLOCK_SIZE + (GRID_SIZE/2 - 0.5));
|
||||
const gz = Math.round(tnt.position.z / BLOCK_SIZE + (GRID_SIZE/2 - 0.5));
|
||||
const gyBelow = Math.round((tnt.position.y - BLOCK_SIZE) / BLOCK_SIZE);
|
||||
|
||||
const blockBelow = getBlockAt(gx, gyBelow, gz);
|
||||
if (!blockBelow && tnt.position.y > -depth - 1) {
|
||||
tnt.userData.landed = false; // Start falling again
|
||||
}
|
||||
|
||||
tnt.userData.fuse--;
|
||||
if (tnt.userData.fuse <= 0) {
|
||||
explodeTNT(tnt);
|
||||
tntProjectiles.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function spawnTNT() {
|
||||
const gx = Math.floor(Math.random() * GRID_SIZE);
|
||||
const gz = Math.floor(Math.random() * GRID_SIZE);
|
||||
|
||||
const geometry = new THREE.BoxGeometry(0.6, 0.6, 0.6);
|
||||
const material = new THREE.MeshLambertMaterial({ color: 0xff0000 }); // Red block for now
|
||||
const tnt = new THREE.Mesh(geometry, material);
|
||||
|
||||
const materials = [
|
||||
new THREE.MeshLambertMaterial({ map: textures.tnt_side }), // px
|
||||
new THREE.MeshLambertMaterial({ map: textures.tnt_side }), // nx
|
||||
new THREE.MeshLambertMaterial({ map: textures.tnt_top }), // py (top)
|
||||
new THREE.MeshLambertMaterial({ map: textures.tnt_bottom }), // ny (bottom)
|
||||
new THREE.MeshLambertMaterial({ map: textures.tnt_side }), // pz
|
||||
new THREE.MeshLambertMaterial({ map: textures.tnt_side }) // nz
|
||||
];
|
||||
|
||||
const tnt = new THREE.Mesh(geometry, materials);
|
||||
|
||||
tnt.position.set(
|
||||
(gx - (GRID_SIZE/2 - 0.5)) * BLOCK_SIZE,
|
||||
@@ -2009,11 +2141,20 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
(gz - (GRID_SIZE/2 - 0.5)) * BLOCK_SIZE
|
||||
);
|
||||
|
||||
tnt.userData = {
|
||||
flashTimer: 0,
|
||||
isFlashing: false,
|
||||
originalMaterials: materials,
|
||||
fuse: 120, // 2 seconds at 60fps
|
||||
landed: false
|
||||
};
|
||||
|
||||
scene.add(tnt);
|
||||
tntProjectiles.push(tnt);
|
||||
}
|
||||
|
||||
function explodeTNT(tnt) {
|
||||
spawnExplosionParticles(tnt.position);
|
||||
scene.remove(tnt);
|
||||
|
||||
// Explosion effect (simple)
|
||||
|
||||
BIN
website/particle/footprint.png
Normal file
BIN
website/particle/footprint.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 896 B |
BIN
website/particle/particles.png
Normal file
BIN
website/particle/particles.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
Reference in New Issue
Block a user