Making a Speedometer
How to measure speed

Speed by build-in Physics

When you let the build-in Physics engine calculate the motion of your game object (dynamic, rigid body etc.) you can directly ask the game object.

The object will provide you the current linear velocity (there is an angular velocity too). The linear velocity is a vector that tells you the direction and the speed the object traveled since the last frame. The speed is the length of the vector (speed can never become negative!).

import bge 

object = bge.logic.getCurrentController().owner
velocity = object.getLinearVelocity()
speed = velocity.length


Speed by positional change

In some situations you can't or do not want to use the build-in physics engine. In that case you can "manually" calculate the speed from positional changes.

This method assumes the object traveled from the location of the last frame to the current location with constant speed on a direct line. Typically this is a pretty save assumption (but it does not consider if the object really moved or teleported such as static objects do).

Here we use the school math:

speed = distance (last position, current position) / time


We need to record the current position, to be used within the formula of he next frame, while we use the recorded position of the last frame. The time is the reciprocity of the frame rate (typically 60):

time = 1/frame rate


This means you can calculate the speed this way:

import bge 

object = bge.logic.getCurrentController().owner
lastPosition = object.get("lastPosition", object.worldPosition)
object["lastPosition"] = object.worldPosition.copy()

step = object.worldPosition - lastPosition
speed = step * bge.logic.getLogicTicRate()


What to do with the speed?

Just now the speed is in a local variable and will get lost as soon as you leave local space. 

From here you can place it in a property:

object["speed"] = speed


to be used within other Logic Bricks (including other Python code).

or you send it in a message:

bge.logic.sendMessage("speed changed", str(speed))


You can do that even with a message actuator:

messageActuator.body = str(speed)
controller.activate(messageActuator)


or any other logic brick.

How to get the speed for displaying?

Dependent what you did with the value, you can retrieve it an use it e.g. in a Text Object:

for body in messageSensor.bodies:
    textObject.text = body


or as property to play an action:
    for body in messageSensor.bodies:
        actionPlayer["frame"] = float(body)

....
There are really many options.

The message method is described in detail in the BGE Guide to Messages