Here's what I came up with for a digital speedometer. Note that this is completely un-tested and I could very well have made some errors. (I will, however, have it tested in short order.)
Also, this is for a "slot machine wheel" way of rendering the digits, where it rotates vertically. If you want to set it up another way, just change the code in setGaugeDigitPos. If you want to use different renders, look at the source code for my Crossfire wing (or for BB93's Community Rimpack) to see how to change the render of an object.
Spoiler:
package java.game.cars;
import java.io.*;
import java.util.*;
import java.util.resource.*;
import java.render.osd.*;
import java.game.*;
import java.game.cars.*;
import java.game.parts.*;
import java.game.parts.bodypart.*;
import java.game.parts.enginepart.*;
import java.game.parts.rgearpart.*;
import java.game.parts.rgearpart.reciprocatingrgearpart.*;
public class SpeedometerDigital extends DecorativeBodyPart
{
// begin movable speedometer script
Ypr anim_ori_1; // rotation vector for first digit (units), dynamically assigned
Ypr anim_ori_2; // rotation vector for second digit (tens), dynamically assigned
Ypr anim_ori_3; // rotation vector for third digit (hundreds), dynamically assigned
// int speedo_check_overflow = 0;
// int speedo_check_underflow = 1;
// int speedo_num_regions = 1; // will be equal to last array's index; number of speedometer "chunks"
// float[] speedo_value = new float[5];
// float[] speedo_pos = new float[5];
int speedo_units = 0; // 0 = metric, 1 = Imperial / US customary
int speedo_hide_unused_digits = 1; // 1 = yes, 0 = no
Thread AnimateThread;
int installed;
static float math_pi = 3.1415926;
static float kmh_to_mph = 0.621371;
static float deg_to_rad = math_pi / 180;
public SpeedometerDigital( int id )
{
super( id );
speedo_units = 0;
speedo_hide_unused_digits = 1;
AnimateThread = new Thread( this, "Animate Thread" );
AnimateThread.start();
}
public void resetAnim() // forces animation to reset
{
if( partOnSlot(991) )
partOnSlot(991).setSlotPos( 1, new Vector3(0,0,0), new Ypr(0,0,0) );
if( partOnSlot(992) )
partOnSlot(993).setSlotPos( 1, new Vector3(0,0,0), new Ypr(0,0,0) );
if( partOnSlot(993) )
partOnSlot(993).setSlotPos( 1, new Vector3(0,0,0), new Ypr(0,0,0) );
}
public void setGaugeDigitPos( int dig1, int dig2, int dig3 )
{
if( partOnSlot(991) )
partOnSlot(991).setSlotPos( 1, new Vector3(0,0,0), new Ypr(0,deg2rad(dig1/10*360),0) );
else if( partOnSlot(991) ) // checks to see if first speedo digit is installed
partOnSlot(991).setSlotPos( 1, new Vector3(0,-0.100,0), new Ypr(0,0,0) );
if( partOnSlot(992) && (dig2 || !speedo_hide_unused_digits) ) // checks to see not only if second digit part is installed, but also if either dig2 >= 0 or hide_unused_digits is false
partOnSlot(992).setSlotPos( 1, new Vector3(0,0,0), new Ypr(0,deg2rad(dig2/10*360),0) );
else if( partOnSlot(992) )
partOnSlot(991).setSlotPos( 1, new Vector3(0,-0.100,0), new Ypr(0,0,0) );
if( partOnSlot(993) && (dig3 || !speedo_hide_unused_digits) ) // checks to see not only if second digit part is installed, but also if either dig3 >= 0 or hide_unused_digits is false
partOnSlot(993).setSlotPos( 1, new Vector3(0,0,0), new Ypr(0,deg2rad(dig2/10*360),0) );
else if( partOnSlot(993) )
partOnSlot(991).setSlotPos( 1, new Vector3(0,-0.100,0), new Ypr(0,0,0) );
}
public float rad2deg( float rad )
{
return(rad / deg_to_rad);
}
public float deg2rad( float deg )
{
return(deg * deg_to_rad);
}
public float kmh2mph( float kmh )
{
return(kmh * kmh_to_mph);
}
public float mph2kmh( float mph )
{
return(mph / kmh_to_mph);
}
public int speedo_calc_digit1 ( float speed, int )
{
int result;
float speedtemp;
if( speedo_units )
speedtemp = kmh2mph(speedtemp);
while (speedtemp >= 100)
speedtemp += (-100);
while (speedtemp >= 10)
speedtemp += (-10);
result = speedtemp;
return result;
}
public int speedo_calc_digit2 ( float speed, int )
{
int result;
float speedtemp;
if( speedo_units )
speedtemp = kmh2mph(speedtemp);
while (speedtemp >= 100)
speedtemp += (-100);
speedtemp = speedtemp / 10;
result = speedtemp;
return result;
}
public int speedo_calc_digit3 ( float speed, int )
{
int result;
float speedtemp;
if( speedo_units )
speedtemp = kmh2mph(speedtemp);
speedtemp = speedtemp / 100;
result = speedtemp;
return result;
}
public void run()
{
while(1)
{
if(AnimateThread)
{
the_car = null;
getCar_LocalVersion();
if( the_car && GameLogic.player && GameLogic.player.car && the_car == GameLogic.player.car.chassis ) // player is using this car
{
installed = 1;
float speed = Math.sqrt(GameLogic.player.car.getSpeedSquare())*3.6;
setGaugeDigitPos(speedo_calc_digit1(speed),speedo_calc_digit2(speed),speedo_calc_digit3(speed));
//setSlotPos( 991, new Vector3(0,0,0), new Ypr(0,0,-3.142) );
if(AnimateThread) AnimateThread.sleep(5); // Wait 0.005 sec (in theory, assuming 29 FPS)
}
else
{
if( installed )
{
setSlotPos( 991, new Vector3(0,0,0), new Ypr(0,0,0) );
setSlotPos( 992, new Vector3(0,0,0), new Ypr(0,0,0) );
setSlotPos( 993, new Vector3(0,0,0), new Ypr(0,0,0) );
installed = 0;
}
if(AnimateThread) AnimateThread.sleep( 2000 ); // Wait 2 sec
}
}
}
}
}