Jump to content

How to make simple, smooth 2d animation? (detailed)


BobieBobie

Recommended Posts

Good day. I need help with making a smooth animation. But first some entry information.
I am trying to smoothly move rectangle from left to right. A pretty simple task I thought: use

RenderGameOverlayEvent

and redraw rectangle every tick. But animation looks pretty ugly, not smooth at all. I did research for 2 days and found something called "partialTicks". @diesieben07 wrote that this can be used to create smooth animations. But I ran into a problem. Here is a formula that @diesieben07 has mentioned:

Quote

actualValue = previousTickValue + (currentValue - lastTickValue) * partialTicks

 

What's the problem? Maybe I do not understand something, but as I can see "actualValue" will always be 0 because the initial value is 0F and there is no next value. It is hard to explain, but I want to apply my code with comments. 

NOTE: I have already registered my events in the main class.

 

Private Gist link: GitHub Gist URL

Link to comment
Share on other sites

1 minute ago, diesieben07 said:

You need to store two values: current and lastTick.

Every tick (not frame, so 20 times a second regardless of framerate, this makes the animation run at a constant speed) you copy current to lastTick and then compute the next value and store that in current.

Every frame you use the formula actual = lastTick + (current - lastTick) * partialTicks to compute the position you actually render at.

This way you will get a smooth animation which still runs at a constant speed, regardless of framerate.

Ok, I got it, but here is the thing: when I am starting to draw, there is no last tick, cause it only started to draw, I believe you can understand me. What shell I do?

Link to comment
Share on other sites

Am I on the right way?:

private float current = 1, lastTick = 1; // "1" is wrong, cause it will lead to 0. It is obvious.

/*....*/

this.lastTick = this.current;
this.current = this.lerp(partialTicks);
this.currentNotification.draw(this.current);

/*....*/

private float lerp(float partialTicks)
{
  return this.lastTick + (this.current - this.lastTick) * partialTicks;
}

 

Edited by BobieBobie
Link to comment
Share on other sites

Did everything you wrote: I am updating current every tick and rendering every frame. I logged the offset to the console and noticed that offset is not equal. I mean this:

Spoiler

[13:52:56] [Client thread/INFO] [Notifications Mod]: Offset: 0.0
[13:52:56] [Client thread/INFO] [Notifications Mod]: Offset: 3.6461377
[13:52:56] [Client thread/INFO] [Notifications Mod]: Offset: 15.162073
[13:52:57] [Client thread/INFO] [Notifications Mod]: Offset: 20.078074
[13:52:57] [Client thread/INFO] [Notifications Mod]: Offset: 24.206429
[13:52:57] [Client thread/INFO] [Notifications Mod]: Offset: 28.769346
[13:52:57] [Client thread/INFO] [Notifications Mod]: Offset: 41.525272
[13:52:58] [Client thread/INFO] [Notifications Mod]: Offset: 47.11528
[13:52:58] [Client thread/INFO] [Notifications Mod]: Offset: 52.34848
[13:52:58] [Client thread/INFO] [Notifications Mod]: Offset: 57.0762
[13:52:58] [Client thread/INFO] [Notifications Mod]: Offset: 61.14977
[13:52:58] [Client thread/INFO] [Notifications Mod]: Offset: 66.20457

Here is an updated code:

Every RenderGameOverlayEvent.Post:

float actualValue = this.lastTick + (this.current - this.lastTick) * partialTicks;
this.currentNotification.draw(actualValue);

ClientTickEvent:

@SubscribeEvent
public void onClientTick(TickEvent.ClientTickEvent event)
{
if (event.phase != TickEvent.Phase.END) return;
NotificationsMod.NMANAGER.updateCurrent();
}

updateCurrent method:

public void updateCurrent()
{
if (this.currentNotification == null) return;

this.lastTick = this.current;
this.current += 2F; // Bigger number - faster animation
}

Even if I do 

this.current++;

animation/offset are not "pretty". 

 

Is that normal? Or am I stupid? :D

Link to comment
Share on other sites

have a look at this, https://github.com/Cadiboo/WIPTech/blob/d5504c15d23c66b220064c93ce8fa27c3c457fd0/src/main/java/cadiboo/wiptech/util/Utils.java#L336-L389

It might not be exactly what your looking for, but its 99% perfect and I spent a lot of time on it so I can say that it works very well

 

Sorry, read the post wrong. Its probably only about 20% what you want but its still useful

Edited by Cadiboo
oops

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Link to comment
Share on other sites

Ok. Imagine drawing a rectangle with built-in drawRect function from Gui class. I am trying to move it SMOOTHLY across the screen. To be more simple: have you ever seen Windows 10 Notifications, that appear from the right bottom side of the screen? Thats what I am trying to recreate. Now it is moving "unstable", not smooth. Maybe I need to change incrementation of current value to much smaller value, but if I will do that - the speed of animation will be VEEERY slow. Reminding Windows 10 notification. Fast and smooth.
Offset? That is a number which represents how far will the rectangle move on the next frame.

Link to comment
Share on other sites

EDIT: Made a correction based on diesieben07's comment.

 

The reason you're confused is that your code is called every render frame, not every tick. Instead you must handle both ticks and renders. The partial ticks helps you convert and synchronize between them.

 

This is how I would name the fields in my equation to make it clearer:

currentFramePos = previousTickPos + (currentTickPos - previousTickPos) * partialTicks

 

Then the steps would be as follows:

1) Start by initializing all of the position fields to the starting position. Don't intialize partialTicks as that is a parameter you'll get from the render event.

2) In a tick-handling (not a render!) event you would set the previousTickPos to currentTickPos, then add whatever motion you want to currentTickPos.

3) In a render-handling event you would set  the currentFramePos using the formula: 

currentFramePos = previousTickPos + (currentTickPos - previousTickPos) * partialTicks

 

The reason you do all this is that you need to draw in render events but you need to set the motion speed in a tick event, so you need to handle both ticks and renders and use partialTicks to convert.

 

 

Edited by jabelar

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

So your problem right now is that it starts moving and never stops?

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

1 hour ago, BobieBobie said:

Of course no. Compare both animations. Mine is laggy, not smooth. And the other one is so smooth. No lagging at all.

How is your FPS? And the world TPS should be 20, is it?

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Just now, Animefan8888 said:

How is your FPS? And the world TPS should be 20, is it?

On the first, weak machine around 20 frames. On another around 70. Both have the same issue. And I can notice why. PartialTicks are unequal, so that xOffset is unstable, which causes jumping animation.

Link to comment
Share on other sites

16 minutes ago, BobieBobie said:

PartialTicks are unequal, so that xOffset is unstable, which causes jumping animation.

Partial ticks is just a float value that is updated every frame to determine how much time is left between the last tick and the next tick on a scale of 0-1. It should only be unstable if your FPS or TPS is unstable.

 

Have you tried incrementing by 1 instead of 2 and seeing how that functions.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Just now, Animefan8888 said:

Partial ticks is just a float value that is updated every frame to determine how much time is left between the last tick and the next tick on a scale of 0-1. It should only be unstable if your FPS or TPS is unstable.

 

Have you tried incrementing by 1 instead of 2 and seeing how that functions.

Of course, nothing changed except the speed. Rewatch the second video. I am having lower FPS there (100+ players nearby) and animations are damn smooth. I cannot achieve that.

Link to comment
Share on other sites

1 hour ago, BobieBobie said:

Of course, nothing changed except the speed. Rewatch the second video. I am having lower FPS there (100+ players nearby) and animations are damn smooth. I cannot achieve that.

Using just this I can get a smooth animation, and most of this was copied over from your code.

Spoiler

@EventBusSubscriber
public class ForumsTest extends Gui {
	
	private static float current, previous;
	
	@SubscribeEvent
	public static void clientTick(ClientTickEvent event) {
		if (event.phase != Phase.END) return;
		if (current >= 200) current = 0;
		previous = current;
		current += 2;
	}
	
	@SubscribeEvent
	public static void renderOverlay(RenderGameOverlayEvent.Post event) {
		if (event.getType() != ElementType.CHAT) return;
		float actual = previous + (current - previous) * event.getPartialTicks();
		drawRect((200 * -1) + Math.round(actual), 0, 200 + Math.round(actual), 60, 0xff000000);
	}
	
}

 

 

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

18 minutes ago, BobieBobie said:

I cannot migrate to the latest version, because not all of the required mods currently support newer versions.

Doesn't change the fact that, what I did worked from an earlier message.

2 hours ago, Animefan8888 said:

Using just this I can get a smooth animation, and most of this was copied over from your code.

 

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Just now, Animefan8888 said:

Doesn't change the fact that, what I did worked from an earlier message.

 

Glad to hear that. Tomorrow morning I will test your code on third machine(much better performance) and see if the animation is smooth. Ty again.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.