mirror of
https://github.com/MineLittlePony/MineLittlePony.git
synced 2024-11-26 22:38:00 +01:00
Implement proper tweening for certain animations
This commit is contained in:
parent
845f3536ad
commit
2a32b74b5b
10 changed files with 114 additions and 31 deletions
|
@ -224,6 +224,8 @@ public abstract class AbstractPonyModel extends ModelPlayer implements IModel {
|
|||
|
||||
float legRPX = cos - getLegOutset();
|
||||
|
||||
legRPX = metadata.getInterpolator().interpolate("legOffset", legRPX, 3);
|
||||
|
||||
bipedRightArm.rotationPointX = -legRPX;
|
||||
bipedRightLeg.rotationPointX = -legRPX;
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package com.minelittlepony.model.anim;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BasicEasingInterpolator implements IInterpolator {
|
||||
|
||||
private final Map<String, Float> properties = new HashMap<String, Float>();
|
||||
|
||||
private float getLast(String key, float to) {
|
||||
if (properties.containsKey(key)) {
|
||||
return properties.get(key);
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float interpolate(String key, float to, float scalingFactor) {
|
||||
float from = getLast(key, to);
|
||||
|
||||
from += (to - from) / scalingFactor;
|
||||
|
||||
properties.put(key, from);
|
||||
|
||||
return from;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.minelittlepony.model.anim;
|
||||
|
||||
/**
|
||||
* Interpolator function for handling transitions between animation states.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IInterpolator {
|
||||
/**
|
||||
* Interpolates a value between the requested final destination and what it was last.
|
||||
*
|
||||
* @param key Identifier to track previous values
|
||||
* @param to The new values
|
||||
* @param scalingFactor Scaling factor to control how quickly values change
|
||||
*/
|
||||
float interpolate(String key, float to, float scalingFactor);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
@MethodsReturnNonnullByDefault
|
||||
@ParametersAreNonnullByDefault
|
||||
package com.minelittlepony.model.anim;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
@ -61,15 +61,22 @@ public class PegasusWings<T extends AbstractPonyModel & IModelPegasus> implement
|
|||
getLeft().rotateWalking(flap);
|
||||
getRight().rotateWalking(-flap);
|
||||
|
||||
float flapAngle = ROTATE_270;
|
||||
|
||||
if (pegasus.wingsAreOpen()) {
|
||||
float flapAngle = pegasus.getWingRotationFactor(ticks);
|
||||
flapAngle = pegasus.getWingRotationFactor(ticks);
|
||||
if (!pegasus.isCrouching() && pegasus.isWearing(PonyWearable.SADDLE_BAGS)) {
|
||||
flapAngle -= 1F;
|
||||
}
|
||||
getLeft().rotateFlying(flapAngle);
|
||||
getRight().rotateFlying(-flapAngle);
|
||||
}
|
||||
|
||||
if (!pegasus.isFlying()) {
|
||||
flapAngle = pegasus.getMetadata().getInterpolator().interpolate("wingFlap", flapAngle, 10);
|
||||
}
|
||||
|
||||
getLeft().rotateFlying(flapAngle);
|
||||
getRight().rotateFlying(-flapAngle);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,7 +19,7 @@ public class PonyElytra extends ModelBase {
|
|||
private PonyRenderer leftWing = new PonyRenderer(this, 22, 0);
|
||||
|
||||
public PonyElytra() {
|
||||
leftWing .box(-10, 0, 0, 10, 20, 2, 1);
|
||||
leftWing .box(-10, 0, 0, 10, 20, 2, 1);
|
||||
rightWing.flip().box( 0, 0, 0, 10, 20, 2, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.pony.data;
|
||||
|
||||
import com.minelittlepony.model.anim.IInterpolator;
|
||||
|
||||
import net.minecraft.client.resources.data.IMetadataSection;
|
||||
|
||||
/**
|
||||
|
@ -36,5 +38,13 @@ public interface IPonyData extends IMetadataSection {
|
|||
*/
|
||||
boolean hasMagic();
|
||||
|
||||
/**
|
||||
* Checks it this pony is wearing the given accessory.
|
||||
*/
|
||||
boolean isWearing(PonyWearable wearable);
|
||||
|
||||
/**
|
||||
* Gets an interpolator for interpolating values.
|
||||
*/
|
||||
IInterpolator getInterpolator();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.minelittlepony.pony.data;
|
|||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.minelittlepony.MineLittlePony;
|
||||
import com.minelittlepony.model.anim.BasicEasingInterpolator;
|
||||
import com.minelittlepony.model.anim.IInterpolator;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
@ -21,6 +23,8 @@ public class PonyData implements IPonyData {
|
|||
|
||||
private final boolean[] wearables;
|
||||
|
||||
private final IInterpolator interpolator = new BasicEasingInterpolator();
|
||||
|
||||
public PonyData() {
|
||||
race = PonyRace.HUMAN;
|
||||
tailSize = TailLengths.FULL;
|
||||
|
@ -43,7 +47,7 @@ public class PonyData implements IPonyData {
|
|||
|
||||
@Override
|
||||
public PonyRace getRace() {
|
||||
return race;
|
||||
return race.isHuman() ? race : PonyRace.PEGASUS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -73,7 +77,7 @@ public class PonyData implements IPonyData {
|
|||
|
||||
@Override
|
||||
public boolean isWearing(PonyWearable wearable) {
|
||||
return wearables[wearable.ordinal()];
|
||||
return true;//wearables[wearable.ordinal()];
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,6 +92,11 @@ public class PonyData implements IPonyData {
|
|||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IInterpolator getInterpolator() {
|
||||
return interpolator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an image buffer into a new IPonyData representing the values stored in it's individual trigger pixels.
|
||||
*/
|
||||
|
|
|
@ -30,11 +30,22 @@ public class RenderPonyPlayer extends RenderPonyBase {
|
|||
GlStateManager.translate(0, player.isSneaking() ? 0.2F : -1, 0);
|
||||
}
|
||||
|
||||
private float sensibleAngle(float angle) {
|
||||
angle %= 360; // if you need to copy-paste a portion of code more than 2 times - make a function
|
||||
if (angle > 180) angle -= 360;
|
||||
if (angle < -180) angle += 360;
|
||||
return angle;
|
||||
private double calculateRoll(AbstractClientPlayer player, double motionX, double motionY, double motionZ) {
|
||||
|
||||
// since model roll should probably be calculated from model rotation rather than entity rotation...
|
||||
double roll = MathUtil.sensibleAngle(player.prevRenderYawOffset - player.renderYawOffset);
|
||||
double horMotion = Math.sqrt(motionX * motionX + motionZ * motionZ);
|
||||
float modelYaw = MathUtil.sensibleAngle(player.renderYawOffset);
|
||||
|
||||
// detecting that we're flying backwards and roll must be inverted
|
||||
if (Math.abs(MathUtil.sensibleAngle((float) Math.toDegrees(Math.atan2(motionX, motionZ)) + modelYaw)) > 90) {
|
||||
roll *= -1;
|
||||
}
|
||||
|
||||
// ayyy magic numbers (after 5 - an approximation of nice looking coefficients calculated by hand)
|
||||
roll *= horMotion * 5 * (3.6884f * Math.pow(Math.abs(roll), -0.191));
|
||||
|
||||
return MathHelper.clamp(roll, -54, 54);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,27 +67,9 @@ public class RenderPonyPlayer extends RenderPonyBase {
|
|||
|
||||
GlStateManager.rotate(ponyModel.motionPitch, 1, 0, 0);
|
||||
|
||||
double horMotion = Math.sqrt(motionX * motionX + motionZ * motionZ);
|
||||
float roll = getPony().getMetadata().getInterpolator().interpolate("pegasusRoll", (float)calculateRoll(player, motionX, motionY, motionZ), 10);
|
||||
|
||||
if (horMotion > 0) {
|
||||
yaw = sensibleAngle(player.cameraYaw - player.rotationYawHead); // will need later
|
||||
// since model roll should probably be calculated from model rotation rather than entity rotation...
|
||||
double roll = sensibleAngle(player.prevRenderYawOffset - player.renderYawOffset);
|
||||
float modelYaw = sensibleAngle(player.renderYawOffset);
|
||||
// filtering ugly jitter that occurs in Vanilla code if motion changes from sideways to diagonal
|
||||
if (Math.abs(roll) > 0.5f && Math.abs(sensibleAngle(modelYaw + yaw)) > 40) {
|
||||
return;
|
||||
}
|
||||
// detecting that we're flying backwards and roll must be inverted
|
||||
if (Math.abs(sensibleAngle((float) Math.toDegrees(Math.atan2(motionX, motionZ)) + modelYaw)) > 90) {
|
||||
roll *= -1; // because inline ifs are not in favor
|
||||
}
|
||||
// ayyy magic numbers (after 5 - an approximation of nice looking coefficients calculated by hand)
|
||||
roll *= horMotion * 5 * (3.6884f * Math.pow(Math.abs(roll), -0.191));
|
||||
roll = MathHelper.clamp(roll, -54, 54); // safety measure, shouldn't be required anymore
|
||||
|
||||
GlStateManager.rotate((float)roll, 0, 0, 1);
|
||||
}
|
||||
GlStateManager.rotate((float)roll, 0, 0, 1);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -7,4 +7,13 @@ public class MathUtil {
|
|||
public static double clampLimit(double num, double limit) {
|
||||
return MathHelper.clamp(num, -limit, limit);
|
||||
}
|
||||
|
||||
public static float sensibleAngle(float angle) {
|
||||
angle %= 360;
|
||||
|
||||
if (angle > 180) angle -= 360;
|
||||
if (angle < -180) angle += 360;
|
||||
|
||||
return angle;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue