2022-12-13 09:20:36 +01:00
|
|
|
enum ANIM_END_ACTION {
|
|
|
|
loop,
|
|
|
|
pingpong,
|
|
|
|
destroy,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum PARTICLE_BLEND_MODE {
|
|
|
|
normal,
|
2023-02-28 09:43:01 +01:00
|
|
|
alpha,
|
2022-12-13 09:20:36 +01:00
|
|
|
additive
|
|
|
|
}
|
|
|
|
|
2022-12-16 09:18:09 +01:00
|
|
|
function __part(_node) constructor {
|
2023-09-26 14:35:25 +02:00
|
|
|
seed = irandom(99999);
|
|
|
|
node = _node;
|
|
|
|
active = false;
|
2023-11-13 05:38:37 +01:00
|
|
|
|
|
|
|
surf = noone;
|
|
|
|
arr_type = 0;
|
|
|
|
|
2023-09-26 14:35:25 +02:00
|
|
|
prevx = 0;
|
|
|
|
prevy = 0;
|
|
|
|
x = 0;
|
|
|
|
y = 0;
|
2023-03-28 06:58:28 +02:00
|
|
|
speedx = 0;
|
|
|
|
speedy = 0;
|
|
|
|
turning = 0;
|
2023-09-26 14:35:25 +02:00
|
|
|
turnSpd = 0;
|
2023-03-28 06:58:28 +02:00
|
|
|
|
2023-10-28 15:28:47 +02:00
|
|
|
x_history = [];
|
|
|
|
y_history = [];
|
|
|
|
|
2023-10-02 04:53:30 +02:00
|
|
|
drawx = 0;
|
|
|
|
drawy = 0;
|
|
|
|
drawrot = 0;
|
|
|
|
drawsx = 0;
|
|
|
|
drawsy = 0;
|
|
|
|
|
2023-10-01 08:37:54 +02:00
|
|
|
accel = 0;
|
|
|
|
spVec = [ 0, 0 ];
|
|
|
|
|
2023-08-16 20:16:31 +02:00
|
|
|
grav = 0;
|
|
|
|
gravDir = -90;
|
|
|
|
gravX = 0;
|
|
|
|
gravY = 0;
|
2022-12-13 09:20:36 +01:00
|
|
|
|
|
|
|
scx = 1;
|
|
|
|
scy = 1;
|
2023-10-09 07:36:20 +02:00
|
|
|
sc_sx = 1;
|
|
|
|
sc_sy = 1;
|
2023-01-17 08:11:55 +01:00
|
|
|
sct = CURVE_DEF_11;
|
2022-12-13 09:20:36 +01:00
|
|
|
|
|
|
|
rot = 0;
|
|
|
|
follow = false;
|
|
|
|
rot_s = 0;
|
|
|
|
|
|
|
|
col = -1;
|
2023-01-17 08:11:55 +01:00
|
|
|
blend = c_white;
|
2022-12-13 09:20:36 +01:00
|
|
|
alp = 1;
|
|
|
|
alp_draw = alp;
|
|
|
|
alp_fade = 0;
|
|
|
|
|
|
|
|
life = 0;
|
|
|
|
life_total = 0;
|
2023-10-28 15:28:47 +02:00
|
|
|
life_incr = 0;
|
2022-12-16 09:18:09 +01:00
|
|
|
step_int = 0;
|
2022-12-13 09:20:36 +01:00
|
|
|
|
|
|
|
anim_speed = 1;
|
|
|
|
anim_end = ANIM_END_ACTION.loop;
|
|
|
|
|
2023-07-25 20:12:40 +02:00
|
|
|
ground = false;
|
|
|
|
ground_y = 0;
|
|
|
|
ground_bounce = 0;
|
2023-09-29 04:22:41 +02:00
|
|
|
ground_friction = 1;
|
2023-07-25 20:12:40 +02:00
|
|
|
|
2023-10-29 06:29:10 +01:00
|
|
|
trailLife = 0;
|
|
|
|
trailActive = false;
|
|
|
|
|
2023-10-09 16:07:33 +02:00
|
|
|
frame = 0;
|
|
|
|
|
2024-01-10 08:37:15 +01:00
|
|
|
path = noone;
|
|
|
|
pathIndex = 0;
|
|
|
|
pathPos = new __vec2();
|
|
|
|
pathDiv = noone;
|
|
|
|
|
2023-10-06 11:51:11 +02:00
|
|
|
static reset = function() { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-10-06 11:51:11 +02:00
|
|
|
|
|
|
|
surf = noone;
|
|
|
|
|
|
|
|
prevx = undefined;
|
|
|
|
prevy = undefined;
|
|
|
|
} #endregion
|
|
|
|
|
2023-10-02 04:53:30 +02:00
|
|
|
static create = function(_surf, _x, _y, _life) { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2022-12-13 09:20:36 +01:00
|
|
|
active = true;
|
|
|
|
surf = _surf;
|
2023-03-28 06:58:28 +02:00
|
|
|
x = _x;
|
|
|
|
y = _y;
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2023-10-29 06:29:10 +01:00
|
|
|
drawx = x;
|
|
|
|
drawy = y;
|
|
|
|
|
2023-10-28 15:28:47 +02:00
|
|
|
life_incr = 0;
|
2022-12-13 09:20:36 +01:00
|
|
|
life = _life;
|
|
|
|
life_total = life;
|
2023-10-09 16:07:33 +02:00
|
|
|
if(node.onPartCreate != noone) node.onPartCreate(self);
|
2023-10-28 15:28:47 +02:00
|
|
|
|
2023-10-29 06:29:10 +01:00
|
|
|
trailLife = 0;
|
|
|
|
x_history = array_create(life);
|
|
|
|
y_history = array_create(life);
|
2023-10-02 04:53:30 +02:00
|
|
|
} #endregion
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2023-10-02 04:53:30 +02:00
|
|
|
static setPhysic = function(_sx, _sy, _ac, _g, _gDir, _turn, _turnSpd) { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2023-08-16 20:16:31 +02:00
|
|
|
speedx = _sx;
|
|
|
|
speedy = _sy;
|
|
|
|
accel = _ac;
|
|
|
|
grav = _g;
|
|
|
|
gravDir = _gDir;
|
|
|
|
gravX = lengthdir_x(grav, gravDir);
|
|
|
|
gravY = lengthdir_y(grav, gravDir);
|
2023-03-28 06:58:28 +02:00
|
|
|
|
|
|
|
turning = _turn;
|
|
|
|
turnSpd = _turnSpd;
|
|
|
|
|
2023-07-25 20:12:40 +02:00
|
|
|
spVec[0] = point_distance(0, 0, speedx, speedy);
|
|
|
|
spVec[1] = point_direction(0, 0, speedx, speedy);
|
2023-10-02 04:53:30 +02:00
|
|
|
} #endregion
|
|
|
|
|
|
|
|
static setWiggle = function(wiggle_maps) { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2023-10-02 04:53:30 +02:00
|
|
|
wig_psx = wiggle_maps.wig_psx;
|
|
|
|
wig_psy = wiggle_maps.wig_psy;
|
|
|
|
wig_rot = wiggle_maps.wig_rot;
|
|
|
|
wig_scx = wiggle_maps.wig_scx;
|
|
|
|
wig_scy = wiggle_maps.wig_scy;
|
|
|
|
wig_dir = wiggle_maps.wig_dir;
|
|
|
|
} #endregion
|
2023-07-25 20:12:40 +02:00
|
|
|
|
2023-10-02 04:53:30 +02:00
|
|
|
static setGround = function(_ground, _ground_offset, _ground_bounce, _ground_frict) { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2023-07-25 20:12:40 +02:00
|
|
|
ground = _ground;
|
|
|
|
ground_y = y + _ground_offset;
|
|
|
|
ground_bounce = _ground_bounce;
|
2023-09-29 04:22:41 +02:00
|
|
|
ground_friction = clamp(1 - _ground_frict, 0, 1);
|
2023-10-02 04:53:30 +02:00
|
|
|
} #endregion
|
2023-02-23 07:02:19 +01:00
|
|
|
|
2023-10-02 04:53:30 +02:00
|
|
|
static setTransform = function(_scx, _scy, _sct, _rot, _rots, _follow) { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2023-01-17 08:11:55 +01:00
|
|
|
sc_sx = _scx;
|
|
|
|
sc_sy = _scy;
|
|
|
|
sct = _sct;
|
|
|
|
|
2022-12-13 09:20:36 +01:00
|
|
|
rot = _rot;
|
|
|
|
rot_s = _rots;
|
|
|
|
follow = _follow;
|
2023-10-02 04:53:30 +02:00
|
|
|
} #endregion
|
2023-02-23 07:02:19 +01:00
|
|
|
|
2023-10-02 04:53:30 +02:00
|
|
|
static setDraw = function(_col, _blend, _alp, _fade) { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2022-12-13 09:20:36 +01:00
|
|
|
col = _col;
|
2023-01-17 08:11:55 +01:00
|
|
|
blend = _blend;
|
2022-12-13 09:20:36 +01:00
|
|
|
alp = _alp;
|
|
|
|
alp_draw = _alp;
|
|
|
|
alp_fade = _fade;
|
2023-10-02 04:53:30 +02:00
|
|
|
} #endregion
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2024-01-10 08:37:15 +01:00
|
|
|
static setPath = function(_path, _pathDiv) { #region
|
|
|
|
INLINE
|
|
|
|
|
|
|
|
path = _path;
|
|
|
|
pathDiv = _pathDiv;
|
|
|
|
} #endregion
|
|
|
|
|
2023-10-09 16:07:33 +02:00
|
|
|
static kill = function(callDestroy = true) { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2022-12-16 09:18:09 +01:00
|
|
|
active = false;
|
2023-10-09 16:07:33 +02:00
|
|
|
if(callDestroy && node.onPartDestroy != noone)
|
|
|
|
node.onPartDestroy(self);
|
2023-10-02 04:53:30 +02:00
|
|
|
} #endregion
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2023-10-09 16:07:33 +02:00
|
|
|
static step = function(frame = 0) { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-10-30 04:18:18 +01:00
|
|
|
//if(life_total > 0) print($"Step {seed}: {trailLife}");
|
2023-10-29 06:29:10 +01:00
|
|
|
trailLife++;
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2022-12-13 09:20:36 +01:00
|
|
|
if(!active) return;
|
2023-03-28 06:58:28 +02:00
|
|
|
x += speedx;
|
2023-10-09 16:07:33 +02:00
|
|
|
self.frame = frame;
|
2023-07-25 20:12:40 +02:00
|
|
|
|
2023-09-11 16:08:58 +02:00
|
|
|
random_set_seed(seed + life);
|
|
|
|
|
2023-07-25 20:12:40 +02:00
|
|
|
if(ground && y + speedy > ground_y) {
|
|
|
|
y = ground_y;
|
|
|
|
speedy = -speedy * ground_bounce;
|
2023-09-29 04:22:41 +02:00
|
|
|
|
|
|
|
if(abs(speedy) < 0.1)
|
|
|
|
speedx *= ground_friction;
|
2023-07-25 20:12:40 +02:00
|
|
|
} else
|
|
|
|
y += speedy;
|
2023-03-28 06:58:28 +02:00
|
|
|
|
|
|
|
var dirr = point_direction(0, 0, speedx, speedy);
|
|
|
|
var diss = point_distance(0, 0, speedx, speedy);
|
2023-08-16 20:16:31 +02:00
|
|
|
diss = max(0, diss + accel);
|
2023-10-02 04:53:30 +02:00
|
|
|
|
2023-03-28 06:58:28 +02:00
|
|
|
if(speedx != 0 || speedy != 0) {
|
2023-10-02 04:53:30 +02:00
|
|
|
dirr += wig_dir.get(seed + life);
|
2023-03-28 06:58:28 +02:00
|
|
|
|
|
|
|
if(turning != 0) {
|
2023-10-30 04:18:18 +01:00
|
|
|
var trn = turning;
|
|
|
|
|
|
|
|
if(turnSpd > 0) trn = turning * diss * turnSpd;
|
|
|
|
else if(turnSpd < 0) trn = turning / diss * turnSpd;
|
|
|
|
|
2023-03-28 06:58:28 +02:00
|
|
|
dirr += trn
|
|
|
|
}
|
2022-12-13 09:20:36 +01:00
|
|
|
}
|
|
|
|
|
2023-08-16 20:16:31 +02:00
|
|
|
speedx = lengthdir_x(diss, dirr) + gravX;
|
|
|
|
speedy = lengthdir_y(diss, dirr) + gravY;
|
2023-03-28 06:58:28 +02:00
|
|
|
|
|
|
|
if(follow) rot = spVec[1];
|
|
|
|
else rot += rot_s;
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2023-10-09 16:07:33 +02:00
|
|
|
if(node.onPartStep != noone && step_int > 0 && safe_mod(life, step_int) == 0)
|
2022-12-16 09:18:09 +01:00
|
|
|
node.onPartStep(self);
|
2023-10-28 15:28:47 +02:00
|
|
|
|
2022-12-13 09:20:36 +01:00
|
|
|
if(life-- < 0) kill();
|
2023-03-28 06:58:28 +02:00
|
|
|
|
2023-07-25 20:12:40 +02:00
|
|
|
if(prevx != undefined) {
|
|
|
|
spVec[0] = point_distance(prevx, prevy, x, y);
|
|
|
|
spVec[1] = point_direction(prevx, prevy, x, y);
|
|
|
|
}
|
2023-03-28 06:58:28 +02:00
|
|
|
|
2023-10-29 06:29:10 +01:00
|
|
|
x_history[life_incr] = drawx;
|
|
|
|
y_history[life_incr] = drawy;
|
|
|
|
life_incr++;
|
|
|
|
|
2023-03-28 06:58:28 +02:00
|
|
|
prevx = x;
|
|
|
|
prevy = y;
|
2023-10-02 04:53:30 +02:00
|
|
|
|
|
|
|
drawx = x;
|
|
|
|
drawy = y;
|
|
|
|
drawrot = rot;
|
|
|
|
drawsx = sc_sx;
|
|
|
|
drawsy = sc_sy;
|
|
|
|
|
|
|
|
drawx += wig_psx.get(seed + life);
|
|
|
|
drawy += wig_psy.get(seed + life);
|
|
|
|
drawrot += wig_rot.get(seed + life);
|
|
|
|
drawsx += wig_scy.get(seed + life);
|
|
|
|
drawsy += wig_scy.get(seed + life);
|
|
|
|
} #endregion
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2024-01-22 03:55:19 +01:00
|
|
|
static draw = function(exact, surf_w, surf_h) { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2022-12-13 09:20:36 +01:00
|
|
|
var ss = surf;
|
2023-10-06 11:51:11 +02:00
|
|
|
|
2024-01-22 03:55:19 +01:00
|
|
|
var lifeRat = 1 - life / life_total;
|
|
|
|
var scCurve = sct == noone? 1 : sct.get(lifeRat);
|
|
|
|
scx = drawsx * scCurve;
|
|
|
|
scy = drawsy * scCurve;
|
|
|
|
|
2023-11-13 05:38:37 +01:00
|
|
|
if(arr_type == 2 && surf != noone && is_array(surf)) {
|
2022-12-13 09:20:36 +01:00
|
|
|
var ind = abs(round((life_total - life) * anim_speed));
|
|
|
|
var len = array_length(surf);
|
|
|
|
|
|
|
|
switch(anim_end) {
|
|
|
|
case ANIM_END_ACTION.loop:
|
|
|
|
ss = surf[safe_mod(ind, len)];
|
|
|
|
break;
|
|
|
|
case ANIM_END_ACTION.pingpong:
|
|
|
|
var ping = safe_mod(ind, (len - 1) * 2 + 1);
|
|
|
|
ss = surf[ping >= len? (len - 1) * 2 - ping : ping];
|
|
|
|
break;
|
|
|
|
case ANIM_END_ACTION.destroy:
|
2023-10-09 16:07:33 +02:00
|
|
|
if(ind >= len) {
|
|
|
|
kill();
|
|
|
|
return;
|
2024-01-22 03:55:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ss = surf[ind];
|
2022-12-13 09:20:36 +01:00
|
|
|
break;
|
|
|
|
}
|
2024-01-22 03:55:19 +01:00
|
|
|
} else if(arr_type == 3) {
|
|
|
|
var _sca = round(min(scx, scy));
|
|
|
|
ss = array_safe_get(surf, clamp(_sca, 0, array_length(surf) - 1));
|
|
|
|
}
|
2023-09-26 14:35:25 +02:00
|
|
|
|
2023-10-08 15:12:20 +02:00
|
|
|
var surface = is_instanceof(ss, SurfaceAtlas)? ss.getSurface() : node.surface_cache[$ ss];
|
2024-01-14 12:20:23 +01:00
|
|
|
var _useS = is_surface(surface);
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2024-01-22 03:55:19 +01:00
|
|
|
if(arr_type == 3) {
|
|
|
|
scx = 1;
|
|
|
|
scy = 1;
|
|
|
|
}
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2022-12-13 09:20:36 +01:00
|
|
|
var _xx, _yy;
|
2024-01-14 12:20:23 +01:00
|
|
|
var s_w = (_useS? surface_get_width(surface) : 1) * scx;
|
|
|
|
var s_h = (_useS? surface_get_height(surface) : 1) * scy;
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2023-10-06 11:51:11 +02:00
|
|
|
var _pp = point_rotate(-s_w / 2, -s_h / 2, 0, 0, rot);
|
|
|
|
_xx = drawx + _pp[0];
|
|
|
|
_yy = drawy + _pp[1];
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2024-01-10 08:37:15 +01:00
|
|
|
if(path != noone) {
|
|
|
|
var _div = pathDiv.get(lifeRat);
|
|
|
|
|
2024-01-16 14:08:57 +01:00
|
|
|
pathPos = path.getPointRatio(clamp(lifeRat, 0, 0.99), pathIndex, pathPos);
|
2024-01-10 08:37:15 +01:00
|
|
|
_xx = _xx * _div + pathPos.x;
|
|
|
|
_yy = _yy * _div + pathPos.y;
|
|
|
|
}
|
|
|
|
|
2022-12-13 09:20:36 +01:00
|
|
|
if(exact) {
|
|
|
|
_xx = round(_xx);
|
|
|
|
_yy = round(_yy);
|
|
|
|
}
|
|
|
|
|
2023-01-17 08:11:55 +01:00
|
|
|
var x0 = _xx - s_w * 1.5;
|
|
|
|
var y0 = _yy - s_h * 1.5;
|
|
|
|
var x1 = _xx + s_w * 1.5;
|
|
|
|
var y1 = _yy + s_h * 1.5;
|
|
|
|
|
2024-01-14 12:20:23 +01:00
|
|
|
if(_useS && (x0 > surf_w || y0 > surf_h || x1 < 0 || y1 < 0))
|
2023-11-13 05:38:37 +01:00
|
|
|
return;
|
2023-01-17 08:11:55 +01:00
|
|
|
|
2023-03-02 07:59:14 +01:00
|
|
|
var cc = (col == -1)? c_white : col.eval(lifeRat);
|
2023-02-23 07:02:19 +01:00
|
|
|
if(blend != c_white) cc = colorMultiply(blend, cc);
|
2024-01-09 03:39:40 +01:00
|
|
|
alp_draw = alp * (alp_fade == noone? 1 : alp_fade.get(lifeRat)) * _color_get_alpha(cc);
|
2023-04-03 11:55:45 +02:00
|
|
|
|
2024-01-14 12:20:23 +01:00
|
|
|
if(_useS) draw_surface_ext(surface, _xx, _yy, scx, scy, drawrot, cc, alp_draw);
|
|
|
|
else {
|
2024-01-15 13:53:46 +01:00
|
|
|
var ss = round(min(scx, scy));
|
2024-01-14 12:20:23 +01:00
|
|
|
if(round(ss) == 0) return;
|
|
|
|
|
|
|
|
var _s = shader_current();
|
|
|
|
shader_reset();
|
|
|
|
|
|
|
|
draw_set_color(cc);
|
|
|
|
draw_set_alpha(alp_draw);
|
|
|
|
|
2024-01-22 03:55:19 +01:00
|
|
|
dynaSurf_circle_fill(_xx, _yy, exact? round(ss) : ss);
|
2024-01-14 12:20:23 +01:00
|
|
|
|
|
|
|
draw_set_alpha(1);
|
|
|
|
|
|
|
|
shader_set(_s);
|
|
|
|
}
|
2023-10-02 04:53:30 +02:00
|
|
|
} #endregion
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2023-10-02 04:53:30 +02:00
|
|
|
static getPivot = function() { #region
|
2023-11-08 08:38:04 +01:00
|
|
|
INLINE
|
2022-12-13 09:20:36 +01:00
|
|
|
|
2023-10-06 11:51:11 +02:00
|
|
|
return [x, y];
|
2023-10-02 04:53:30 +02:00
|
|
|
} #endregion
|
2023-11-13 07:11:52 +01:00
|
|
|
|
|
|
|
static clone = function() { #region
|
|
|
|
var _p = new __part(node);
|
|
|
|
struct_override(_p, self);
|
|
|
|
return _p;
|
|
|
|
} #endregion
|
2022-12-13 09:20:36 +01:00
|
|
|
}
|
2023-03-28 06:58:28 +02:00
|
|
|
|
|
|
|
#region helper
|
|
|
|
#macro UPDATE_PART_FORWARD static updateParticleForward = function() { \
|
|
|
|
var pt = outputs[| 0]; \
|
2023-12-19 14:30:34 +01:00
|
|
|
for( var i = 0; i < array_length(pt.value_to); i++ ) { \
|
|
|
|
var _n = pt.value_to[i]; \
|
2023-03-28 06:58:28 +02:00
|
|
|
if(_n.value_from != pt) continue; \
|
|
|
|
\
|
|
|
|
if(variable_struct_exists(_n.node, "updateParticleForward")) \
|
|
|
|
_n.node.updateParticleForward(); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
#endregion
|