Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Hello once again. I'm trying to create a looping animation using modifiers, similar to the floating bottles you've shown an example of. 

So far I've only managed to get the modifier to play once, is there a way to make the animation cycle back and forth between it's unmodified state and the modified state within the plugin settings? 

Or is the intended method to use parallel processes to toggle conditions (such as a switch enabling the modifier) on and off?

Sorry for the late response: I was on vacation for a week.

Animated modifiers are not exposed in the plugin parameters, since I felt it was easier to define them in JavaScript. I thought I had published documentation for this, but it looks like I was mistaken… I’ll try to fix that properly when I’m able to.

Let me know whether this is enough for now: In JavaScript, you can call for example

TS_Dynamic_Characters.parameters.modifierDefinitions.push(new TS_Dynamic_Characters.ModifierDefinition({
	name: 'bob-and-sway',
	bushDepth: 25, // This (by default) also turns on bush display for tile Events.
	anchorY: 50, // To rotate around the (vertical) centre, not the bottom.

	// Note that using a custom function for any "offset" will turn off offset rounding by default!:

	/** @type {Varying<number>} */
	yOffsetVertical: function (t, { x, y }) {
		// The second argument above is a `Game_CharacterBase` instance, which (among many more) has `x` and `y` properties.
		// `this`, here, is the `ModifierDefinition` instance.
		return -3 * t * Math.sin(phase(x, y) + Graphics.frameCount / 20);
	},

	// You can also write this more concisely, but without `this`:
	/** @type {Varying<number>} */
	angle: (t, { x, y }) => 5 * t * Math.sin(phase(x, y) + Graphics.frameCount / 15),
}));

to create the bottle animation, where Varying is

/**
 * This is the type definition for modifier varying functions.
 * You can copy it into your own plugin to get type annotations.
 *
 * @template T
 * @typedef {((
 * 	this: ModifierDefinition,
 * 	t: number,
 * 	character: Game_CharacterBase,
 * ) => T) & { [CONSTANT]?: T }} Varying
 */

. This looks complicated, but basically it means is that, in the record you pass into the ModifierDefinition constructor here, you can use either a constant as value for properties where the type is annotated with {Varying<…>} ( is any other type), which is what’s available through the plugin parameters, or you can use a Function (which disables certain optimisations for that modifier, to enable continuous animation).

The first parameter t is how “eased-in” the modifier currently is. The second parameter is the Character (Event, Actor or Vehicle) the modifier is being calculated for. I use only its position above, so I immediately spread it into x and y. Note that the annotations are optional, so just

TS_Dynamic_Characters.parameters.modifierDefinitions.push(new TS_Dynamic_Characters.ModifierDefinition({
	name: 'bob-and-sway',
	bushDepth: 25,
	anchorY: 50,

	// Note that using a custom function for any "offset" will turn off offset rounding by default!:

	yOffsetVertical: function (t, { x, y }) {
		return -3 * t * Math.sin(phase(x, y) + Graphics.frameCount / 20);
	},

	angle: (t, { x, y }) => 5 * t * Math.sin(phase(x, y) + Graphics.frameCount / 15),
}));

in a plugin loaded after Dynamic Characters would have the same effect.

You can find the full list of properties that can be animated this way in ModifierDefinition‘s initialize method. (Their norm is a VaryingDefault.) Note that for tone: ColorTone and blend: BlendColor, you’d have to instantiate those types similarly and use function values as property values there.

(2 edits)

To be honest, it would have been a better idea to adjust the decodeParameters implementation so that you could write those functions directly in “Text” entry mode there in the plugin parameters.

I’ll make a note to do that when possible, will likely have it trigger on values that begin with ( or function. (That will still be precompiled only once then, so no eval overhead.)

Still no ETA for this or characters-on-windows-support, since I’m still not in good shape to code anything complicated, unfortunately.

I'm trying to understand, but much of this is going over my head.

I've tried copying your examples, but I'm not seeing anything happen in game.

What I've done is put this into a new plugin which sits below yours in the load order.

@template T 
@typedef {((
    this: ModifierDefinition,
    t: number,
    character: Game_CharacterBase,
) => T) & { [CONSTANT]?: T }} Varying
TS_Dynamic_Characters.parameters.modifierDefinitions.push(new TS_Dynamic_Characters.ModifierDefinition({
    name: 'bob-and-sway',
    bushDepth: 25, // This (by default) also turns on bush display for tile Events.
    anchorY: 50, // To rotate around the (vertical) centre, not the bottom.
    yOffsetVertical: function (t, { x, y }) {
        return -3 * t * Math.sin(phase(x, y) + Graphics.frameCount / 20);
    },
    angle: (t, { x, y }) => 5 * t * Math.sin(phase(x, y) + Graphics.frameCount / 15),
}));

I've kept the name for testing purposes and changed my character rule to look for bob-and-sway.

I'm not sure where I'm going wrong.

Thanks for all the help, and wishing you well.

(1 edit)

This part here:

@template T 
@typedef {((
    this: ModifierDefinition,
    t: number,
    character: Game_CharacterBase,
) => T) & { [CONSTANT]?: T }} Varying

is probably crashing the plugin when it loads, since it’s just a JSDoc comment (it’s used with other comments to enable type checks in the editor) but the part that makes it a comment is missing here as far as I can tell.

You can remove these lines entirely. The rest should then start working.

When I remove that part I get this error. Phase is not defined.

(TS_Dyn_WitchOrbHover is what I've put this stuff into.)


(2 edits)

I missed the first line(s) while copying, sorry. This should be fixed:

// This likely doesn't look great on moving Events!
const phase = (x, y) => (x * 147 + y * 15) % 11 / 5.5 * Math.PI;
TS_Dynamic_Characters.parameters.modifierDefinitions.push(new TS_Dynamic_Characters.ModifierDefinition({
	name: 'bob-and-sway',
	bushDepth: 25, // This (by default) also turns on bush display for tile Events.
	anchorY: 50, // To rotate around the (vertical) centre, not the bottom.

	// Note that using a custom function for any "offset" will turn off offset rounding by default!:

	yOffsetVertical: function (t, { x, y }) {
		// The second argument above is a `Game_CharacterBase` instance, which (among many more) has `x` and `y` properties.
		// `this`, here, is the `ModifierDefinition` instance.
		return -3 * t * Math.sin(phase(x, y) + Graphics.frameCount / 20);
	},

	// You can also write this more concisely, but without `this`:
	angle: (t, { x, y }) => 5 * t * Math.sin(phase(x, y) + Graphics.frameCount / 15),
}));

The phase formula is totally arbitrary, I just wrote something to make it different based on which tile the event sits on. You may want to use a formula that changes much more slowly in space (and also use { _realX: x, _realY: y } instead of { x, y } to get fractional numbers, but that can still look wrong on a looping map sometimes).

(+1)

That worked, thank you! I'll play with the formula from here to achieve the effect I'm going for.