Gamestudio Links
Zorro Links
Newest Posts
Newbie Questions
by fairtrader. 12/06/23 11:29
Zorro Trader GPT
by TipmyPip. 12/04/23 11:34
Square root rule
by Smallz. 12/02/23 09:15
RTest not found error
by TipmyPip. 12/01/23 21:43
neural function for Python to [Train]
by TipmyPip. 12/01/23 14:47
Xor Memory Problem.
by TipmyPip. 11/28/23 14:23
Training with command line parameters
by TipmyPip. 11/26/23 08:42
Combine USD & BTC Pairs In Asset Loop
by TipmyPip. 11/26/23 08:30
AUM Magazine
Latest Screens
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Tactics of World War I
Who's Online Now
7 registered members (fairtrader, Quad, miwok, Martin_HH, AndrewAMD, alibaba, dpn), 581 guests, and 0 spiders.
Key: Admin, Global Mod, Mod
Newest Members
fairtrader, hus, Vurtis, Harry5, KelvinC
19019 Registered Users
Previous Thread
Next Thread
Print Thread
Rating: 3
Dynamic positioning for racing games. #80773
07/08/06 19:30
07/08/06 19:30
Joined: Aug 2001
Posts: 2,320
Alberta, Canada
William Offline OP
Expert
William  Offline OP
Expert

Joined: Aug 2001
Posts: 2,320
Alberta, Canada
Below is some solid code for positions in a racing game. It is dynamic and can calculate your position whether you have 1-8 vehicles.
It also allows for 1 path divergence. So if your racetrack completely diverges at a point(2 seperate directions), and comes back together, the script
will keep the positioning working. I found this to be the best way to go about it. Using path_scan worked to an extent, but didn't suit my needs.

Your going to have to be more advanced with c-script to properly use it, but i'll explain some of it. I figured i'd post it since it was one of the more "sore" points of creating a full-fledged racing game(and I know i'd love to have seen this somewhere before I made it), next to multiplayer(but you cant really post that). If your a begginer, be sure to store this somewhere on your hardrive for future use anyways. Also, be sure to read the comments in the code. There
might be a better way to go about this too, so if anyones got something done, would be great to look into it.


Heres how to set up your paths in the level:

Make a path of about 20-30 nodes that goes around your level. This will be your main path.


If you have any divergences:

- make the skill2 of the node that diverges into 2 paths, equal to 1.

- make the last node on the divergence path, before it connects to the main path skill2 equal to 1. This node tells the positioning code to branch
back into the main path again.

- set the node on the main path(that the 2 paths diverge back into), as skill3 = 1. This tallies up your nodes and do a final position count from the
2 paths.

- The divergence path should have the same amount of nodes as the main path does(between where it diverges and connects again).

The code will detect both paths at once if there very close to eachother. So you may want to go with only one path at a time, if so, do this:

//if(s_time){if(s_add > v_add){max_add = s_add; my.pnplace = v_addi + s_add;} if(s_add < v_add){max_add = v_add; my.pnplace = v_addi + v_add;}}
//if(v_add == s_add){my.pnplace = v_addi + s_add;}
if(s_time){my.pnplace = v_addi + s_add + b_add;}

If you want both paths at a time(considering there far enough away from eachother), do this:

if(s_time){if(s_add > v_add){max_add = s_add; my.pnplace = v_addi + s_add;} if(s_add < v_add){max_add = v_add; my.pnplace = v_addi + v_add;}}
if(v_add == s_add){my.pnplace = v_addi + s_add;}
//if(s_time){my.pnplace = v_addi + s_add + b_add;}

That code above will take the highest node from either path(if 2 are detected at once), and use it for positioning.

Other Info

- Set the variable num_karts in your main(). So if you have 6 vehicles, make it equal 6.

- Also, I don't know how you go about your laps, but for every new lap, add this my.kartlap += 2; once. It is a failsafe method for the paths, basically
when you vehicle passes a new lap, you time the positioning by it. Meaning the vehicles that are ahead one lap will never fallbehind for whatever
reason(bug in positioning code, ect.).

Heres a quick way i'm doing it in the code. The player can only recieve a new lap if they've travelled so far around the racetrack

if(node2 > 10){my.lap_next = 0; my.lap_ready = 1; lappers = 1;}
if(lappers == 1)&&(node2 == 1){lappers = 0; my.kartlap += 2;}

Basically, when node2(the nodes of the mainpath) equals "1"(the first one, where you start out), it adds to my.kartlap.

- Finally, this code works much better if you have even more nodes in your path(50+). This is all relative too your racetrack size of course.
But i'd reccomend putting less nodes at first, then simply splitting up each edge. It's much much faster then putting a wad of nodes in one by one.
The code basically counts the nodes, and then splits the distances between the nodes(if your tied with an A.I kart). It also works well with multiplayer.
But that's a bit too complex to post right now(as you need to know how to properly set up client/server functions). Also, become familar with all
the path commands before using this. However, i'd assume you already are, as this would not work/be needed if you dont already have A.I racing around your
track by now.


Heres how to set up the code:

Put this above your player and A.I scripts(prolly in your globals script).

Code:
 
var NUM_KARTS = 8; //determines the amount of karts in a race(Used for the position calculations)
var create_1pp;//enable if playing in a level with no paths

define pplace, skill47; // contains the karts position in the race
define pnplace, skill48; // contains the amount of nodes the kart aquired
define pvplace, skill49; // used to figure out position
define lap_ready, skill51; //Misc. Used for laps
define lap_next, skill52;
define int_pos, skill53;




You'd call this loop for your players vehicle(not the A.I). It gathers how far the player has travelled. Also allows some backwards travel.

Code:
 
function position_loop()
{
var node2 = 1; // start at first node
var node3;
var node4;

var position2[3];
var position3[3];
var position4[3];
var position5[3];

var ii;
var lappers;

var p_addi; var v_addi; var v_add; var s_add; var b_add;
var s_time; var max_add; var n_mount; var b_addi; var f_add;

vec_set(position4.x, vector(1134,1359, -95000));
path_set(my,"path_003");
path_getnode(my,node2,position2.x,nullvector);
my.pnplace = 0;

while(1)
{
if(!create_1pp)
{
//if(s_time){if(s_add > v_add){max_add = s_add; my.pnplace = v_addi + s_add;} if(s_add < v_add){max_add = v_add; my.pnplace = v_addi + v_add;}}
//if(v_add == s_add){my.pnplace = v_addi + s_add;}
if(s_time){my.pnplace = v_addi + s_add + b_add;}

if(vec_to_angle(temp.pan, vec_diff(temp, position2.x, my.x)) < 2400) //Detects the main path + checks for divergence and backwards travel
{
if(s_time){s_add += 1;}else{v_add = 0; s_add = 0;}
my.pnplace += 1; node4 = node2 - 4; if(node4 < 0){node4 = -11;} path_getnode(my,node4,position5.x,null);
if(f_add == 1){my.pnplace += 8;} f_add = 0; b_add = 0;
vec_set(position3.x, position2.x);
path_getnode(my,node2,null,my.skill1);
if(my.skill3){my.pnplace = v_addi + n_mount; my.skill3 = 0; s_time = 0; s_add = 0; v_add = 0; v_addi = 0; b_add = 0;}
if(my.skill2){my.skill2 = 0; s_time = 1; node3 = path_nextnode(my,node2,2); p_addi = node3; v_addi = my.pnplace; path_getnode(my,node3,position4.x,nullvector); node2 = path_nextnode(my,node2,1); b_addi = node2;}
if(!my.skill2){node2 = path_nextnode(my,node2,1);}
path_getnode(my,node2,position2.x,my.skill1);
if(my.skill3){temp = node2 - b_addi; n_mount = temp + 1;}
}

if(vec_to_angle(temp.pan, vec_diff(temp, position4.x, my.x)) < 2400) //Detects the divergence path
{
if(s_time){v_add += 1;}else{v_add = 0; s_add = 0;}

my.pnplace += 1;
if(!my.skill2){node3 = path_nextnode(my,node3,1); path_getnode(my,node3,position4.x,my.skill1);}
if(my.skill2){my.pnplace += 1; s_time = 0; my.skill2 = 0; temp = node3 - p_addi; n_mount = temp + 2; node2 = path_nextnode(my,node3,1); path_getnode(my,node2,position2.x,nullvector); vec_set(position4.x, vector(3000,3000,-12000)); }
}
//backwards travel code, ommited for now...
/* if(vec_to_angle(temp.pan, vec_diff(temp, position5.x, my.x)) < 2400) //Detects backwards travel
{
if(s_time){b_add = -8;}else{b_add = 0;}
if(!s_time){f_add = 1; my.pnplace = node4 - 4;}
}*/

my.pvplace = my.pnplace; my.pvplace *= my.kartlap + 1; //Split the distance up if vehicles have the same amount of nodes
ii = vec_dist(my.x,position2.x)/vec_dist(position3.x,position2.x);
ii /= 25;
ii = clamp(ii,0,1);
my.pvplace -= ii;

if(node2 > 10){my.lap_next = 0; my.lap_ready = 1; lappers = 1;}
if(lappers == 1)&&(node2 == 1){lappers = 0; my.kartlap += 2;}

//Calculate Positions
if(kart_ready == 1){compute(); kart1.pplace = getkartpos(1);} //calculate the karts positions, my.pplace is your position(from 1-8).


//This puts up your 1st-8th place panel. According to your placement.
if(kart1){if(kart1.pplace == 1){avatar1.bmap = 1ki;}if(kart1.pplace == 2){avatar2.bmap = 1ki;}if(kart1.pplace == 3){avatar3.bmap = 1ki;}if(kart1.pplace == 4){avatar4.bmap = 1ki;}}
if(kart2){kart2.pplace = getkartpos(2); if(kart2.pplace == 1){avatar1.bmap = 2ki;}if(kart2.pplace == 2){avatar2.bmap = 2ki;}if(kart2.pplace == 3){avatar3.bmap = 2ki;}if(kart2.pplace == 4){avatar4.bmap = 2ki;}}
if(kart3){kart3.pplace = getkartpos(3); if(kart3.pplace == 1){avatar1.bmap = 3ki;}if(kart3.pplace == 2){avatar2.bmap = 3ki;}if(kart3.pplace == 3){avatar3.bmap = 3ki;}if(kart3.pplace == 4){avatar4.bmap = 3ki;}}
if(kart4){kart4.pplace = getkartpos(4); if(kart4.pplace == 1){avatar1.bmap = 4ki;}if(kart4.pplace == 2){avatar2.bmap = 4ki;}if(kart4.pplace == 3){avatar3.bmap = 4ki;}if(kart4.pplace == 4){avatar4.bmap = 4ki;}}
if(kart5){kart5.pplace = getkartpos(5); if(kart5.pplace == 1){avatar1.bmap = 5ki;}if(kart5.pplace == 2){avatar2.bmap = 5ki;}if(kart5.pplace == 3){avatar3.bmap = 5ki;}if(kart5.pplace == 4){avatar4.bmap = 5ki;}}
if(kart6){kart6.pplace = getkartpos(6); if(kart6.pplace == 1){avatar1.bmap = 6ki;}if(kart6.pplace == 2){avatar2.bmap = 6ki;}if(kart6.pplace == 3){avatar3.bmap = 6ki;}if(kart6.pplace == 4){avatar4.bmap = 6ki;}}
if(kart7){kart7.pplace = getkartpos(7); if(kart7.pplace == 1){avatar1.bmap = 7ki;}if(kart7.pplace == 2){avatar2.bmap = 7ki;}if(kart7.pplace == 3){avatar3.bmap = 7ki;}if(kart7.pplace == 4){avatar4.bmap = 7ki;}}
if(kart8){kart8.pplace = getkartpos(8); if(kart8.pplace == 1){avatar1.bmap = 8ki;}if(kart8.pplace == 2){avatar2.bmap = 8ki;}if(kart8.pplace == 3){avatar3.bmap = 8ki;}if(kart8.pplace == 4){avatar4.bmap = 8ki;}}
}

//This puts up your 1st-4th place panels. According to your placement and A.I. Think of the players pics in mariokart... somethign like that
ppp1.visible = off; ppp2.visible = off; ppp3.visible = off; ppp4.visible = off; ppp5.visible = off; ppp6.visible = off; ppp7.visible = off; ppp8.visible = off;
if(my.pplace == 1){ppp1.visible = on;} if(my.pplace == 2){ppp2.visible = on;} if(my.pplace == 3){ppp3.visible = on;}
if(my.pplace == 4){ppp4.visible = on;} if(my.pplace == 5){ppp5.visible = on;} if(my.pplace == 6){ppp6.visible = on;}
if(my.pplace == 7){ppp7.visible = on;} if(my.pplace == 8){ppp8.visible = on;}
wait(1);
}
}




You'd call this loop for each of your A.I vehicles, it gathers how far the A.I has travelled.

Code:
 
function aiposition_loop()
{
var node = 1; // start at first node
var node2 = 1; // start at first node
var node3;

var position[3];
var position2[3];
var position3[3];
var position4[3];
var pposition[3];

var ii;
var lappers;

var p_addi; var v_addi; var b_addi; var v_add;
var s_add; var s_time; var max_add; var n_mount;

path_set(my,"path_003");
path_getnode(my,node2,position2.x,nullvector);
my.pnplace = 0;

while(1)
{
path_set(my,"path_003");

//if(s_time){if(s_add > v_add){max_add = s_add; my.pnplace = v_addi + s_add;} if(s_add < v_add){max_add = v_add; my.pnplace = v_addi + v_add;}}
//if(v_add == s_add){my.pnplace = v_addi + s_add;}
if(s_time){my.pnplace = v_addi + s_add;}

if(vec_to_angle(temp.pan, vec_diff(temp, position2.x, my.x)) < 2400) //add nodes
{
if(s_time){s_add += 1;}else{v_add = 0; s_add = 0;}
my.pnplace += 1;

vec_set(position3.x, position2.x);
path_getnode(my,node2,null,my.skill1);
if(my.skill3){my.pnplace = v_addi + n_mount; my.skill3 = 0; s_time = 0; s_add = 0; v_add = 0; v_addi = 0;}
if(my.skill2){my.skill2 = 0; s_time = 1; node3 = path_nextnode(my,node2,2); p_addi = node3; v_addi = my.pnplace; path_getnode(my,node3,position4.x,nullvector); node2 = path_nextnode(my,node2,1); b_addi = node2;}
if(!my.skill2){node2 = path_nextnode(my,node2,1);}
path_getnode(my,node2,position2.x,my.skill1);
if(my.skill3){temp = node2 - b_addi; n_mount = temp + 1;}
}

if(vec_to_angle(temp.pan, vec_diff(temp, position4.x, my.x)) < 2400) //add nodes
{
if(s_time){v_add += 1;}else{v_add = 0; s_add = 0;}

my.pnplace += 1;
if(!my.skill2){node3 = path_nextnode(my,node3,1); path_getnode(my,node3,position4.x,my.skill1);}
if(my.skill2){my.pnplace += 1; s_time = 0; my.skill2 = 0; temp = node3 - p_addi; n_mount = temp + 2; node2 = path_nextnode(my,node3,1); path_getnode(my,node2,position2.x,nullvector); vec_set(position4.x, vector(3000,3000,-12000)); }
}

my.pvplace = my.pnplace; my.pvplace *= my.kartlap + 1;
ii = vec_dist(my.x,position2.x)/vec_dist(position3.x,position2.x);
ii /= 25;
ii = clamp(ii,0,1);
my.pvplace -= ii;

if(node2 > 10){my.lap_next = 0; my.lap_ready = 1; lappers = 1;}
if(lappers == 1)&&(node2 == 1){lappers = 0; my.kartlap += 2;}

wait(1);
}
}




Put this below your player and A.I scripts. A special thanks to Rhuarc for helping me out with the sorting seen here.

Code:
 
define MAX_KARTS,8;

var kartpositions[MAX_KARTS];
var kartnums[MAX_KARTS];

function clearstack()
{
var i;
while(i<MAX_KARTS)
{
kartpositions[i]=-1;
kartnums[i]=-1;
i+=1;
}
}

function pushkartpos(kartnum,position)
{
var i;
while(i<NUM_KARTS)
{
if(kartpositions[i]==-1) //hit the end of the used stack
{
kartpositions[i] = position;
kartnums[i] = kartnum;
return;
}
if(position>kartpositions[i] && kartpositions[i]!=-1)
{
var j; j=6;
while(j>=i)
{
kartpositions[j+1]=kartpositions[j];
kartnums[j+1] = kartnums[j];
j-=1;
}
kartpositions[i]=position;
kartnums[i] = kartnum;
return;
}
i+=1;
}
}

function compute() //singleplayer
{
clearstack();
var i;
if(NUM_KARTS>0){pushkartpos(1,kart1.pvplace);}
if(NUM_KARTS>1){pushkartpos(2,kart2.pvplace);}
if(NUM_KARTS>2){pushkartpos(3,kart3.pvplace);}
if(NUM_KARTS>3){pushkartpos(4,kart4.pvplace);}
if(NUM_KARTS>4){pushkartpos(5,kart5.pvplace);}
if(NUM_KARTS>5){pushkartpos(6,kart6.pvplace);}
if(NUM_KARTS>6){pushkartpos(7,kart7.pvplace);}
if(NUM_KARTS>7){pushkartpos(8,kart8.pvplace);}
}

function getkartpos(kartnum)
{
var i;
while(i<NUM_KARTS)
{
if(kartnums[i]==kartnum)
{
return(i+1); //i starts at 0, so increase it to 1 for 1st place
}
i+=1;
}
return(-1); //error for some reason.
}



I'm assuming that each of your vehicles have it's own unique pointer(as seen above, kart1-kart8). As well, reserve skills 1-6 of your vehicle for the
paths. Have fun!

Note: This code also contains a small part which makes your panels visible. I didn't include the code for the panels&bitmaps.

Edit: I noticed the backwards travel code is causing some bugs... omitted it.

/*
if(vec_to_angle(temp.pan, vec_diff(temp, position5.x, my.x)) < 2400) //add nodes
{
if(s_time){b_add = -8;}else{b_add = 0;}
if(!s_time){f_add = 1; my.pnplace = node4 - 4;}

//if(my.skill3){beep();s_time = 0; s_add = 0; v_add = 0; v_addi = 0;}
//if(my.check_p){my.pnplace = checkpoint; my.check_p = 0;}
}*/

Re: Dynamic positioning for racing games. [Re: William] #80774
07/09/06 00:54
07/09/06 00:54
Joined: Aug 2005
Posts: 1,185
Ukraine
Lion_Ts Offline
Serious User
Lion_Ts  Offline
Serious User

Joined: Aug 2005
Posts: 1,185
Ukraine
Thank You, William!
I don't need code for racing game right now, but I like to teach myself with interesting stuff like yours.

P.S.
"...store this somewhere on my hardrive for future use anyways..."

Re: Dynamic positioning for racing games. [Re: Lion_Ts] #80775
07/09/06 06:53
07/09/06 06:53
Joined: Aug 2001
Posts: 2,320
Alberta, Canada
William Offline OP
Expert
William  Offline OP
Expert

Joined: Aug 2001
Posts: 2,320
Alberta, Canada
Yeah, it's a good idea to store all kinds of code on your computer. If your not doing a racing game, the sorting code might come in handy. It basically takes in each players data, sorts numbers from highest to lowest, then relates the position calculated in the stack back to each player. This can come in handy to count all kind of position related things, like each players kills(in a DM game), flag captures for more than 2 teams, ect.

Re: Dynamic positioning for racing games. [Re: William] #80776
07/09/06 21:12
07/09/06 21:12
Joined: Aug 2005
Posts: 1,185
Ukraine
Lion_Ts Offline
Serious User
Lion_Ts  Offline
Serious User

Joined: Aug 2005
Posts: 1,185
Ukraine
Yep, You are right!
Thanks for sharing your work.


Moderated by  adoado, checkbutton, mk_1, Perro 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1