-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
769f1e9
commit 0743d3e
Showing
15 changed files
with
400 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import * as PIXI from 'pixi.js' | ||
import { FKeyboard } from '@fibbojs/event' | ||
import type { FScene2d } from '../FScene2d' | ||
import { F2dShapes } from '../types/F2dShapes' | ||
import type { FComponent2dOptions, FComponent2dOptions__initCollider, FComponent2dOptions__initRigidBody } from '../FComponent2d' | ||
import { FComponent2d } from '../FComponent2d' | ||
|
||
export interface FCharacter2dOptions extends FComponent2dOptions { | ||
/** | ||
* The speed of the character. | ||
*/ | ||
speed?: number | ||
} | ||
|
||
/** | ||
* @description An abstract pre-defined character controller. | ||
* @category Character | ||
*/ | ||
export abstract class FCharacter2d extends FComponent2d { | ||
/** | ||
* The inputs that will be used to move the character. | ||
*/ | ||
inputs: { | ||
up: boolean | ||
down: boolean | ||
left: boolean | ||
right: boolean | ||
} | ||
|
||
/** | ||
* The speed of the character. | ||
*/ | ||
speed: number | ||
|
||
constructor(scene: FScene2d, options?: FCharacter2dOptions) { | ||
super(scene, { | ||
scale: { x: 0.5, y: 1 }, | ||
...options, | ||
}) | ||
|
||
// Define default values | ||
const DEFAULT_OPTIONS = { | ||
speed: 1, | ||
} | ||
// Apply default options | ||
options = { ...DEFAULT_OPTIONS, ...options } | ||
// Validate options | ||
if (!options.speed) | ||
throw new Error('FCharacter2d requires speed option') | ||
|
||
// Store speed | ||
this.speed = options.speed | ||
|
||
// Map of the movements (will be updated by the keyboard) | ||
this.inputs = { | ||
up: false, | ||
down: false, | ||
left: false, | ||
right: false, | ||
} | ||
|
||
// Create a square | ||
this.container = new PIXI.Graphics() | ||
.rect(this.position.x, this.position.y, this.scale.x * 100, this.scale.y * 100) | ||
.fill(new PIXI.FillGradient(0, 0, this.scale.x * 100, this.scale.y * 100).addColorStop(0, 0xFF00FF).addColorStop(1, 0xFFFF00)) | ||
// Set the pivot of the container to the center | ||
this.container.pivot.set(this.container.width / 2, this.container.height / 2) | ||
|
||
// Create a keyboard instance | ||
const fKeyboard = new FKeyboard(scene) | ||
|
||
// Key down | ||
fKeyboard.onKeyDown('ArrowUp', () => { | ||
this.inputs.up = true | ||
}) | ||
fKeyboard.onKeyDown('ArrowDown', () => { | ||
this.inputs.down = true | ||
}) | ||
fKeyboard.onKeyDown('ArrowLeft', () => { | ||
this.inputs.left = true | ||
}) | ||
fKeyboard.onKeyDown('ArrowRight', () => { | ||
this.inputs.right = true | ||
}) | ||
|
||
// Key up | ||
fKeyboard.onKeyUp('ArrowUp', () => { | ||
this.inputs.up = false | ||
}) | ||
fKeyboard.onKeyUp('ArrowDown', () => { | ||
this.inputs.down = false | ||
}) | ||
fKeyboard.onKeyUp('ArrowLeft', () => { | ||
this.inputs.left = false | ||
}) | ||
fKeyboard.onKeyUp('ArrowRight', () => { | ||
this.inputs.right = false | ||
}) | ||
} | ||
|
||
initRigidBody(options?: FComponent2dOptions__initRigidBody): void { | ||
super.initRigidBody({ | ||
shape: F2dShapes.SQUARE, | ||
...options, | ||
}) | ||
} | ||
|
||
initCollider(options?: FComponent2dOptions__initCollider): void { | ||
super.initCollider({ | ||
shape: F2dShapes.SQUARE, | ||
...options, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import RAPIER from '@dimforge/rapier2d' | ||
import type { FScene2d } from '../FScene2d' | ||
import type { FComponent2dOptions, FComponent2dOptions__initRigidBody } from '../FComponent2d' | ||
import { FCharacter2d } from './FCharacter2d' | ||
|
||
/** | ||
* @description A pre-defined character controller based on Dynamic rigidbodies. | ||
* @category Character | ||
* @example | ||
* ```ts | ||
* import { FScene2d, FCharacter2dDynamic } from '@fibbojs/2d' | ||
* | ||
* const scene = new FScene2d() | ||
* | ||
* const capsule = new FCharacter2dDynamic(scene) | ||
* scene.addComponent(capsule) | ||
* ``` | ||
*/ | ||
export class FCharacter2dDynamic extends FCharacter2d { | ||
constructor(scene: FScene2d, options?: FComponent2dOptions) { | ||
super(scene, options) | ||
|
||
/** | ||
* Handle movements on each frame (only character movement, as gravity is handled by the dynamic rigid body) | ||
*/ | ||
scene.onFrame(() => { | ||
// Apply movement on the y axis | ||
if (this.inputs.up) { | ||
this.rigidBody?.applyImpulse({ x: 0, y: 0.15 * this.speed }, true) | ||
} | ||
else if (this.inputs.down) { | ||
this.rigidBody?.applyImpulse({ x: 0, y: -0.15 * this.speed }, true) | ||
} | ||
// Apply movement on the x axis | ||
if (this.inputs.left) { | ||
this.rigidBody?.applyImpulse({ x: -0.15 * this.speed, y: 0 }, true) | ||
} | ||
else if (this.inputs.right) { | ||
this.rigidBody?.applyImpulse({ x: 0.15 * this.speed, y: 0 }, true) | ||
} | ||
}) | ||
|
||
// Initialize the rigid body | ||
this.initRigidBody() | ||
} | ||
|
||
initRigidBody(options?: FComponent2dOptions__initRigidBody): void { | ||
super.initRigidBody({ | ||
rigidBodyType: RAPIER.RigidBodyType.Dynamic, | ||
lockRotations: true, | ||
...options, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import * as THREE from 'three' | ||
import RAPIER from '@dimforge/rapier2d' | ||
import type { FScene2d } from '../FScene2d' | ||
import type { FComponent2dOptions, FComponent2dOptions__initRigidBody } from '../FComponent2d' | ||
import { FCharacter2dKinematic } from './FCharacter2dKinematic' | ||
|
||
/** | ||
* @description A pre-defined character controller based on Kinematic Position rigidbodies. | ||
* @category Character | ||
* @example | ||
* ```ts | ||
* import { FScene2d, FCharacter2dKP } from '@fibbojs/2d' | ||
* | ||
* const scene = new FScene2d() | ||
* | ||
* const capsule = new FCharacter2dKP(scene) | ||
* scene.addComponent(capsule) | ||
* ``` | ||
*/ | ||
export class FCharacter2dKP extends FCharacter2dKinematic { | ||
constructor(scene: FScene2d, options?: FComponent2dOptions) { | ||
super(scene, options) | ||
|
||
/** | ||
* Handle movements on each frame (gravity + character movement) | ||
* For some reason, using the onFrame method will result in weird behavior with gravity | ||
* (e.g. the character crossing the ground) | ||
*/ | ||
scene.onFrame((delta) => { | ||
const movementDirection = new RAPIER.Vector2(0, 0) | ||
// Compute the movement direction | ||
movementDirection.x = this.inputs.left ? -1 : this.inputs.right ? 1 : 0 | ||
// TODO : jump | ||
// movementDirection.y = this.inputs.up ? 1 : this.inputs.down ? -1 : 0 | ||
|
||
// Create movement vector | ||
const desiredMovement = { | ||
x: movementDirection.x * delta * 8 * this.speed, | ||
y: this.scene.world.gravity.y * delta, | ||
} | ||
// Compute the desired movement | ||
this.characterController.computeColliderMovement( | ||
this.collider as RAPIER.Collider, | ||
desiredMovement, | ||
) | ||
// Get the corrected movement | ||
const correctedMovement = this.characterController.computedMovement() | ||
// Apply the movement to the rigid body | ||
this.rigidBody?.setNextKinematicTranslation({ | ||
x: this.rigidBody.translation().x + correctedMovement.x * delta * this.speed * 64, | ||
y: this.rigidBody.translation().y + correctedMovement.y * delta * this.speed * 64, | ||
}) | ||
}) | ||
|
||
// Initialize the rigid body | ||
this.initRigidBody() | ||
} | ||
|
||
initRigidBody(options?: FComponent2dOptions__initRigidBody): void { | ||
super.initRigidBody({ | ||
rigidBodyType: RAPIER.RigidBodyType.KinematicPositionBased, | ||
...options, | ||
}) | ||
} | ||
} |
Oops, something went wrong.