1

I am making a mod that tells you your current speed on the screen. My current issue is finding a good way to get the current speed at each frame.

My attempt consists of my knowledge that the LivingEntity class (from which the Player class extends) has a function called getSpeed(). All I need now is to find a public function that returns the current player object.

If there is a way to get the player's speed that's easier (or more direct) than this, please let me know. I am still fairly new to Minecraft modding, so I hope the answer doesn't seem too obvious.

EDIT: I already posted this on stackGameDev, but I wanted to repost here so that it would get more attention

1 Answer 1

2

The .getSpeed() method that you found would not do what you want, even if you were able to call it --- it gives you an entity's base speed multiplier, basically how fast do they walk compared to other entities. For player entities, this is hardcoded to 0.1.


However, we can still get the information from the player, we just need to do it in a different way, and to that end you are correct in thinking that we need a reference to the current player. You can always get this via something like

var player = Minecraft.getInstance().player; 

however, I think you might also find that its given to you for free in most places where you'd actually want to use it --- for example, when I was testing this I was just logging out the speed every tick by subscribing to the PlayerTickEvent, and that event gives you the player object directly, so you wouldn't need to grab it yourself.


In any event, we now have a reference to our player --- how do we calculate their speed?

On the player, you'll find a few methods to get their X, Y and Z coordinates in the world: .getX(), .getY() and .getZ(). There are also some fields which store the X, Y and Z position the player was at last frame, these are .xOld, .yOld and .zOld. With this information, we can work out how far the player travelled between this frame and the previous frame.

var deltaX = player.getX() - player.xOld; var deltaY = player.getY() - player.yOld; var deltaZ = player.getZ() - player.zOld; 

(In Physics delta, quite literally referring to the Greek letter Δ, means "change", which is why these are named as they are, it's referring to the change in the X, Y and Z values over time).

Now we have our deltas, how do you calculate the speed? Well, you might remember Pythagoras's theorem from school: a2 + b2 = c2. If you think about a 2d world for a second, we know how far they moved horizontally (their X delta), and how far they moved vertically (their Y delta), so that means that we now have two sides of a triangle (A and B), and to find the total distance that they moved you'd just need to find the third side of that triangle (C).

Well, it turns out that Pythagoras's theorem actually generalises to any number of higher dimensions, giving us a2 + b2 + c2 = d2 for 3d spaces. This means that to find the total distance they travelled since last frame, we just need to do this:

var speed = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2) + Math.pow(deltaZ, 2)); 

This is the player's speed, because speed is just the rate of change of an object's position, which is exactly what we've calculated. A value of 1 would mean, for example, that they had travelled one whole block since last frame, 2 would be two blocks, 0.5 would be half a block, etc. I believe that canonically in Minecraft each block is 1 meter cubed in size, so it would be correct to say that this value is their speed in meters.

Sign up to request clarification or add additional context in comments.

10 Comments

Thanks, this really helped me get closer. I have one more question though: How could I convert this to blocks per second (b/s)? Currently, it's giving me the blocks per frame, bet that isn't very readable. How could I convert this?
Would I simply multiply the speed by the FPS?
Yes, I think that would be the solution. You can't obviously precisely convert frames to seconds as their FPS can vary, but multiplying by their current FPS would definitely be a good enough approximation
I've just tried this but it's given ridiculous values such as 12 bps when walking while the fandom says it should be around 4, 15 bps (fandom says 5) when sprinting, and an absurd 96 bps when flying!
You probably want to multiply by TPS rather than FPS. Ticks actually update the simulation of the world, and there can be at most 20 per second, whereas frames redraw the screen, and I guess if you turn off vsync there is no upper limit on FPS besides your computer (although FPS > your vsync is typically pointless). So the player will only actually be moving once every tick, not once every frame
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.