# LibGDX particle emitter rotation

I have a libGDX game, in which I'd like to make some ice breath like effect using particles. So far we made a cone like effect. I can obtain and render it on the screen with this.

ParticleEffectPool.PooledEffect effect = breathPool.obtain();
effect.setPosition(x,y);


But I don't really see any way to rotate the entire particle system in a given direction. Is there any way to achieve this?

• No it is not impossible. Read -> here – Fish Apr 19 '15 at 17:58
• is it the same for the 2d particle system? – Rothens Apr 19 '15 at 18:01

You could try picking out the angle property of your emitter (or emitters if you have many) and manually adjust the values to center around some angle.

ParticleEffect effect = /* your effect */
ParticleEmitter emitter = effect.findEmitter("some_name"); // find the emitter you want to     rotate here
float targetAngle = /* your target angle */

ScaledNumericValue angle = emitter.getAngle();

/* find angle property and adjust that by letting the min, max of low and high span their current size around your angle */

float angleHighMin = angle.getHighMin();
float angleHighMax = angle.getHighMax();
float spanHigh = angleHighMax - angleHighMin;
angle.setHigh(angle - spanHigh / 2.0f, angle + spanHigh / 2.0f);

float angleLowMin = angle.getLowhMin();
float angleLowMax = angle.getLowMax();
float spanLow = angleLowMax - angleLowMin;
angle.setLow(angle - spanLow / 2.0f, angle + spanLow / 2.0f);


Note that the above would just adjust what the high and low are, and you'll most likely need to do something about it wrapping around.

• This worked! You mean to use targetAngle in setHigh() and setLow(), but forgot...and you there's a typo in getLowMin(). Works fine otherwise. – Max Apr 12 '16 at 5:03
• Does not work if your particles do not have the same width than height. – Winter Feb 9 '18 at 21:10

Here's my own solution for 90° rotations:

/**
* Created on 2018-02-09.
*
* @author Alexander Winter
*/
public class RotatableParticleEffect extends ParticleEffect {
public RotatableParticleEffect() {}

public RotatableParticleEffect(ParticleEffect effect) {
super(effect);
}

public void rotateBy(int turnQuarter) {
while(turnQuarter < 0)
turnQuarter += 4;

turnQuarter %= 4;

for(ParticleEmitter emitter : getEmitters()) {
ScaledNumericValue angle = emitter.getAngle();

angle.setHighMax(angle.getHighMax() + turnQuarter * -90f);
angle.setHighMin(angle.getHighMin() + turnQuarter * -90f);

angle.setLowMax(angle.getLowMax() + turnQuarter * -90f);
angle.setLowMin(angle.getLowMin() + turnQuarter * -90f);

ScaledNumericValue rot = emitter.getRotation();

rot.setHighMax(rot.getHighMax() + turnQuarter * -90f);
rot.setHighMin(rot.getHighMin() + turnQuarter * -90f);

rot.setLowMax(rot.getLowMax() + turnQuarter * -90f);
rot.setLowMin(rot.getLowMin() + turnQuarter * -90f);

for(int i = 0; i < turnQuarter; i++) {
swapFields(emitter.getXOffsetValue(), emitter.getYOffsetValue());

emitter.getYOffsetValue().setLowMin(-emitter.getYOffsetValue().getLowMin());
emitter.getYOffsetValue().setLowMax(-emitter.getYOffsetValue().getLowMax());
}
}
}

private static void swapFields(Object o1, Object o2) {
if(o1 == null || o2 == null)
throw new IllegalArgumentException("Objects must not be null");

if(!o1.getClass().equals(o2.getClass()))
throw new IllegalArgumentException("Objects are not the same type");

Class<?> type = o1.getClass();

while(type != null) {
for(Field field : type.getDeclaredFields()) {
if(!field.isAccessible())
field.setAccessible(true);

try {
Object tmp = field.get(o1);
field.set(o1, field.get(o2));
field.set(o2, tmp);
} catch(IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}

type = type.getSuperclass();
}
}
}


With this solution, you can't rotate with any angle. If you'd need to, you will need to adjust the X and Y offsets with a rotation. offsetY = originalOffsetY * sin(angle) and same for X with cos(). I didn't implement the full solution for any angle because I didn't need it. However, I can confirm this simpler solution works for me.

Add the particle effect to a group with transformation enabled (default).

• This answer could benefit from additional information. How does this solve the problem and are there any more steps to accomplish the goal? – MichaelHouse Jul 28 '15 at 13:25