Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ShaneBrumback/0b4b9a06603540b1b0f8f844dfc810ad to your computer and use it in GitHub Desktop.
Save ShaneBrumback/0b4b9a06603540b1b0f8f844dfc810ad to your computer and use it in GitHub Desktop.
Threejs Examples - Particle System 3D Blast Effect
<!--////////////////////////////////////////////////////////////////////////////////////////
/// ///
/// Example Using Three.js Library, HTML, CSS & JavaScript ///
// 3D Interactive Web Apps & Games 2021-2024 ///
/// Contact Shane Brumback https://www.shanebrumback.com ///
/// Send a message if you have questions about this code ///
/// I am a freelance developer. I develop any and all web. ///
/// Apps Websites 3D 2D CMS Systems etc. Contact me anytime :) ///
/// ///
////////////////////////////////////////////////////////////////////////////////////////////-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Three.js Examples - Particle System 3D Blast Effect</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three@latest/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@latest/examples/js/controls/OrbitControls.js"></script>
<script type="module">
// Define global variables
let scene, camera, renderer;
const shotGunSpheres = [];
// Set up Three.js scene
scene = new THREE.Scene();
// Set up the camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 2;
camera.position.z = 2;
camera.position.y = 1;
// Set up the renderer
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.toneMapping = THREE.ReinhardToneMapping;
renderer.domElement.id = 'renderer';
renderer.setClearColor(0x000000, 1); // Set background color to black
renderer.domElement.style.position = 'fixed';
renderer.domElement.style.zIndex = '-1';
renderer.domElement.style.left = '0';
renderer.domElement.style.top = '0';
document.body.appendChild(renderer.domElement);
// Set up the orbital controls
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.dampingFactor = 0.1;
// Create a grid helper
const grid = new THREE.GridHelper(100, 150);
scene.add(grid);
document.addEventListener('mousedown', function (event) {
const origin = getClickedPoint(event.clientX, event.clientY);
fireShotGunSpheres(origin);
});
// Function to calculate the clicked 3D point based on mouse coordinates
function getClickedPoint(clientX, clientY) {
const vector = new THREE.Vector3();
const rect = renderer.domElement.getBoundingClientRect();
vector.x = ((clientX - rect.left) / rect.width) * 2 - 1;
vector.y = -((clientY - rect.top) / rect.height) * 2 + 1;
vector.z = 0.5;
vector.unproject(camera);
const dir = vector.sub(camera.position).normalize();
const distance = -camera.position.z / dir.z;
return camera.position.clone().add(dir.multiplyScalar(distance));
}
// Function to create and add spheres to the scene when the mouse is clicked
function fireShotGunSpheres(origin) {
// Loop 20 times to create 20 spheres
for (let i = 0; i < 50; i++) {
// Create a sphere
const sphere = new THREE.SphereGeometry(0.05, 32, 32);
const material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
const sphereMesh = new THREE.Mesh(sphere, material);
// Set the sphere position to the origin
sphereMesh.position.copy(origin);
// Set the direction of the shotgun spheres based on the mouse click
const direction = new THREE.Vector3();
direction.x = THREE.MathUtils.randFloat(-0.1, 0.1);
direction.y = THREE.MathUtils.randFloat(-0.1, 0.1);
direction.z = THREE.MathUtils.randFloat(-0.1, 0.1);
direction.normalize();
// Set the initial velocity of the shotgun spheres
const velocity = direction.clone().multiplyScalar(0.2);
// Add the velocity to the sphere position
sphereMesh.position.add(velocity);
// Create a point light at the center
const pointLight = new THREE.PointLight(0xffffff, 10, 50);
pointLight.position.set(0, 0, 0);
scene.add(pointLight);
// Add the sphere to the scene
scene.add(sphereMesh);
// Add the sphere to the shotGunSpheres array
shotGunSpheres.push({ mesh: sphereMesh, velocity: velocity, light: pointLight });
// Remove the sphere and point light after 2 seconds
setTimeout(() => {
scene.remove(sphereMesh);
scene.remove(pointLight);
const index = shotGunSpheres.findIndex((item) => item.mesh === sphereMesh);
if (index !== -1) {
shotGunSpheres.splice(index, 1);
}
}, 2000);
}
}
// Function to animate the spheres created in the fireShotGunSpheres() function
function animateShotGunParticles() {
// Loop through each sphere
for (let i = 0; i < shotGunSpheres.length; i++) {
const sphereData = shotGunSpheres[i];
const sphere = sphereData.mesh;
const velocity = sphereData.velocity;
// Move the sphere according to its velocity
sphere.position.add(velocity);
// Check if the sphere is too far from the camera
if (sphere.position.z < camera.position.z - 10) {
scene.remove(sphere);
shotGunSpheres.splice(i, 1);
i--;
}
}
}
function animate() {
requestAnimationFrame(animate);
animateShotGunParticles();
renderer.render(scene, camera);
controls.update();
}
animate();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment