Sign in to follow this  

How to calculate a drift in car?

This topic is 2349 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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++:

[code]
/*
* 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;
}[/code]
pastebin:
[url="http://pastebin.com/m9AMupBD"]http://pastebin.com/m9AMupBD[/url]

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); -> [url="http://wiki.sa-mp.com/wiki/GetVehiclePos"]http://wiki.sa-mp.co...i/GetVehiclePos[/url]
native GetVehicleZAngle(vehicleid, &Float:z_angle); -> [url="http://wiki.sa-mp.com/wiki/GetVehicleZAngle"]http://wiki.sa-mp.co...etVehicleZAngle[/url]
native GetVehicleRotationQuat(vehicleid, &Float:w, &Float:x, &Float:y, &Float:z); -> [url="http://wiki.sa-mp.com/wiki/GetVehicleRotationQuat"]http://wiki.sa-mp.co...cleRotationQuat[/url]
native GetVehicleHealth(vehicleid, &Float:health); -> [url="http://wiki.sa-mp.com/wiki/GetVehicleHealth"]http://wiki.sa-mp.co...etVehicleHealth[/url]
native GetVehicleVelocity(vehicleid, &Float:X, &Float:Y, &Float:Z); -> [url="http://wiki.sa-mp.com/wiki/GetVehicleVelocity"]http://wiki.sa-mp.co...VehicleVelocity[/url]

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:

[code]
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]);
}
}
[/code]

Hoep somebody can help me out, thanks in advance!



Share this post


Link to post
Share on other sites
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!).

Share this post


Link to post
Share on other sites

This topic is 2349 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this