How to create shooting game
Code shooting logic first
Set FPS mode with camera.useFPS()
, detect mouse clicks with OnPointerDown()
to trigger createBullet()
which initializes and positions bullets stored in the bullets array, using BULLET_SPEED
and BULLET_RANGE_SQUARED
to define their speed and range, then add bullets to the world, and move them using Update()
which calls moveBullets()
to handle movement and removal of out-of-range bullets.
const camera = WORLD.getObject("MainCamera");
camera.useFPS();
let bullets = [];
const BULLET_SPEED = 1.5;
const BULLET_RANGE_SQUARED = 30000;
// Triggered when the pointer is pressed
function OnPointerDown() {
createBullet();
}
// Creates a bullet and sets its initial properties
function createBullet() {
let cameraDirection = new THREE.Vector3();
camera.getWorldDirection(cameraDirection);
cameraDirection.setLength(BULLET_SPEED);
const cameraPosition = camera.position;
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const bullet = new THREE.Mesh(geometry, material);
// Position the bullet in front of the camera
bullet.position.set(
cameraPosition.x + cameraDirection.x,
cameraPosition.y + cameraDirection.y,
cameraPosition.z + cameraDirection.z
);
bullet.rotation.copy(camera.rotation);
bullets.push({ object: bullet, direction: cameraDirection.clone() });
WORLD.add(bullet);
}
// Updates the state, usually on a per-frame basis
function Update(dt) {
moveBullets();
}
// Moves the bullets and handles their lifecycle
function moveBullets() {
for (let i = bullets.length - 1; i >= 0; i--) {
const bullet = bullets[i];
const bulletPosition = bullet.object.position;
const movementVector = bullet.direction;
bullet.object.position.set(
bulletPosition.x + movementVector.x,
bulletPosition.y + movementVector.y,
bulletPosition.z + movementVector.z
);
// Check if the bullet is beyond the defined range
if (
bullet.object.position.distanceToSquared(PLAYER.position) >
BULLET_RANGE_SQUARED
) {
WORLD.remove(bullet.object);
bullet.object.geometry.dispose();
bullet.object.material.dispose();
bullets.splice(i, 1);
}
}
}
add Target Objects
Define a hit detection range with TARGET_HIT_RANGE
and initialize an array targetObjects
to store targets. Add objects like a "car"
to targetObjects using WORLD.getObject()
. Modify moveBullets()
to include collision detection with targetObjects, checking the distance between each bullet and target. If a bullet is within TARGET_HIT_RANGE
of a target, invoke target.kill()
to handle the hit, remove the bullet from the world, and clean up its resources.
const TARGET_HIT_RANGE = 32;
const targetObjects = [];
targetObjects.push(WORLD.getObject("car"));
//add more objects as targetObject as you need.
// other code
//inside of moveEnergyBall
function moveEnergyBall() {
// other code
// Check if the ball hits any target
for (let j = 0; j < targetObjects.length; j++) {
const target = targetObjects[j];
if (
bullet.object.position.distanceToSquared(target.position) <
TARGET_HIT_RANGE
) {
target.kill(); // Handle target hit
WORLD.remove(bullet.object);
bullet.object.geometry.dispose();
bullet.object.material.dispose();
bulets.splice(i, 1);
}
}
}
Final code
Just copy paste this code and use shooting feature. Just dont forget to change targetObjects.
const camera = WORLD.getObject("MainCamera");
camera.useFPS();
let bullets = [];
const BULLET_SPEED = 1.5;
const BULLET_RANGE_SQUARED = 30000;
const TARGET_HIT_RANGE = 32;
const targetObjects = [];
targetObjects.push(WORLD.getObject("car")); // change to your target
//add more objects as targetObject as you need.
// Triggered when the pointer is pressed
function OnPointerDown() {
createBullet();
}
// Creates a bullet and sets its initial properties
function createBullet() {
let cameraDirection = new THREE.Vector3();
camera.getWorldDirection(cameraDirection);
cameraDirection.setLength(BULLET_SPEED);
const cameraPosition = camera.position;
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const bullet = new THREE.Mesh(geometry, material);
// Position the bullet in front of the camera
bullet.position.set(
cameraPosition.x + cameraDirection.x,
cameraPosition.y + cameraDirection.y,
cameraPosition.z + cameraDirection.z
);
bullet.rotation.copy(camera.rotation);
bullets.push({ object: bullet, direction: cameraDirection.clone() });
WORLD.add(bullet);
}
// Updates the state, usually on a per-frame basis
function Update(dt) {
moveBullets();
}
// Moves the bullets and handles their lifecycle
function moveBullets() {
for (let i = bullets.length - 1; i >= 0; i--) {
const bullet = bullets[i];
const bulletPosition = bullet.object.position;
const movementVector = bullet.direction;
bullet.object.position.set(
bulletPosition.x + movementVector.x,
bulletPosition.y + movementVector.y,
bulletPosition.z + movementVector.z
);
// Check if the bullet is beyond the defined range
if (
bullet.object.position.distanceToSquared(PLAYER.position) >
BULLET_RANGE_SQUARED
) {
WORLD.remove(bullet.object);
bullet.object.geometry.dispose();
bullet.object.material.dispose();
bullets.splice(i, 1);
}
for (let j = 0; j < targetObjects.length; j++) {
const target = targetObjects[j];
if (
bullet.object.position.distanceToSquared(target.position) <
TARGET_HIT_RANGE
) {
target.kill(); // Handle target hit
WORLD.remove(bullet.object);
bullet.object.geometry.dispose();
bullet.object.material.dispose();
bullets.splice(i, 1);
}
}
}
}
Customize it
You can add gun objects and guis to customize it.
Check out the My asset page for instructions on how to add your assets.
If you want to use an asset instead of creating bullets with Three.js, modify the following lines in the previous final code.
// Delete the following 3 lines (lines 26-28 in the final code)
// const geometry = new THREE.SphereGeometry(1, 32, 32);
// const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// const bullet = new THREE.Mesh(geometry, material);
// Then add this code in their place
const bullet = WORLD.getObject("bullet_object").clone();
// Delete the following 2 lines (lines 80-81 in the final code)
// bullet.object.geometry.dispose();
// bullet.object.material.dispose();