Skip to content

Commit

Permalink
feat: added tilt effect to particles, this was called wobble in previ…
Browse files Browse the repository at this point in the history
…ous commit

build: disabled wobble effect since it was the tilt effect, this needs new work
  • Loading branch information
matteobruni committed Jun 21, 2021
1 parent a3e9769 commit 7eade2e
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 9 deletions.
1 change: 1 addition & 0 deletions core/main/src/Core/Interfaces/IParticle.ts
Expand Up @@ -35,6 +35,7 @@ export interface IParticle {
readonly opacity: IParticleValueAnimation<number>;
readonly rotate: IParticleValueAnimation<number>;
readonly size: IParticleValueAnimation<number>;
readonly tilt: IParticleValueAnimation<number>;
readonly strokeColor?: IParticleHslAnimation;
readonly options: IParticles;
readonly position: Vector;
Expand Down
45 changes: 44 additions & 1 deletion core/main/src/Core/Particle.ts
Expand Up @@ -10,7 +10,15 @@ import type { IParticle } from "./Interfaces/IParticle";
import type { IParticles } from "../Options/Interfaces/Particles/IParticles";
import { ParticlesOptions } from "../Options/Classes/Particles/ParticlesOptions";
import { Shape } from "../Options/Classes/Particles/Shape/Shape";
import { AnimationStatus, DestroyMode, OutMode, RotateDirection, ShapeType, StartValueType } from "../Enums";
import {
AnimationStatus,
DestroyMode,
OutMode,
RotateDirection,
ShapeType,
StartValueType,
TiltDirection,
} from "../Enums";
import { ImageDrawer } from "../ShapeDrawers/ImageDrawer";
import type { IImageShape } from "../Options/Interfaces/Particles/Shape/IImageShape";
import type { RecursivePartial } from "../Types";
Expand Down Expand Up @@ -75,6 +83,7 @@ export class Particle implements IParticle {
readonly opacity: IParticleValueAnimation<number>;
readonly rotate: IParticleValueAnimation<number>;
readonly size: IParticleValueAnimation<number>;
readonly tilt: IParticleValueAnimation<number>;
readonly strokeColor?: IParticleHslAnimation;
readonly velocity: Vector;
readonly shape: ShapeType | string;
Expand Down Expand Up @@ -230,6 +239,40 @@ export class Particle implements IParticle {
}
}

const tiltOptions = this.options.tilt;

this.tilt = {
value: (NumberUtils.getRangeValue(tiltOptions.value) * Math.PI) / 180,
};

let tiltDirection = tiltOptions.direction;

if (tiltDirection === TiltDirection.random) {
const index = Math.floor(Math.random() * 2);

tiltDirection = index > 0 ? TiltDirection.counterClockwise : TiltDirection.clockwise;
}

switch (tiltDirection) {
case TiltDirection.counterClockwise:
case "counterClockwise":
this.tilt.status = AnimationStatus.decreasing;
break;
case TiltDirection.clockwise:
this.tilt.status = AnimationStatus.increasing;
break;
}

const tiltAnimation = this.options.tilt.animation;

if (tiltAnimation.enable) {
this.tilt.velocity = (tiltAnimation.speed / 360) * container.retina.reduceFactor;

if (!tiltAnimation.sync) {
this.tilt.velocity *= Math.random();
}
}

const sizeAnimation = this.options.size.animation;

if (sizeAnimation.enable) {
Expand Down
34 changes: 32 additions & 2 deletions core/main/src/Core/Particle/Updater.ts
@@ -1,9 +1,8 @@
import type { Container } from "../Container";
import type { Particle } from "../Particle";
import { NumberUtils, Utils } from "../../Utils";
import { AnimationStatus, DestroyType, OutMode, OutModeAlt } from "../../Enums";
import { AnimationStatus, DestroyType, OutMode, OutModeDirection, OutModeAlt } from "../../Enums";
import type { IDelta } from "../Interfaces/IDelta";
import { OutModeDirection } from "../../Enums/Directions/OutModeDirection";
import { IBounds } from "../Interfaces/IBounds";
import { IDimension } from "../Interfaces/IDimension";
import { ICoordinates } from "../Interfaces/ICoordinates";
Expand Down Expand Up @@ -150,6 +149,9 @@ export class Updater {
/* change rotation */
this.updateAngle(delta);

/* change tilt */
this.updateTilt(delta);

/* change wobble */
this.updateWobble(delta);

Expand Down Expand Up @@ -322,6 +324,34 @@ export class Updater {
}
}

private updateTilt(delta: IDelta): void {
const particle = this.particle;
const tilt = particle.options.tilt;
const tiltAnimation = tilt.animation;
const speed = (particle.tilt.velocity ?? 0) * delta.factor;
const max = 2 * Math.PI;

if (tiltAnimation.enable) {
switch (particle.tilt.status) {
case AnimationStatus.increasing:
particle.tilt.value += speed;

if (particle.tilt.value > max) {
particle.tilt.value -= max;
}
break;
case AnimationStatus.decreasing:
default:
particle.tilt.value -= speed;

if (particle.tilt.value < 0) {
particle.tilt.value += max;
}
break;
}
}
}

private updateWobble(delta: IDelta): void {
const particle = this.particle;
const wobble = particle.options.wobble;
Expand Down
10 changes: 10 additions & 0 deletions core/main/src/Enums/Directions/TiltDirection.ts
@@ -0,0 +1,10 @@
/**
* @category Enums
*/
export enum TiltDirection {
clockwise = "clockwise",
counterClockwise = "counter-clockwise",
random = "random",
}

export type TiltDirectionAlt = "counter-clockwise";
2 changes: 2 additions & 0 deletions core/main/src/Enums/Directions/index.ts
@@ -1,2 +1,4 @@
export * from "./MoveDirection";
export * from "./RotateDirection";
export * from "./OutModeDirection";
export * from "./TiltDirection";
4 changes: 4 additions & 0 deletions core/main/src/Options/Classes/Particles/ParticlesOptions.ts
Expand Up @@ -17,6 +17,7 @@ import { Life } from "./Life/Life";
import { Bounce } from "./Bounce/Bounce";
import { Destroy } from "./Destroy/Destroy";
import { Wobble } from "./Wobble/Wobble";
import { Tilt } from "./Tilt/Tilt";

/**
* [[include:Options/Particles.md]]
Expand All @@ -38,6 +39,7 @@ export class ParticlesOptions implements IParticles, IOptionLoader<IParticles> {
size;
shadow;
stroke: SingleOrMultiple<Stroke>;
tilt;
twinkle;
wobble;

Expand Down Expand Up @@ -91,6 +93,7 @@ export class ParticlesOptions implements IParticles, IOptionLoader<IParticles> {
this.shape = new Shape();
this.size = new Size();
this.stroke = new Stroke();
this.tilt = new Tilt();
this.twinkle = new Twinkle();
this.wobble = new Wobble();
}
Expand Down Expand Up @@ -124,6 +127,7 @@ export class ParticlesOptions implements IParticles, IOptionLoader<IParticles> {
this.shape.load(data.shape);
this.size.load(data.size);
this.shadow.load(data.shadow);
this.tilt.load(data.tilt);
this.twinkle.load(data.twinkle);
this.wobble.load(data.wobble);

Expand Down
42 changes: 42 additions & 0 deletions core/main/src/Options/Classes/Particles/Tilt/Tilt.ts
@@ -0,0 +1,42 @@
import { TiltAnimation } from "./TiltAnimation";
import { TiltDirection, TiltDirectionAlt } from "../../../../Enums";
import type { RecursivePartial } from "../../../../Types";
import type { IOptionLoader } from "../../../Interfaces/IOptionLoader";
import { ValueWithRandom } from "../../ValueWithRandom";
import type { ITilt } from "../../../Interfaces/Particles/Tilt/ITilt";

/**
* [[include:Options/Particles/Rotate.md]]
* @category Options
*/
export class Tilt extends ValueWithRandom implements ITilt, IOptionLoader<ITilt> {
animation;
direction: TiltDirection | keyof typeof TiltDirection | TiltDirectionAlt;
enable;

constructor() {
super();
this.animation = new TiltAnimation();
this.direction = TiltDirection.clockwise;
this.enable = false;
this.value = 0;
}

load(data?: RecursivePartial<ITilt>): void {
if (!data) {
return;
}

super.load(data);

this.animation.load(data.animation);

if (data.direction !== undefined) {
this.direction = data.direction;
}

if (data.enable !== undefined) {
this.enable = data.enable;
}
}
}
36 changes: 36 additions & 0 deletions core/main/src/Options/Classes/Particles/Tilt/TiltAnimation.ts
@@ -0,0 +1,36 @@
import type { RecursivePartial } from "../../../../Types";
import type { IOptionLoader } from "../../../Interfaces/IOptionLoader";
import type { ITiltAnimation } from "../../../Interfaces/Particles/Tilt/ITiltAnimation";

/**
* @category Options
*/
export class TiltAnimation implements ITiltAnimation, IOptionLoader<ITiltAnimation> {
enable;
speed;
sync;

constructor() {
this.enable = false;
this.speed = 0;
this.sync = false;
}

load(data?: RecursivePartial<ITiltAnimation>): void {
if (data === undefined) {
return;
}

if (data.enable !== undefined) {
this.enable = data.enable;
}

if (data.speed !== undefined) {
this.speed = data.speed;
}

if (data.sync !== undefined) {
this.sync = data.sync;
}
}
}
2 changes: 2 additions & 0 deletions core/main/src/Options/Interfaces/Particles/IParticles.ts
Expand Up @@ -15,6 +15,7 @@ import type { ILife } from "./Life/ILife";
import type { IBounce } from "./Bounce/IBounce";
import type { IDestroy } from "./Destroy/IDestroy";
import type { IWobble } from "./Wobble/IWobble";
import { ITilt } from "./Tilt/ITilt";

/**
* [[include:Options/Particles.md]]
Expand Down Expand Up @@ -46,6 +47,7 @@ export interface IParticles {
shape: IShape;
size: ISize;
stroke: SingleOrMultiple<IStroke>;
tilt: ITilt;
twinkle: ITwinkle;
wobble: IWobble;
}
13 changes: 13 additions & 0 deletions core/main/src/Options/Interfaces/Particles/Tilt/ITilt.ts
@@ -0,0 +1,13 @@
import type { ITiltAnimation } from "./ITiltAnimation";
import type { TiltDirection, TiltDirectionAlt } from "../../../../Enums";
import type { IValueWithRandom } from "../../IValueWithRandom";

/**
* [[include:Options/Particles/Rotate.md]]
* @category Options
*/
export interface ITilt extends IValueWithRandom {
animation: ITiltAnimation;
direction: TiltDirection | keyof typeof TiltDirection | TiltDirectionAlt;
enable: boolean;
}
@@ -0,0 +1,8 @@
/**
* @category Options
*/
export interface ITiltAnimation {
enable: boolean;
speed: number;
sync: boolean;
}
10 changes: 5 additions & 5 deletions core/main/src/Utils/CanvasUtils.ts
Expand Up @@ -343,11 +343,11 @@ export class CanvasUtils {
shadow: IShadow
): void {
const pos = particle.getPosition();
const wobbleOptions = particle.options.wobble;
const tiltOptions = particle.options.tilt;

context.save();
if (wobbleOptions.enable) {
context.transform(1, Math.cos(particle.wobbleAngle), Math.sin(particle.wobbleAngle), 1, pos.x, pos.y);
if (tiltOptions.enable) {
context.transform(1, Math.cos(particle.tilt.value), Math.sin(particle.tilt.value), 1, pos.x, pos.y);
} else {
context.translate(pos.x, pos.y);
}
Expand Down Expand Up @@ -401,8 +401,8 @@ export class CanvasUtils {
context.restore();

context.save();
if (wobbleOptions.enable) {
context.transform(1, Math.cos(particle.wobbleAngle), Math.sin(particle.wobbleAngle), 1, pos.x, pos.y);
if (tiltOptions.enable) {
context.transform(1, Math.cos(particle.tilt.value), Math.sin(particle.tilt.value), 1, pos.x, pos.y);
} else {
context.translate(pos.x, pos.y);
}
Expand Down
15 changes: 14 additions & 1 deletion demo/vanilla/public/presets/wobble.json
Expand Up @@ -31,7 +31,10 @@
"decay": 0.1,
"distance": 0,
"direction": "top",
"drift": 2,
"drift": {
"min": -2,
"max": 2
},
"enable": true,
"gravity": {
"acceleration": 9.81,
Expand All @@ -57,6 +60,16 @@
"value": 0.5
},
"rotate": {
"value": 0,
"direction": "random",
"animation": {
"enable": true,
"speed": 60
}
},
"tilt": {
"direction": "random",
"enable": true,
"value": 0,
"animation": {
"enable": true,
Expand Down

0 comments on commit 7eade2e

Please sign in to comment.