How to calculate a drift in car?

Started by
0 comments, last by 0x3a 12 years, 9 months ago
Hello people!

I want to calculate the if a car drifts,
I'm using C++ and I have ported some code from PAWN (yes a scripting language) and the code doesn't seem to work correctly. The extension for my game is behaving with weird calculations.

this is tthe code I yet have in c++:


/*
* Default Includes
*/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

/*
* AMX Includes
*/
#include "./SDK/amx/amx.h"
#include "./SDK/plugin.h"
/*
* Includes from Third Partys'
*/
//#pragma warning(disable:4244)

#include "./ThirdPartySource/Invoke.cpp"//
//#include "./ThirdPartySource/samp.cpp"//ZeeX

AMX * pAMX;

#define PI 3.14159265

extern void * pAMXFunctions;

using namespace std;

#define MAX_PLAYERS (500)

float GlobalPos_X[MAX_PLAYERS];
float GlobalPos_Y[MAX_PLAYERS];
float GlobalPos_Z[MAX_PLAYERS];

float GlobalPos_Angle1[MAX_PLAYERS];
float GlobalPos_Angle2[MAX_PLAYERS];

float SpeedX;
float SpeedY;
float SpeedZ;

float floatdata[11];

int GlobalPos_Timer[MAX_PLAYERS] = {-1};
int GlobalPos_Points[MAX_PLAYERS];
int GlobalPos_Combo[MAX_PLAYERS];

#define PLAYER_STATE_DRIVER (2)

#define PLUGIN_PRIVATE_UPDATE_DRIFT (50)//time in miliseconds
#define SLEEP_TIME PLUGIN_PRIVATE_UPDATE_DRIFT

#define MINIMAL_ANGLE (15.5)//in degrees
#define MAXIMAL_ANGLE (360.0)//in degrees
#define MINIMAL_SPEED (15.0)//in meters / second
#define MAXIMAL_SPEED (500.0)//in meters / second

float g_MinSpeed = MINIMAL_SPEED;
float g_MaxAngle = MAXIMAL_ANGLE;
float g_MinAngle = MINIMAL_ANGLE;
float g_MaxSpeed = MAXIMAL_SPEED;

int DriftStartEndDelay = 40;
//#define USE_VEHICLE_MODEL_CHECK
//#define CHECK_MAX_VALUES

int g_Ticked = 0;
int g_TickMax = PLUGIN_PRIVATE_UPDATE_DRIFT;

int PlayerVehicleID;
#if defined USE_VEHICLE_MODEL_CHECK
int PlayerVehicleModelID;
#endif


int OnPlayerDriftStart(int playerid);
int OnPlayerDriftStart(int playerid)
{
//if (playerid == NULL)
// return 0;
int idx;
cell ret;
int amxerr = amx_FindPublic(pAMX, "OnPlayerDriftStart", &idx);
if (amxerr == AMX_ERR_NONE)
{
amx_Push(pAMX, playerid);
amx_Exec(pAMX, &ret, idx);
return 1;
}
return 0;
}

int OnPlayerDriftUpdate(int playerid,int points,int combo);
int OnPlayerDriftUpdate(int playerid,int points,int combo)
{
//if (playerid == NULL)
// return 0;
int idx;
cell ret;
int amxerr = amx_FindPublic(pAMX, "OnPlayerDriftUpdate", &idx);
if (amxerr == AMX_ERR_NONE)
{
amx_Push(pAMX, combo);
amx_Push(pAMX, points);
amx_Push(pAMX, playerid);
amx_Exec(pAMX, &ret, idx);
return 1;
}
return 0;
}

int OnPlayerDriftEnd(int playerid,int points,int combo);
int OnPlayerDriftEnd(int playerid,int points,int combo)
{
//if (playerid == NULL)
// return 0;
int idx;
cell ret;
int amxerr = amx_FindPublic(pAMX, "OnPlayerDriftEnd", &idx);
if (amxerr == AMX_ERR_NONE)
{
amx_Push(pAMX, combo);
amx_Push(pAMX, points);
amx_Push(pAMX, playerid);
amx_Exec(pAMX, &ret, idx);
return 1;
}
return 0;
}

PLUGIN_EXPORT void PLUGIN_CALL
ProcessTick()
{
if(g_Ticked == g_TickMax)
{
int playerid = 0;
while(playerid != (MAX_PLAYERS-1))
{
if(g_Invoke->callNative(&PAWN::GetPlayerState,playerid) == PLAYER_STATE_DRIVER)
{
PlayerVehicleID = g_Invoke->callNative(&PAWN::GetPlayerVehicleID,playerid);
#if defined USE_VEHICLE_MODEL_CHECK
PlayerVehicleModelID = Invoke::callNative(&PAWN::GetVehicleModel,PlayerVehicleID);

switch(PlayerVehicleModelID)
{
case 443,448,461 .. 463,521 .. 523,581,586,481,509,510,430,446,452 .. 454,472,473,484,493,595,417,425,447,465,469,487,488,497,501,548,563,406,444,556,557,573,460,464,476,511 .. 513,519,520,539,553,577,592,593,471:
{
#endif
g_Invoke->callNative(&PAWN::GetVehicleVelocity,PlayerVehicleID, &SpeedX, &SpeedY, &SpeedZ);
g_Invoke->callNative(&PAWN::GetVehicleZAngle, PlayerVehicleID, &GlobalPos_Angle1[playerid]);
g_Invoke->callNative(&PAWN::GetPlayerPos, playerid, &floatdata[4], &floatdata[5], &floatdata[6]);
floatdata[10] = sqrt(pow(SpeedX, 2)+pow(SpeedY, 2)+pow(SpeedZ, 2))*274;
floatdata[1] = sqrt(pow((floatdata[4]-GlobalPos_X[playerid]),2)+pow((floatdata[5]-GlobalPos_Y[playerid]),2));
floatdata[3] = GlobalPos_Angle1[playerid];
if(floatdata[4]>GlobalPos_X[playerid]){floatdata[7]=floatdata[4]-GlobalPos_X[playerid];}else{floatdata[7]=GlobalPos_X[playerid]-floatdata[4];}

if(floatdata[5]>GlobalPos_Y[playerid]){floatdata[8]=floatdata[5]-GlobalPos_Y[playerid];}else{floatdata[8]=GlobalPos_Y[playerid]-floatdata[5];}

if(GlobalPos_Y[playerid]>floatdata[5] && GlobalPos_X[playerid]>floatdata[4]){ //1
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = (floatdata[0]+90)-(floatdata[0]*2)+90;
}
if(GlobalPos_Y[playerid]<floatdata[5] && GlobalPos_X[playerid]>floatdata[4]){ //2
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = (floatdata[0]+180)-180;
}
if(GlobalPos_Y[playerid]<floatdata[5] && GlobalPos_X[playerid]<floatdata[4]){ //3
floatdata[0] = acos(floatdata[8]/floatdata[1]);
floatdata[9] = (floatdata[0]+360)-(floatdata[0]*2);
}
if(GlobalPos_Y[playerid]>floatdata[5] && GlobalPos_X[playerid]<floatdata[4]){ //4
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatdata[0]+180;
}
if(floatdata[9] == 0.0)
{
GlobalPos_Angle2[playerid] = floatdata[3];
} else {
GlobalPos_Angle2[playerid] = floatdata[9];
}

float angle = abs(GlobalPos_Angle1[playerid]-GlobalPos_Angle2[playerid]);
if(
#if defined CHECK_MAX_VALUES
g_MaxAngle > angle &&
#endif
angle > g_MinAngle &&
floatdata[10] > g_MinSpeed
#if defined CHECK_MAX_VALUES
&& floatdata[10] < g_MaxSpeed
#endif
)
{
GlobalPos_Points[playerid] += (int)floor(angle * floatdata[10]);
if(GlobalPos_Timer[playerid] != -1)
{
GlobalPos_Combo[playerid] += 1;
OnPlayerDriftUpdate(playerid,GlobalPos_Points[playerid],GlobalPos_Combo[playerid]);
}
else
{
OnPlayerDriftStart(playerid);
}
GlobalPos_Timer[playerid] = DriftStartEndDelay;
}
else
{
if(GlobalPos_Timer[playerid] != -1)
{
GlobalPos_Timer[playerid]--;
if(GlobalPos_Timer[playerid] == -1)
{
OnPlayerDriftEnd(playerid,GlobalPos_Points[playerid],GlobalPos_Combo[playerid]);
GlobalPos_Combo[playerid] = 0;
GlobalPos_Points[playerid] = 0;
}
}
}
#if defined USE_VEHICLE_MODEL_CHECK
}
}
#endif
GlobalPos_X[playerid] = floatdata[4];
GlobalPos_Y[playerid] = floatdata[5];
GlobalPos_Z[playerid] = floatdata[6];
}
playerid++;
}
g_Ticked = -1;
}
g_Ticked += 1;
}

static cell AMX_NATIVE_CALL SetDriftUpdateDelay( AMX* amx, cell* params )
{
if(params[1] > 5000)
{
g_TickMax = 5000;
return 1;
}
if(params[1] < 25)
{
g_TickMax = 25;
return 1;
}
g_TickMax = params[1];
return 1;
}

static cell AMX_NATIVE_CALL SetDriftMinAngle( AMX* amx, cell* params )
{
float val = amx_ctof(params[1]);
if(val > 90.0)
{
g_MinAngle = 90.0;
return 1;
}
if(val < 0.0)
{
g_MinAngle = 0.0;
return 1;
}
g_MinAngle = val;
return 1;
}

static cell AMX_NATIVE_CALL SetDriftMaxAngle( AMX* amx, cell* params )
{
float val = amx_ctof(params[1]);
if(val > 89.0)
{
g_MaxAngle = 89.0;
return 1;
}
if(val < 0.1)
{
g_MaxAngle = 0.1f;
return 1;
}
g_MaxAngle = val;
return 1;
}

static cell AMX_NATIVE_CALL SetDriftMinSpeed( AMX* amx, cell* params )
{
float val = amx_ctof(params[1]);
if(val > 1000.0)
{
g_MinSpeed = 1000.0;
return 1;
}
if(val < 0.1)
{
g_MinSpeed = 0.1f;
return 1;
}
g_MinSpeed = val;
return 1;
}

static cell AMX_NATIVE_CALL SetDriftMaxSpeed( AMX* amx, cell* params )
{
float val = amx_ctof(params[1]);
if(val > 1000.0)
{
g_MaxSpeed = 1000.0;
return 1;
}
if(val < 0.1)
{
g_MaxSpeed = 0.1f;
return 1;
}
g_MaxSpeed = val;
return 1;
}

static cell AMX_NATIVE_CALL n_DriftStartEndDelay( AMX* amx, cell* params )
{
if(params[1] > 1000)
{
DriftStartEndDelay = 1000;
}
else if(params[1] < 0)
{
DriftStartEndDelay = 1;
}
else
{
DriftStartEndDelay = params[1];
}
return 1;
}

static cell AMX_NATIVE_CALL GetDriftMinSpeed( AMX* amx, cell* params )
{
cell* cptr;
amx_GetAddr(amx, params[1], &cptr);
*cptr = amx_ftoc(g_MinSpeed);
return 1;
}

static cell AMX_NATIVE_CALL GetDriftMaxSpeed( AMX* amx, cell* params )
{
cell* cptr;
amx_GetAddr(amx, params[1], &cptr);
*cptr = amx_ftoc(g_MaxSpeed);
return 1;
}

static cell AMX_NATIVE_CALL GetDriftMaxAngle( AMX* amx, cell* params )
{
cell* cptr;
amx_GetAddr(amx, params[1], &cptr);
*cptr = amx_ftoc(g_MaxAngle);
return 1;
}

static cell AMX_NATIVE_CALL GetDriftMinAngle( AMX* amx, cell* params )
{
cell* cptr;
amx_GetAddr(amx, params[1], &cptr);
*cptr = amx_ftoc(g_MinAngle);
return 1;
}

static cell AMX_NATIVE_CALL n_GetDriftStartEndDelay( AMX* amx, cell* params )
{
return DriftStartEndDelay;
}

static cell AMX_NATIVE_CALL GetDriftUpdateDelay( AMX* amx, cell* params )
{
return g_TickMax;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports()
{
return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES | SUPPORTS_PROCESS_TICK;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load( void **ppData )
{
g_Invoke = new Invoke;
pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
cout << " Drift Counter Plugin 2011 by Gamer_Z loaded";
return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload( )
{
list<AMX*>::iterator i = g_Invoke->amx_list.begin();
list<AMX*>::iterator l;

for(l = g_Invoke->amx_list.end(); i != l; i++)
{
if(*i == pAMX)
{
g_Invoke->amx_list.erase(i);
break;
}
}
if(g_Invoke) delete g_Invoke;
cout << " Drift Counter Plugin 2011 by Gamer_Z unloaded";
}

AMX_NATIVE_INFO driftAMXNatives[ ] =
{
{"DriftSet_UpdateDelay", SetDriftUpdateDelay},
{"DriftSet_MinimalSpeed", SetDriftMinSpeed},
{"DriftSet_MinimalAngle", SetDriftMinAngle},
#if defined CHECK_MAX_VALUES
{"DriftSet_MaximalSpeed", SetDriftMaxSpeed},
{"DriftSet_MaximalAngle", SetDriftMaxAngle},

{"DriftGet_MaximalSpeed", GetDriftMaxSpeed},
{"DriftGet_MaximalAngle", GetDriftMaxAngle},
#endif
{"DriftSet_StartEndDelay", n_DriftStartEndDelay},

{"DriftGet_StartEndDelay", n_GetDriftStartEndDelay},
{"DriftGet_UpdateDelay", GetDriftUpdateDelay},

{"DriftGet_MinimalSpeed", GetDriftMinSpeed},
{"DriftGet_MinimalAngle", GetDriftMinAngle},
{0, 0}
};

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad( AMX *amx )
{
pAMX = amx;
g_Invoke->amx_list.push_back(amx);
g_Invoke->getAddresses();
return amx_Register( amx, driftAMXNatives, -1 );
}

PLUGIN_EXPORT int PLUGIN_CALL AmxUnload( AMX *amx )
{
return AMX_ERR_NONE;
}

pastebin:
http://pastebin.com/m9AMupBD

okay and I can call any PAWN function from C++, so this are the vehicle functions to my diposal:


native GetVehiclePos(vehicleid, &Float:x, &Float:y, &Float:z); -> http://wiki.sa-mp.co...i/GetVehiclePos
native GetVehicleZAngle(vehicleid, &Float:z_angle); -> http://wiki.sa-mp.co...etVehicleZAngle
native GetVehicleRotationQuat(vehicleid, &Float:w, &Float:x, &Float:y, &Float:z); -> http://wiki.sa-mp.co...cleRotationQuat
native GetVehicleHealth(vehicleid, &Float:health); -> http://wiki.sa-mp.co...etVehicleHealth
native GetVehicleVelocity(vehicleid, &Float:X, &Float:Y, &Float:Z); -> http://wiki.sa-mp.co...VehicleVelocity

I repeat: all this functions can be easily called from C++ and used in the extension of the game (plugin).



I would like to know how to accomplish these calculation as they don't work correctly...

this is the code from PAWN:


for(new playerid; playerid < MAX_PLAYERS; playerid++)
{
if(IsPlayerConnected(playerid) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
{
new PlayerVehicleID = GetPlayerVehicleID(playerid);
//new PlayerVehicleModelID = GetVehicleModel(PlayerVehicleID);
new Float:floatdata[11];

//switch(PlayerVehicleModelID)
//{
// case 443,448,461 .. 463,521 .. 523,581,586,481,509,510,430,446,452 .. 454,472,473,484,493,595,417,425,447,465,469,487,488,497,501,548,563,406,444,556,557,573,460,464,476,511 .. 513,519,520,539,553,577,592,593,471:
// {
new Float:SpeedX, Float:SpeedY, Float:SpeedZ;
GetVehicleVelocity(PlayerVehicleID, SpeedX, SpeedY, SpeedZ);
floatdata[10] = floatmul(floatsqroot((floatpower(SpeedX, 2.0)+floatpower(SpeedY, 2.0)+floatpower(SpeedZ, 2.0))), 274.0);

GetVehicleZAngle(PlayerVehicleID, GlobalPos[playerid][Angle1]);

GetPlayerPos(playerid,floatdata[4],floatdata[5],floatdata[6]);
floatdata[1] = floatsqroot(floatpower(floatsub(floatdata[4],GlobalPos[playerid][X]),2)+floatpower(floatsub(floatdata[5],GlobalPos[playerid][Y]),2));
GetVehicleZAngle(PlayerVehicleID, floatdata[3]);
if(floatdata[4]>GlobalPos[playerid][X]){floatdata[7]=floatdata[4]-GlobalPos[playerid][X];}else{floatdata[7]=GlobalPos[playerid][X]-floatdata[4];}
if(floatdata[5]>GlobalPos[playerid][Y]){floatdata[8]=floatdata[5]-GlobalPos[playerid][Y];}else{floatdata[8]=GlobalPos[playerid][Y]-floatdata[5];}
if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //1
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatsub(floatsub(floatadd(floatdata[0], 90), floatmul(floatdata[0], 2)), -90.0);
}
if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //2
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatsub(floatadd(floatdata[0], 180), 180.0);
}
if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //3
floatdata[0] = acos(floatdata[8]/floatdata[1]);
floatdata[9] = floatsub(floatadd(floatdata[0], 360), floatmul(floatdata[0], 2));
}
if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //4
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatadd(floatdata[0], 180);
}
if(floatdata[9] == 0.0)
{
GlobalPos[playerid][Angle2] = floatdata[3];
} else {
GlobalPos[playerid][Angle2] = floatdata[9];
}

new Float:angle = floatabs(GlobalPos[playerid][Angle1]-GlobalPos[playerid][Angle2]);
if(90.0 > angle > 17.5 && floatdata[10] > 23.5)
{
GlobalPos[playerid][Points] += floatround(angle * floatdata[10] / 83);
if(GlobalPos[playerid][Timer] != -1)
{
GlobalPos[playerid][Combo] += 1;
new s[256];
format(s, 256, "~n~~n~~n~~w~_________________Drift!~n~___________________~r~Points:~w~_%d~n~___________________~r~Combo:~w~_x%d!",GlobalPos[playerid][Points],floatround(GlobalPos[playerid][Combo]/30,floatround_floor)+1);
TextDrawSetString(PlayerTextDraw[playerid], s);
}
else
{
TextDrawShowForPlayer(playerid,PlayerTextDraw[playerid]);
//GameTextForPlayer(playerid, "Drift started!", 500, 1);
}
GlobalPos[playerid][Timer] = floatround(2000/SLEEP_TIME);
}
else
{
if(GlobalPos[playerid][Timer] != -1)
{
GlobalPos[playerid][Timer]--;
if(GlobalPos[playerid][Timer] == -1)
{
TextDrawHideForPlayer(playerid,PlayerTextDraw[playerid]);
//GameTextFormatForPlayer(playerid, "Drift ended with %d points!", 750, 1, GlobalPos[playerid][Points]);
GlobalPos[playerid][Combo] = 0;
GlobalPos[playerid][Points] = 0;
}
}
}
//}
//}

GetPlayerPos(playerid,GlobalPos[playerid][X],GlobalPos[playerid][Y],GlobalPos[playerid][Z]);
}
}


Hoep somebody can help me out, thanks in advance!



Advertisement
When I think about drift I'd say you need to implement momentum. On a side-note, that code is rather unreadable and I'm not going to attempt it, its 2am so yeah..

Anyway, take a look at this: http://en.wikipedia.org/wiki/Momentum
Momentum basically accounts for the movement already enforced on the object when trying to change the direction ( and velocity ) of the object. You can't go straight around corners you will 'drift' because you still have a velocity ( momentum, bazinga!).
If I've helped you in any way please push the reputation button, thanks!

Abstraction is my choice of words.
Portfolio: http://www.0x3a.com/
Blog: http://blog.0x3a.com/

This topic is closed to new replies.

Advertisement