Skip to content

Commit

Permalink
feat: add FTransform
Browse files Browse the repository at this point in the history
  • Loading branch information
Gugustinette committed Aug 29, 2024
1 parent ce32859 commit 525fb54
Show file tree
Hide file tree
Showing 20 changed files with 248 additions and 131 deletions.
8 changes: 4 additions & 4 deletions packages/2d/src/FCollider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ export class FCollider {
// Devide the scale by 2 for the collider (RAPIER uses half-extents)
// Also interpete the scale as relative to the component's scale
options.scale = {
x: component.scale.x * (options.scale.x / 2),
y: component.scale.y * (options.scale.y / 2),
x: component.transform.scale.x * (options.scale.x / 2),
y: component.transform.scale.y * (options.scale.y / 2),
}

// Create a collider description according to the shape given
Expand All @@ -109,13 +109,13 @@ export class FCollider {
// If no rigidbody given, the collider is free : set translation and rotation for the collider
if (options.rigidBody === undefined) {
// Interprete the given position as relative to the component's position
const finalPosition = component.position
const finalPosition = component.transform.position
finalPosition.x += options.position.x
finalPosition.y += options.position.y
colliderDesc.setTranslation(finalPosition.x, finalPosition.y)

// Interprete the given rotation as relative to the component's rotation
const finalRotation = component.rotation + options.rotation
const finalRotation = component.transform.rotation + options.rotation
colliderDesc.setRotation(finalRotation)
}
// Set the sensor flag
Expand Down
68 changes: 31 additions & 37 deletions packages/2d/src/FComponent.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { FComponent as FComponentCore } from '@fibbojs/core'
import { Container } from 'pixi.js'
import * as RAPIER from '@dimforge/rapier2d'
import type * as PIXI from 'pixi.js'
import type { FScene } from './FScene'
import type { FColliderOptions } from './FCollider'
import { FCollider } from './FCollider'
import type { FRigidBodyOptions } from './FRigidBody'
import { FRigidBody } from './FRigidBody'
import { FTransform } from './FTransform'

export interface FComponentOptions {
position?: { x: number, y: number }
Expand Down Expand Up @@ -35,19 +35,10 @@ export abstract class FComponent extends FComponentCore {
*/
container: Container

// Transform
/**
* Position of the component.
* Transforms
*/
position: { x: number, y: number }
/**
* Scale of the component.
*/
scale: { x: number, y: number }
/**
* Rotation of the component.
*/
rotation: number
transform: FTransform

// Physics & collision
/**
Expand Down Expand Up @@ -89,14 +80,17 @@ export abstract class FComponent extends FComponentCore {
if (!options.position || !options.scale || (options.rotation === undefined && options.rotationDegree === undefined))
throw new Error('FibboError: FComponent requires position, scale and rotation options')

// Set the transform values
this.position = options.position
this.scale = options.scale
this.rotation = options.rotationDegree ? options.rotationDegree * (Math.PI / 180) : options.rotation ?? 0
// Create the transform
this.transform = new FTransform({
position: options.position,
scale: options.scale,
rotation: options.rotation,
rotationDegree: options.rotationDegree,
})
// Set the container values
this.container.position.set(this.position.x, this.position.y)
this.container.scale.set(this.scale.x * 100, this.scale.y * 100)
this.container.rotation = this.rotation
this.container.position.set(this.transform.position.x, this.transform.position.y)
this.container.scale.set(this.transform.scale.x * 100, this.transform.scale.y * 100)
this.container.rotation = this.transform.rotation
// Set the pivot of the container to the center
this.container.pivot.set(this.container.width / 2, this.container.height / 2)
}
Expand All @@ -109,11 +103,11 @@ export abstract class FComponent extends FComponentCore {
this.container.position.set(newContainerPosition.x * 100, -newContainerPosition.y * 100)
this.container.rotation = -newContainerRotation
// Update position and rotation properties of the component according to the rigid body
this.position = {
this.transform.position = {
x: this.container.position.x / 100,
y: -this.container.position.y / 100,
}
this.rotation = this.container.rotation
this.transform.rotation = this.container.rotation
// If a sensor exists, update its position and rotation according to the rigid body
if (this.sensor) {
// Apply offset to the sensor
Expand Down Expand Up @@ -142,17 +136,17 @@ export abstract class FComponent extends FComponentCore {
this.container.position.set(newContainerPosition.x * 100, -newContainerPosition.y * 100)
this.container.rotation = -newContainerRotation
// Update position and rotation properties of the component according to the collider
this.position = {
this.transform.position = {
x: this.container.position.x / 100,
y: -this.container.position.y / 100,
}
this.rotation = this.container.rotation
this.transform.rotation = this.container.rotation
}
else {
// If the rigid body and collider doesn't exist, update the container position and rotation according to the default values
// The y position is inverted because the y axis is inverted in PIXI.js compared to Rapier
this.container.position.set(this.position.x * 100, -this.position.y * 100)
this.container.rotation = this.rotation
this.container.position.set(this.transform.position.x * 100, -this.transform.position.y * 100)
this.container.rotation = this.transform.rotation
}
}

Expand All @@ -167,7 +161,7 @@ export abstract class FComponent extends FComponentCore {
* ```
*/
setPosition(options: { x: number, y: number }): void {
this.position = { x: options.x, y: options.y }
this.transform.position = { x: options.x, y: options.y }
this.container.position.set(options.x, options.y)
// If a collider exists, update its translation
if (this.collider)
Expand All @@ -188,7 +182,7 @@ export abstract class FComponent extends FComponentCore {
* ```
*/
setScale(options: { x: number, y: number }): void {
this.scale = { x: options.x, y: options.y }
this.transform.scale = { x: options.x, y: options.y }
this.container.height = options.y * 100
this.container.width = options.x * 100
// If a collider exists
Expand Down Expand Up @@ -216,7 +210,7 @@ export abstract class FComponent extends FComponentCore {
* ```
*/
setRotation(r: number): void {
this.rotation = r
this.transform.rotation = r
this.container.rotation = r
// If a collider exists, update its rotation
if (this.collider)
Expand Down Expand Up @@ -332,42 +326,42 @@ export abstract class FComponent extends FComponentCore {
* Setters & getters for transform properties
*/
get x(): number {
return this.position.x
return this.transform.position.x
}

set x(x: number) {
this.setPosition({ x, y: this.position.y })
this.setPosition({ x, y: this.transform.position.y })
}

get y(): number {
return this.position.y
return this.transform.position.y
}

set y(y: number) {
this.setPosition({ x: this.position.x, y })
this.setPosition({ x: this.transform.position.x, y })
}

get rotationDegree(): number {
return this.rotation * (180 / Math.PI)
return this.transform.rotation * (180 / Math.PI)
}

set rotationDegree(r: number) {
this.setRotationDegree(r)
}

get scaleX(): number {
return this.scale.x
return this.transform.scale.x
}

set scaleX(x: number) {
this.setScale({ x, y: this.scale.y })
this.setScale({ x, y: this.transform.scale.y })
}

get scaleY(): number {
return this.scale.y
return this.transform.scale.y
}

set scaleY(y: number) {
this.setScale({ x: this.scale.x, y })
this.setScale({ x: this.transform.scale.x, y })
}
}
6 changes: 3 additions & 3 deletions packages/2d/src/FRigidBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ export class FRigidBody {
const rigidBodyDesc = new RAPIER.RigidBodyDesc(options.rigidBodyType as RAPIER.RigidBodyType)
// Interprete the given position as relative to the component's position
rigidBodyDesc.setTranslation(
component.position.x + options.position.x,
component.position.y + options.position.y,
component.transform.position.x + options.position.x,
component.transform.position.y + options.position.y,
)

// Interprete the given rotation as relative to the component's rotation
rigidBodyDesc.setRotation(component.rotation + options.rotation)
rigidBodyDesc.setRotation(component.transform.rotation + options.rotation)

// Create the rigid body
this.rigidBody = component.scene.world.createRigidBody(rigidBodyDesc)
Expand Down
60 changes: 60 additions & 0 deletions packages/2d/src/FTransform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
export interface FTransformOptions {
position?: { x: number, y: number }
scale?: { x: number, y: number }
rotation?: number
rotationDegree?: number
}

/**
* @description 2D Transforms for a component.
* @category Core
*/
export class FTransform {
/**
* Position of the component.
*/
position: { x: number, y: number }
/**
* Scale of the component.
*/
scale: { x: number, y: number }
/**
* Rotation of the component.
*/
rotation: number

/**
* @description Create a new FTransform.
* @param options The options for the collider.
* @param options.position The position of the collider. If not defined, it will default to `{ x: 0, y: 5 }`.
* @param options.scale The scale of the collider. If not defined, it will default to `{ x: 1, y: 1 }`.
* @param options.rotation The rotation of the collider. If not defined, it will default to 0.
* @param options.rotationDegree The rotation of the collider in degrees. If not defined, it will default to undefined.
* @example
* ```ts
* const collider = new FTransform({
* position: { x: 0, y: 0 },
* scale: { x: 1, y: 1 },
* rotation: 0,
* })
* ```
*/
constructor(options?: FTransformOptions) {
// Define default options
const DEFAULT_OPTIONS = {
position: { x: 0, y: 5 },
scale: { x: 1, y: 1 },
rotation: 0,
}
// Apply default options
options = { ...DEFAULT_OPTIONS, ...options }
// Validate options
if (!options.position || !options.scale || (options.rotation === undefined && options.rotationDegree === undefined))
throw new Error('FibboError: FComponent requires position, scale and rotation options')

// Set the transform values
this.position = options.position
this.scale = options.scale
this.rotation = options.rotationDegree ? options.rotationDegree * (Math.PI / 180) : options.rotation ?? 0
}
}
4 changes: 2 additions & 2 deletions packages/2d/src/cameras/FAttachedCamera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export class FAttachedCamera extends FCamera {
onFrame(_delta: number): void {
// Move the camera to the target
this.scene.viewport.moveCenter(
this.target.position.x * 100 + this.position.x * 100,
-this.target.position.y * 100 - this.position.y * 100,
this.target.transform.position.x * 100 + this.position.x * 100,
-this.target.transform.position.y * 100 - this.position.y * 100,
)
}

Expand Down
4 changes: 2 additions & 2 deletions packages/2d/src/character/FCharacter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ export abstract class FCharacter extends FComponent {

// 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))
.rect(this.transform.position.x, this.transform.position.y, this.transform.scale.x * 100, this.transform.scale.y * 100)
.fill(new PIXI.FillGradient(0, 0, this.transform.scale.x * 100, this.transform.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)

Expand Down
4 changes: 3 additions & 1 deletion packages/2d/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
export { FScene } from './FScene'
export { FComponent } from './FComponent'
export { FComponentEmpty } from './FComponentEmpty'
export { FTransform } from './FTransform'

// Cameras
export { FCamera } from './cameras/FCamera'
export { FAttachedCamera } from './cameras/FAttachedCamera'
export { FFixedCamera } from './cameras/FFixedCamera'
export { FFreeCamera } from './cameras/FFreeCamera'

// Character
// Character controllers
export { FCharacter } from './character/FCharacter'
export { FCharacterDynamic } from './character/FCharacterDynamic'
export { FCharacterKinematic } from './character/FCharacterKinematic'
Expand All @@ -34,3 +35,4 @@ export type { FRigidBodyOptions } from './FRigidBody'
export type { FCameraOptions } from './cameras/FCamera'
export type { FCharacterOptions } from './character/FCharacter'
export type { FSceneOptions } from './FScene'
export type { FTransformOptions } from './FTransform'
2 changes: 1 addition & 1 deletion packages/2d/src/polygons/FCircle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class FCircle extends FComponent {
super(scene, options)
// Create a circle
this.container = new PIXI.Graphics()
.circle(this.position.x, this.position.y, this.scale.x * 100 / 2)
.circle(this.transform.position.x, this.transform.position.y, this.transform.scale.x * 100 / 2)
.fill(new PIXI.FillGradient(0, 0, 10, 10).addColorStop(0, 0x0000FF).addColorStop(1, 0xFFFF00))
}

Expand Down
4 changes: 2 additions & 2 deletions packages/2d/src/polygons/FSquare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ export class FSquare extends FComponent {
super(scene, options)
// 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))
.rect(this.transform.position.x, this.transform.position.y, this.transform.scale.x * 100, this.transform.scale.y * 100)
.fill(new PIXI.FillGradient(0, 0, this.transform.scale.x * 100, this.transform.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)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/2d/src/sprite/FSprite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class FSprite extends FComponent {
// Define the texture and container while loading
this.texture = PIXI.Texture.EMPTY
this.container = new PIXI.Graphics()
.rect(this.position.x, this.position.y, this.scale.x * 100, this.scale.y * 100)
.rect(this.transform.position.x, this.transform.position.y, this.transform.scale.x * 100, this.transform.scale.y * 100)
.fill(new PIXI.FillGradient(0, 0, 100, 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)
Expand Down
18 changes: 9 additions & 9 deletions packages/3d/src/FCollider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ export class FCollider {
// Devide the scale by 2 for the collider (RAPIER uses half-extents)
// Also interpete the scale as relative to the component's scale
options.scale = {
x: component.scale.x * (options.scale.x / 2),
y: component.scale.y * (options.scale.y / 2),
z: component.scale.z * (options.scale.z / 2),
x: component.transform.scale.x * (options.scale.x / 2),
y: component.transform.scale.y * (options.scale.y / 2),
z: component.transform.scale.z * (options.scale.z / 2),
}

// Create a collider description according to the shape given
Expand Down Expand Up @@ -140,19 +140,19 @@ export class FCollider {
if (options.rigidBody === undefined) {
// Interprete the given position as relative to the component's position
const finalPosition = new THREE.Vector3(
component.position.x + options.position.x,
component.position.y + options.position.y,
component.position.z + options.position.z,
component.transform.position.x + options.position.x,
component.transform.position.y + options.position.y,
component.transform.position.z + options.position.z,
)
finalPosition.add(this.colliderPositionOffset)
colliderDesc.setTranslation(finalPosition.x, finalPosition.y, finalPosition.z)

// Interprete the given rotation as relative to the component's rotation
const finalRotation = new THREE.Quaternion().setFromEuler(
new THREE.Euler(
component.rotation.x + options.rotation.x,
component.rotation.y + options.rotation.y,
component.rotation.z + options.rotation.z,
component.transform.rotation.x + options.rotation.x,
component.transform.rotation.y + options.rotation.y,
component.transform.rotation.z + options.rotation.z,
),
)
colliderDesc.setRotation(finalRotation)
Expand Down
Loading

0 comments on commit 525fb54

Please sign in to comment.