FANDOM


2013-06-10 17.57.40

ModelTest in the middle of an animation

The most important and probably the most complicated step in this tutorial is animating the model itself. To animate the model, you must follow a rather different syntax created to make animating easier.

Getting Started

To start animating, we need to take a look at the animate() method in our ModelTest.

public void animate(IAnimatedEntity entity, float f, float f1, float f2, float f3, float f4, float f5) {
	animator.update(entity);
	setAngles();
}

Currently, we have only two lines of code. However, for animating, we have to call more methods inside. To begin, we first will create the animation for when animID == 1. If you remember correctly, animID = 1 is the animation we created for the AIHeadBang. To begin animating, we put Animator's setAnim(int) method into the code after setAngles() to specify that we are starting to animate the first animation. Simply put:

animator.setAnim(1);

Implementing Phases

Next, we begin the first phase of the animation. In Minecraft animating, animations are separated into many phases. Each phase is a change in rotation and possible position. A phase does not represent a certain rotation and position, but instead a change in rotation and position. This is done over a period of time. Thus, to create a phase, we use the animator's methods startPhase(int) and endPhase(). The integer parameter inside startPhase(int) represents the duration of the phase. Here's what our code so far looks like:

//start animating animation 1
animator.setAnim(1);
//start phase with duration 10 (0.5 seconds)
animator.startPhase(10);

//end the phase
animator.endPhase();

This will create an animation with one phase that lasts for 10 ticks. However, still nothing rotates because we haven't specified anything to change yet. We can do so by calling animator's rotate() method:

animator.setAnim(1);
animator.startPhase(10);
	animator.rotate(head, -PI / 6F, 0F, 0F);
	animator.rotate(body, -PI / 6F, 0F, 0F);
animator.endPhase();

The rotate method has four parameters:

  • ModelRenderer: the box being rotated
  • float: the rotation X to be rotated by
  • float: the rotation Y to be rotated by
  • float: the rotation Z to be rotated by

In our example here, we've used -PI / 6F, which is equivalent to -30 degrees (-PI / 6F is in radians). This is an example of a complete phase in an animation. This code will make the model lift its head and body upwards. At the end of this phase, the rotations are set, and will continue from this point for future phases. So we can start our next phase, which will make the head and body slam downwards.

animator.setAnim(1);
animator.startPhase(10);
	animator.rotate(head, -PI / 6F, 0F, 0F);
	animator.rotate(body, -PI / 6F, 0F, 0F);
animator.endPhase();
animator.startPhase(4);
	animator.rotate(body, PI / 2F, 0F, 0F);
	animator.move(body, 0F, -2F, 0F);
animator.endPhase();

We define the second phase right after the first phase. The animator will figure out which phase to run by itself, and it will play chronologically. Again, we call Animator's rotate() method, rotating the body to PI / 2F, which is equivalent to 90 degrees forward. Therefore, the body will move from its previous rotation (-PI / 6F) to its target location (PI / 2F) in the given amount of time. Since we don't specify any rotation for the head, the head rotation moves from its previous rotation (-PI / 6F) back to 0.

Here, we also make use of the animator's move() method, which works similar to the rotate() method. The parameters are similar:

  • ModelRenderer: the box being moved
  • float: the x offset to be moved by
  • float: the y offset to be moved by
  • float: the z offset to be moved by

If you know your modeling well, you will know that when y = -2F, the box will move upwards by two units, Unfortunately, movement is a bit more complicated than rotating. For rotating, our typical resetting point is 0F, however for position, our resetting points depend on how the ModelRenderer itself is defined through its setRotationPoint() method. So in order to make sure this works, we have to manually reset the rotation points that are changed in animations beforehand in any place such as the setAngles() method (even though it's not really an angle). Since we are only moving the body's y value, we only need to reset the y value:

public void setAngles() {
	//reset the rotation point each render tick
	body.rotationPointY = 24F;
}

After that, we are finished with our second phase!

Special Phases

Currently, our animation 1 makes the model raise its body/head, and then slam it down. The last thing we need is for the model to lift its body back up, but before that, we can add a delay to the time the model's body hits the ground. We do this because if it automatically lifts its head right after slamming it, the animation might look funny. Luckily, the animator has some special methods that you can use when we want the model to keep its head on the ground. Animator's setStationaryPhase(int) keeps the rotations frozen, or stationary, for the given duration, and then continues with the animation. The setStationaryPhase() method calls startPhase() and endPhase() inside itself, so you don't need to call it again. Instead, just write like this:

animator.setAnim(1);
animator.startPhase(10);
	animator.rotate(head, -PI / 6F, 0F, 0F);
	animator.rotate(body, -PI / 6F, 0F, 0F);
animator.endPhase();
animator.startPhase(4);
	animator.rotate(body, PI / 2F, 0F, 0F);
	animator.move(body, 0F, -2F, 0F);
animator.endPhase();

//ADD THIS LINE
animator.setStationaryPhase(6);

Therefore, after hitting the ground, the model will stay in that position for 6 ticks. Then, after that, we finally want the model to go back to its default rotations and positions. Once again, Animator's resetPhase(int) method has been created to make things simpler. The restPhase() method recieves the duration as a paramater as usual, and transitions the current pose back into the default pose. Again, startPhase() and endPhase() don't need to be called. Type like so:

animator.setAnim(1);
animator.startPhase(10);
	animator.rotate(head, -PI / 6F, 0F, 0F);
	animator.rotate(body, -PI / 6F, 0F, 0F);
animator.endPhase();
animator.startPhase(4);
	animator.rotate(body, PI / 2F, 0F, 0F);
	animator.move(body, 0F, -2F, 0F);
animator.endPhase();
animator.setStationaryPhase(6);

//ADD THIS LINE
animator.resetPhase(10);

Nice job! You've finished your first animation!

Making Many Animations and Finishing Up

To make more animations, simply do the same thing right under your previous animations. Just remember to call Animator.setAnim(int) when starting a new animation (no need to end the animation; you only need to end phases). For our example, our second animation for AIShakeHead looks like this:

animator.setAnim(2);
animator.startPhase(10);
	animator.rotate(head, 0F, -PI / 4F, 0F);
	animator.rotate(body, 0F, -PI / 8F, 0F);
animator.endPhase();
animator.startPhase(10);
	animator.rotate(head, 0F, PI / 4F, 0F);
	animator.rotate(body, 0F, PI / 8F, 0F);
animator.endPhase();
animator.resetPhase(10);

Add this to your ModelTest.animate() method, and you're done! Your ModelTest should look something like this:

public class ModelTest extends ModelBase {
	
	public ModelRenderer body, head;
	private Animator animator;
	
	public static final float PI = (float)Math.PI;
	
	public ModelTest() {
		body = new ModelRenderer(this, 32, 0);
		body.addBox(-3F, -10F, -3F, 6, 10, 6);
		body.setRotationPoint(0F, 24F, 0F);
		head = new ModelRenderer(this, 0, 0);
		head.addBox(-4F, -8F, -4F, 8, 8, 8);
		head.setRotationPoint(0F, -10F, 0F);
		body.addChild(head);
		
		animator = new Animator(this);
	}
	
	public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) {
		animate((IAnimatedEntity)entity, f, f1, f2, f3, f4, f5);
		body.render(f5);
	}
	
	public void setAngles() {
		//reset the rotation point each render tick
		body.rotationPointY = 24F;
	}
	
	public void animate(IAnimatedEntity entity, float f, float f1, float f2, float f3, float f4, float f5) {
		animator.update(entity);
		setAngles();
		
		animator.setAnim(1);
		animator.startPhase(10);
			animator.rotate(head, -PI / 6F, 0F, 0F);
			animator.rotate(body, -PI / 6F, 0F, 0F);
		animator.endPhase();
		animator.startPhase(4);
			animator.rotate(body, PI / 2F, 0F, 0F);
			animator.move(body, 0F, -2F, 0F);
		animator.endPhase();
		animator.setStationaryPhase(6);
		animator.resetPhase(10);
		
		animator.setAnim(2);
		animator.startPhase(10);
			animator.rotate(head, 0F, -PI / 4F, 0F);
			animator.rotate(body, 0F, -PI / 8F, 0F);
		animator.endPhase();
		animator.startPhase(10);
			animator.rotate(head, 0F, PI / 4F, 0F);
			animator.rotate(body, 0F, PI / 8F, 0F);
		animator.endPhase();
		animator.resetPhase(10);
	}
}

Congratulations! Just link everything up, register your entity, and try it out! Have fun :)

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.