Tres FPS controls
First person shooter controls to easily create 3D shooter experiences (or other first person experiences).
Installation
pnpm i @jaimebboyjt/tres-fps-controls
Demos
All the examples can be found in: Examples.
How to use it
To get started you can simply import the main component and use it.
<script setup>
import { TresCanvas } from "@tresjs/core";
import { fpsControls } from "@jaimebboyjt/tres-fps-controls";
</script>
<template>
<TresCanvas window-size>
<TresPerspectiveCamera
:position="[0, 0, 3]"
:fov="45"
:aspect="1"
:near="0.1"
:far="1000"
/>
<fpsControls />
</TresCanvas>
</template>
That's it. Now you're going to have a shooter controller. The WASD keys allow you to move and the mouse pointer changes where you look.
[!NOTE] This package uses PointerLockControls from cientos.
ControlsKey
We can provide a controlsKeys
prop to change, add or remove some of the basic functionalities.
export default {
props: {
controlsKeys: {
type: Array,
default: () => [
{ name: 'forward', key: 'w' },
{ name: 'backward', key: 's' },
{ name: 'left', key: 'a' },
{ name: 'right', key: 'd' },
// Optionals
{ name: 'run', key: 'Shift', speed: moveSpeed * 2 },
{ name: 'creep', key: 'ctrl', speed: moveSpeed * 0.25 },
// Mouse actions
{ name: 'leftClick', action: () => { } },
{ name: 'rightClick', action: () => { } },
{ name: 'middleClick', action: () => { } },
{ name: 'wheelActionUp', action: () => { } },
{ name: 'wheelActionDown', action: () => { } },
// Key actions
{
name: 'actions', actions: // You can have as many events as you want 🥳
[
{ name: 'action', key: 'e', action: () => {} },
{ name: 'action', key: 'q', action: () => {} },
{ name: 'action', key: 'r', action: () => {} },
{ name: 'action', key: 'f', action: () => {} },
],
},
],
},
}
}
[!TIP] Under the hood we use useMagicKeys. Check out all the possible keycodes.
As you can see we can provide different actions, including an array of actions using the keyboard.
<script setup>
import { TresCanvas } from "@tresjs/core";
import { fpsControls } from "@jaimebboyjt/tres-fps-controls";
const keyboardMap = [
{ name: "run", key: "q", speed: 0.5 },
{ name: "creep", key: "e" },
{ name: "leftClick", action: () => animationSword() },
{
name: "actions",
actions: [
{ name: "action2", key: "f", action: () => console.log("F press") },
{ name: "action4", key: "r", action: () => console.log("R press") },
],
},
{ name: "wheelActionUp", action: () => console.log("up") },
{ name: "wheelActionDown", action: () => console.log("down") },
];
</script>
<template>
<TresCanvas window-size>
<TresPerspectiveCamera
:position="[0, 0, 3]"
:fov="45"
:aspect="1"
:near="0.1"
:far="1000"
/>
<fpsControls :controlsKeys="keyboardMap" />
</TresCanvas>
</template>
Other props
Prop | Description | Type | Default |
---|---|---|---|
moveSpeed | Move speed | Number | 0.1 |
camera | The camera to control | Camera | undefined |
domElement | The dom element to listen to | HTMLCanvasElement | undefined |
selector | Accept an id element as string, if it is set, the new element will be used as the trigger | String | undefined |
Add weapons (models)
Do you want to add a weapon? Like a pistol, that is always with your character? It couldn't be easier:
Just add your desired model as a slot (learn how to load models here). For example:
...
<fpsControls>
<Suspense>
<GLTFModel path="/PixelArt Medieval Sword.glb" :scale="0.4"
:position="[-4.5, -3, -5]" // Don't forget set the z axis :rotation="[0, 1,
0]" />
</Suspense>
</fpsControls>
...
This will make your model update its position each time you move.
[!IMPORTANT] Normally you would set up the z axis, so the model is in front of you camera.
Expose methods
Do you still need more configurations?
We provide all the methods for you, exposed by the component, so you can use them as you like.
const exposeMethods = {
root: PointerLockControlsRef,
models: wrapperRef,
moveMethods: {
forward: () => walkSystem.moveForward(),
backward: () => walkSystem.moveBackward(),
left: () => walkSystem.moveLeft(),
right: () => walkSystem.moveRight(),
run: () => walkSystem.applyRun(),
creep: () => walkSystem.applyCreep(),
stopCreep: () => walkSystem.stopCreep(),
stopRun: () => walkSystem.stopRun(),
stopSideward: () => walkSystem.stopSideward(),
stopForward: () => walkSystem.stopForward(),
}
}
For granular control each method comes with its stop
method.
You can access all these methods using Template ref, as you normally would do with your TresJs components.
Events
We also provide some reactive events. Ej:
<script>
import { fpsControls } from 'fpsControls'
const handleState = (e) => console.log(e)
const handleLock = (e) => console.log(e)
const onChange = (e) => console.log(e)
</script>
<template>
<TresCanvas window-size>
<TresPerspectiveCamera
:position="[0, 0, 3]"
:fov="45"
:aspect="1"
:near="0.1"
:far="1000"
/>
<fpsControls @state="handleState" @isLock="handleLock" @change="onChange" />
</TresCanvas>
</template>
Event | Description |
---|---|
state | trigger when the state changes. |
isLock | trigger whether the pointer is locked. |
change | trigger when the character makes a move (moves the camera). |
Posible states:
const states = {
idle: 'idle',
walking: 'walking',
running: 'running',
creeping: 'creeping',
}
Gamepad
Check example inside playground on how to use the a gamepad with this repo :D |
Contributing
I appreciate your interest in this project! If you have any feedback, suggestions, or resources related to the controller, please feel free to share.
License
Sponsors
If you like this package you can support my work [here](https://github.com/sponsors/JaimeTorrealba ☺️. A github star or just some words of appreciation are incredible.