Open sonirico opened 8 years ago
try setting time with OperationFactory::seconds
- i think it's a case of the temporal operation having a duration of 0.
unique("touch",
scaleTo(1f, seconds(.5f), Interpolation.bounceOut)
).register(e);
PS. pass interpolation as a parameter - makes tweaking it much easier.
edit: OperationFactory::seconds
simply sets the value to the smallest possible float which is greater than zero.
public static float seconds(float value) {
if (value == 0) {
int raw = floatToRawIntBits(0);
value = intBitsToFloat(raw + 1);
}
return value;
}
I have just noticed that linear_move
extended Operation base class straightaway. That is because I needed an operation which just sets the velocity for a MotionComponent once. I should have used SingleUseOperation instead.
In regard to Interpolation, I can barely use it for movements due to it works by modifying a position vector instead of velocities. Do you remember the gif in here ? xD
I can barely use it for movements
Ah, yeah, more useful for UI and the like.
I am using OperationFactory.xy(float, float)
because it is less verbose than instanciating a new vector2 everytime, but I run into problems. I have an OperationComponent like:
public class OperationComponent extends PooledComponent {
public Operation operation = null;
public boolean registered = false;
public OperationComponent () {
}
public void setOperation (Operation operation) {
this.operation = operation;
}
public void register (Entity entity) {
operation.register(entity);
}
public void register (World world, int entityId) {
operation.register(world, entityId);
}
@Override
protected void reset() {
operation = null;
registered = false;
}
}
And a the proper system:
public class CustomOperationSystem extends EntityProcessingSystem {
private ComponentMapper<OperationComponent> mapper;
public CustomOperationSystem() {
super(Aspect.all(OperationComponent.class));
}
@Override
protected void process(Entity e) {
OperationComponent oc = mapper.get(e);
if (!oc.registered) {
oc.register(e);
oc.registered = true;
}
}
}
Then in my stage builder:
...
Operation o2 = sequence(
animate(AnimationValues.STATES.WALKING),
linearMove(new Vector2(-100, 0), 2),
forever(
sequence(
animate(AnimationValues.STATES.ATTACKING),
delay(1),
shot(Weapon.ELF_ARROW, sequence( linearByVel(new Vector2(100, 0)), rotateOnce(new Vector2(100, 0))), G.GROUPS.BULLET),
animate(AnimationValues.STATES.WALKING),
linearMove(new Vector2(0, -200), 3),
animate(AnimationValues.STATES.ATTACKING),
delay(1),
shot(Weapon.ELF_ARROW, sequence( linearByVel(new Vector2(100, 0)), rotateOnce(new Vector2(100, 0))), G.GROUPS.BULLET),
animate(AnimationValues.STATES.WALKING),
linearMove(new Vector2(0, 200), 3)
)
)
);
OperationComponent oc2 = orc.edit().create(OperationComponent.class);
oc2.setOperation(o2);
...
If by any chance I replaced new Vector2
with xy
the whole behavior changes -not expected rare things. I think that if the xy method returned a new vector instance there would not be issues. Why is it static final?
Why is it static final?
To avoid garbage collection as much as possible on slower / limited platforms. Causes issues when it is passed to the same method twice.
Hmm, I don't see any operations with two or more parameters taking vectors? That's the only point where it can be problematic. are you setting the vector in the operation or overwriting the reference? The xy()
vector has to be written to the operation's own vector, if it's not already the case.
public static MoveToOperation moveTo(Vector2 destination,
float duration,
Interpolation interpolation) {
MoveToOperation op = operation(MoveToOperation.class);
configure(op, duration, interpolation);
op.dest.set(destination);
return op;
}
Vector2.set
method is always used to copy their values. I learnt about that reference issue in the hard way, long ago xD.
Hmm... I'd record the stack trace for each Vector2, something is going on somewhere.
are you calling xy
from somewhere in your factory or operations?
I think what @sonirico is saying he was keeping a reference to the vector in his custom operations.
@DaanVanYperen totally the opposite (I think XD)
CustomOperationFactory.java
:
public final class CustomOperationFactory {
private CustomOperationFactory() {
}
/**
* Sets a linear motion movement
* @param vel
* @return
*/
public static LinearMoveByVelocityOperation move (Vector2 vel) {
LinearMoveByVelocityOperation lmbv = operation(LinearMoveByVelocityOperation.class);
lmbv.vel.set(vel);
return lmbv;
}
/**
* Sets a linear motion movement specified by final destination and duration
* @param deltaSpace the distance to move
* @param duration how long it takes to reach it
* @return
*/
public static LinearMoveOperation moveBy(Vector2 deltaSpace, float duration) {
LinearMoveOperation lmo = operation(LinearMoveOperation.class);
lmo.vel.set(deltaSpace);
lmo.duration = duration;
return lmo;
}
/**
* Sets harmonic motion
* @param A total displacement
* @param nLaps period (aka T)
* @param angle initial angle (aka phi)
* @param duration
* @param vel velocity for the no harmonic axis
* @param xAxis whether perform it in the x axis
* @param yAxis whether perform it in the y axis
* @return
*/
public static SinusMoveOperation sinusMove (
float A, float nLaps, float angle, float duration, Vector2 vel, boolean xAxis, boolean yAxis
) {
SinusMoveOperation smo = operation(SinusMoveOperation.class);
smo.vel.set(vel);
smo.xAxis = xAxis;
smo.yAxis = yAxis;
smo.duration = duration;
smo.A = A;
smo.phi = angle * MathUtils.degreesToRadians;
float f = nLaps / duration; // frequency = laps per second
smo.omega = MathUtils.PI2 * f;// w = 2 * PI * frequency
return smo;
}
/**
* An alternate sinusoidal movement with no complex harmonic equations
* @param vel
* @param radius
* @param xAxis
* @param yAxis
* @param duration
* @return
*/
public static AlternateSinusMoveOperation alternateSinusMove (Vector2 vel, float radius, boolean xAxis, boolean yAxis, float duration) {
AlternateSinusMoveOperation smo = operation(AlternateSinusMoveOperation.class);
smo.radius = radius;
smo.xAxis = xAxis;
smo.yAxis = yAxis;
smo.vel.set(vel);
smo.duration = duration;
return smo;
}
/**
* Chases the target. This movement takes as long as duration is set.
* For a standard duration value, this movement will perform faster/lower
* depending on the distance between the pursuer and the target
* @param entityId the target to pursue
* @param duration how long it takes to perform the movement.
* @return
*/
public static ChaseByDurationOperation chaseByDuration (int entityId, float duration) {
ChaseByDurationOperation co = operation(ChaseByDurationOperation.class);
co.targetEntityId = entityId;
co.duration = duration;
return co;
}
/**
* Always chases the target with the given velocity
* @param entityId
* @param vel
* @return
*/
public static ChaseByVelocityOperation chaseByVelocity (int entityId, Vector2 vel) {
ChaseByVelocityOperation co = operation(ChaseByVelocityOperation.class);
co.targetEntityId = entityId;
co.vel.set(vel);
return co;
}
public static AttackOperation attack (Weapon w) {
AttackOperation ao = operation(AttackOperation.class);
ao.weapon = w;
return ao;
}
/**
* Flips the sprite of an animated component
* @param x whether flip on x axis
* @param y whether flip on y axis
* @return
*/
public static FlipOperation flip (boolean x, boolean y) {
FlipOperation fo = operation(FlipOperation.class);
fo.flipX = x;
fo.flipY = y;
return fo;
}
/**
* Makes and entity collidable with entities composed by DamageableComponents.
* @param damage How much damage it will inflict
* @return The operation to process
*/
public static MeleeAttackOperation melee (int damage) {
MeleeAttackOperation mao = operation(MeleeAttackOperation.class);
mao.damage = damage;
return mao;
}
/**
* Removes the melee state from an entity
* @return The operation to process
*/
public static EndMeleeOperation endMelee() {
EndMeleeOperation mao = operation(EndMeleeOperation.class);
return mao;
}
/**
* Sets animations for entities
* @param animation
* @return
*/
public static AnimateOperation animate (Enum animation) {
AnimateOperation ao = operation(AnimateOperation.class);
ao.animation = animation;
return ao;
}
public static ShotOperation shot (Weapon weapon) {
ShotOperation so = operation(ShotOperation.class);
so.weapon = weapon;
return so;
}
public static ShotOperation shot (Weapon weapon, Operation moveDescriptor) {
ShotOperation so = operation(ShotOperation.class);
so.weapon = weapon;
so.moveDescriptor = moveDescriptor;
return so;
}
public static ShotOperation shot (Weapon weapon, Operation moveDescriptor, String... groups) {
ShotOperation so = operation(ShotOperation.class);
so.weapon = weapon;
so.moveDescriptor = moveDescriptor;
so.groups = groups;
return so;
}
public static RotateOnceOperation rotateOnce ( Vector2 direction ) {
RotateOnceOperation roo = operation(RotateOnceOperation.class);
roo.direction.set(direction);
return roo;
}
/**
* Achieves the fancy effect of blinking.
* @param minorA Low alpha
* @param majorA High alpha
* @param delay how long it takes to start blinking
* @param interval Delta time between blinking
* @param repeatCount How many times the Entity will blink
* @return
*/
public static BlinkOperation blink (
float minorA, float majorA,
float delay, float interval, int repeatCount)
{
BlinkOperation bo = operation(BlinkOperation.class);
bo.minorAlpha = minorA;
bo.minorAlpha = majorA;
bo.delay = delay;
bo.interval = interval;
bo.repeatCount = repeatCount;
return bo;
}
}
On the other hand, in every operation composed by vectors, I always set them as:
Vector2
d vec = Vector2.Zero.cpy();
@junkdog using the "find usages" tool from intellij there were no results.
Sorry for the big block of code. Next time I think I should link to the repo. It's currently in gitlab though.
I think what @sonirico is trying to say is we should rename orion to xmas, to prepare for the holidays!
(I'm sharp! :D)
I have a piece of code like this:
RotateOperation never gets executed. But if I do this...
Then it works. Btw, it also works if
sequence
is replaced byparallel
(in both cases). Is this behavior normal or should I make a test case?