Skip to content

Commit 73cb88c

Browse files
committed
particles wrapper update plus tween and hue support.
1 parent 4497b47 commit 73cb88c

File tree

8 files changed

+151
-33
lines changed

8 files changed

+151
-33
lines changed

assets/plugins/particle-storm.js

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

base/Map.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,7 @@ export class Map {
10651065
property_info.message,
10661066
property_info.thought_message,
10671067
property_info.back_interaction_message,
1068+
property_info.allow_only_front_interaction,
10681069
avatar,
10691070
property_info.shop_key,
10701071
property_info.inn_key,
@@ -1475,6 +1476,9 @@ export class Map {
14751476
if (layer_obj.properties.reveal_layer || hidden) {
14761477
layer_sprite.visible = false;
14771478
}
1479+
if (layer_obj.properties.opacity !== undefined) {
1480+
layer_sprite.alpha = layer_obj.properties.opacity;
1481+
}
14781482
} else {
14791483
layer_sprite = layer_obj.sprite;
14801484
}

base/NPC.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class NPC extends ControllableChar {
3838
private _message: string;
3939
private _thought_message: string;
4040
private _back_interaction_message: string;
41+
private _allow_only_front_interaction: boolean;
4142
private _avatar: string;
4243
private _voice_key: string;
4344
private _base_collision_layer: number;
@@ -114,6 +115,7 @@ export class NPC extends ControllableChar {
114115
message,
115116
thought_message,
116117
back_interaction_message,
118+
allow_only_front_interaction,
117119
avatar,
118120
shop_key,
119121
inn_key,
@@ -174,6 +176,7 @@ export class NPC extends ControllableChar {
174176
this._message = message ?? "";
175177
this._thought_message = thought_message ?? "";
176178
this._back_interaction_message = back_interaction_message ?? "";
179+
this._allow_only_front_interaction = allow_only_front_interaction ?? false;
177180
this._avatar = avatar ?? null;
178181
this._voice_key = voice_key ?? "";
179182
this._shop_key = shop_key;
@@ -235,6 +238,10 @@ export class NPC extends ControllableChar {
235238
get back_interaction_message() {
236239
return this._back_interaction_message;
237240
}
241+
/** If true, the hero will only be able to interact with this NPC when he's on the front of it. */
242+
get allow_only_front_interaction() {
243+
return this._allow_only_front_interaction;
244+
}
238245
/** The avatar key of this NPC. */
239246
get avatar() {
240247
return this._avatar;

base/ParticlesWrapper.ts

Lines changed: 92 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {GoldenSun} from "GoldenSun";
33
import {GAME_HEIGHT, GAME_WIDTH} from "./magic_numbers";
44
import {elements, element_colors_in_battle, hex2rgb} from "./utils";
55
import * as _ from "lodash";
6+
import {EventValue} from "game_events/GameEvent";
67

78
export type AdvParticleValue =
89
| number
@@ -87,6 +88,8 @@ export type Emitter = {
8788
step: number;
8889
visible: boolean;
8990
};
91+
hue_angle?: number;
92+
random_animation_start?: boolean;
9093
particles_display_blend_mode?: string;
9194
render_white_core?: boolean;
9295
core_custom_color?: string;
@@ -123,6 +126,13 @@ export type Emitter = {
123126
frame_rate: number;
124127
loop: boolean;
125128
};
129+
tween_emitter?: {
130+
duration: number;
131+
x?: number | EventValue;
132+
y?: number | EventValue;
133+
easing?: string;
134+
incremental?: boolean;
135+
};
126136
};
127137

128138
export type ParticlesInfo = {
@@ -154,10 +164,10 @@ export class ParticlesWrapper {
154164
},
155165
element?: elements,
156166
xy_pos_getter?: (
157-
x: number | string,
158-
y: number | string,
159-
shift_x: number,
160-
shift_y: number
167+
x: number | string | EventValue,
168+
y: number | string | EventValue,
169+
shift_x: number | EventValue,
170+
shift_y: number | EventValue
161171
) => {x: number; y: number}
162172
) {
163173
const promises: Promise<void>[] = [];
@@ -317,7 +327,59 @@ export class ParticlesWrapper {
317327
emitter_info.shift_x,
318328
emitter_info.shift_y
319329
);
320-
emitter.emit(emitter_info.emitter_data_key, x, y, {
330+
if (
331+
emitter_info.hue_angle !== undefined ||
332+
emitter_info.random_animation_start ||
333+
adv_particles_seq.particles_callback ||
334+
emitter_info.animation !== undefined
335+
) {
336+
emitter.onEmit = new Phaser.Signal();
337+
emitter.onEmit.add(
338+
(emitter: Phaser.ParticleStorm.Emitter, particle: Phaser.ParticleStorm.Particle) => {
339+
if (emitter_info.hue_angle !== undefined) {
340+
if (!particle.sprite.filters) {
341+
const hue_filter = this.game.add.filter("Hue") as Phaser.Filter.Hue;
342+
particle.sprite.filters = [hue_filter];
343+
hue_filter.angle = emitter_info.hue_angle;
344+
}
345+
}
346+
if (emitter_info.random_animation_start) {
347+
if (particle.sprite.animations.currentAnim) {
348+
particle.sprite.frameName = _.sample(
349+
Object.keys(particle.sprite.animations.currentAnim._frameData._frameNames)
350+
);
351+
}
352+
}
353+
if (adv_particles_seq.particles_callback) {
354+
adv_particles_seq.particles_callback(particle);
355+
}
356+
if (emitter_info.animation !== undefined) {
357+
if (
358+
!particle.sprite.animations.currentAnim ||
359+
!particle.sprite.animations.currentAnim.isPlaying
360+
) {
361+
const particle_key = adv_particles_seq.data[emitter_info.emitter_data_key]
362+
.image as string;
363+
const particle_sprite_base = this.data.info.misc_sprite_base_list[particle_key];
364+
const anim_key = particle_sprite_base.getAnimationKey(
365+
particle_key,
366+
emitter_info.animation.animation_key
367+
);
368+
particle_sprite_base.setAnimation(particle.sprite, particle_key);
369+
particle.sprite.animations.play(
370+
anim_key,
371+
emitter_info.animation.frame_rate,
372+
emitter_info.animation.loop
373+
);
374+
}
375+
}
376+
}
377+
);
378+
}
379+
const pos = {x: x, y: y};
380+
const get_x = () => pos.x;
381+
const get_y = () => pos.y;
382+
emitter.emit(emitter_info.emitter_data_key, get_x, get_y, {
321383
...(emitter_info.total !== undefined && {total: emitter_info.total}),
322384
...(emitter_info.repeat !== undefined && {repeat: emitter_info.repeat}),
323385
...(emitter_info.frequency !== undefined && {frequency: emitter_info.frequency}),
@@ -330,31 +392,32 @@ export class ParticlesWrapper {
330392
...(emitter_info.radiate !== undefined && {radiate: emitter_info.radiate}),
331393
...(emitter_info.radiateFrom !== undefined && {radiateFrom: emitter_info.radiateFrom}),
332394
});
333-
if (adv_particles_seq.particles_callback) {
334-
emitter.forEach((particle: Phaser.ParticleStorm.Particle) => {
335-
adv_particles_seq.particles_callback(particle);
336-
}, this);
337-
}
338-
if (emitter_info.animation !== undefined) {
339-
const particle_key = adv_particles_seq.data[emitter_info.emitter_data_key].image as string;
340-
const particle_sprite_base = this.data.info.misc_sprite_base_list[particle_key];
341-
const anim_key = particle_sprite_base.getAnimationKey(
342-
particle_key,
343-
emitter_info.animation.animation_key
344-
);
345-
emitter.forEach((particle: Phaser.ParticleStorm.Particle) => {
346-
particle_sprite_base.setAnimation(particle.sprite, particle_key);
347-
}, this);
348-
emitter.onEmit = new Phaser.Signal();
349-
emitter.onEmit.add(
350-
(emitter: Phaser.ParticleStorm.Emitter, particle: Phaser.ParticleStorm.Particle) => {
351-
particle.sprite.animations.play(
352-
anim_key,
353-
emitter_info.animation.frame_rate,
354-
emitter_info.animation.loop
355-
);
395+
if (emitter_info.tween_emitter) {
396+
const dest: {x?: number; y?: number} = {};
397+
if (emitter_info.tween_emitter.x) {
398+
if (typeof emitter_info.tween_emitter.x !== "number") {
399+
dest.x = this.data.game_event_manager.get_value(emitter_info.tween_emitter.x);
400+
} else {
401+
dest.x = emitter_info.tween_emitter.x;
356402
}
357-
);
403+
dest.x = (emitter_info.tween_emitter.incremental ? pos.x : 0) + dest.x;
404+
}
405+
if (emitter_info.tween_emitter.y) {
406+
if (typeof emitter_info.tween_emitter.y !== "number") {
407+
dest.y = this.data.game_event_manager.get_value(emitter_info.tween_emitter.y);
408+
} else {
409+
dest.y = emitter_info.tween_emitter.y;
410+
}
411+
dest.y = (emitter_info.tween_emitter.incremental ? pos.y : 0) + dest.y;
412+
}
413+
this.game.add
414+
.tween(pos)
415+
.to(
416+
dest,
417+
emitter_info.tween_emitter.duration,
418+
_.get(Phaser.Easing, emitter_info.tween_emitter.easing ?? "Linear.None"),
419+
true
420+
);
358421
}
359422
emitters.push(emitter);
360423
});

base/game_events/GameEventManager.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ export class GameEventManager {
169169
}
170170
const is_close_check = this.data.hero.is_close(npc);
171171
if (is_close_check) {
172+
if (
173+
npc.allow_only_front_interaction &&
174+
(npc.tile_pos.y + 1 !== this.data.hero.tile_pos.y || npc.tile_pos.x !== this.data.hero.tile_pos.x)
175+
) {
176+
continue;
177+
}
172178
this.data.hero.stop_char();
173179
npc.stop_char();
174180
this.control_enable = false;

base/game_events/ParticlesEvent.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {ParticlesInfo} from "ParticlesWrapper";
2-
import {GameEvent, event_types} from "./GameEvent";
2+
import {EventValue, GameEvent, event_types} from "./GameEvent";
33

44
enum game_groups {
55
LOWER = "lower",
@@ -29,7 +29,39 @@ export class ParticlesEvent extends GameEvent {
2929

3030
async _fire() {
3131
++this.data.game_event_manager.events_running_count;
32-
const promises = this.data.particle_wrapper.start_particles(this.particles_info, this.group);
32+
const xy_pos_getter = (
33+
x: number | EventValue,
34+
y: number | EventValue,
35+
shift_x: number | EventValue,
36+
shift_y: number | EventValue
37+
) => {
38+
let this_x = x as number;
39+
let this_y = y as number;
40+
let this_shift_x = shift_x as number;
41+
let this_shift_y = shift_y as number;
42+
if (x !== undefined && typeof x !== "number") {
43+
this_x = this.data.game_event_manager.get_value(x);
44+
}
45+
if (y !== undefined && typeof y !== "number") {
46+
this_y = this.data.game_event_manager.get_value(y);
47+
}
48+
if (shift_x !== undefined && typeof shift_x !== "number") {
49+
this_shift_x = this.data.game_event_manager.get_value(shift_x);
50+
}
51+
if (shift_y !== undefined && typeof shift_y !== "number") {
52+
this_shift_y = this.data.game_event_manager.get_value(shift_y);
53+
}
54+
this_x += this_shift_x ?? 0;
55+
this_y += this_shift_y ?? 0;
56+
return {x: this_x, y: this_y};
57+
};
58+
const promises = this.data.particle_wrapper.start_particles(
59+
this.particles_info,
60+
this.group,
61+
undefined,
62+
undefined,
63+
xy_pos_getter
64+
);
3365
const udpate_callback = () => this.data.particle_wrapper.render();
3466
this.data.game_event_manager.add_callback(udpate_callback);
3567
await Promise.all(promises);

types/particlestorm.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ declare module Phaser {
191191
scrollSpeed: Phaser.Point;
192192
force: Phaser.Point;
193193
onEmit: Phaser.Signal;
194+
newParticleCallbacks?: ((sprite: Phaser.Sprite) => void)[]
194195
onComplete: Phaser.Signal;
195196
onKill: Phaser.Signal;
196197
particleClass: Phaser.ParticleStorm.Particle;

types/phaser.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ declare module Phaser {
135135
enableUpdate: boolean;
136136
frame: number;
137137
frameTotal: number;
138+
_frameData: any;
138139
game: Phaser.Game;
139140
isFinished: boolean;
140141
isPaused: boolean;

0 commit comments

Comments
 (0)