Archived

This topic is now archived and is closed to further replies.

robertgamble

Billboarding in Mario Kart style game..?

Recommended Posts

robertgamble    122
I''m working on a Mario Kart/"Mode 7" style game for the GP32 handheld, and javascript (using javascript as a "testbed" so that I don''t have to keep recompiling and uploading each time I change something). An old javascript version is available here: http://www.elephantsneverforget.co.uk/mode7.asp (wasd to move around), it''s pretty slow but runs great on the GP32 (60fps at 40Mhz). At the moment you can drive around, the graphics look ok and there''s some collision detection. However I can''t work out how to draw cars/trackside objects etc.. At first I was drawing the car with raycasting.. E.g when I draw a pixel on the floor check if the ray coordinates match the car coordinates. But that was very slow, and didn''t seem like the right way of doing it... I was thinking that a better way would be to transform & project the coordinates and then draw the objects as point sprites. But I''m unsure of how to get this "in sync" with whats being drawn by the floorcaster. So what is the best way of doing this? Any help would be greatly appreciated.

Share this post


Link to post
Share on other sites
vember    122
Use the inverse of the matrix you''re using for the transformation between the screen-cordinates and the mode7-plane.

I suspect though that the current transformation isn''t in matrix form though so you have to translate it to that first.

good luck,
-claes

Share this post


Link to post
Share on other sites
Nik02    4348
The said matrix consists from the perspective division, rotation in y-axis (camera direction in ground plane), and rotation in x-axis(the "camera height" angle).
You already have all this information when drawing the ground, just use the inverse to project any points from the "floor space" to screen space.

rgds Nik

PS. sorry for late reply

[edited by - Nik02 on September 4, 2003 3:15:05 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Just had a look at your algorithm. You''re doing it wrong, to get this fast you should only cast rays at the left and right sides of the screen, and then linearly interpolate texture coordinates across.

Share this post


Link to post
Share on other sites
robertgamble    122
quote:
Original post by Anonymous Poster
Just had a look at your algorithm. You''re doing it wrong, to get this fast you should only cast rays at the left and right sides of the screen, and then linearly interpolate texture coordinates across.


I''ve had a go at adding interpolation, for now I''m interpolating between the top of each column to the bottom like this:-


//get top of the floor area
var RAYX1 = (p.x + (FloorDist[100] * cos[angle]) - Sof)>>19;
var RAYY1 = (p.y - (FloorDist[100] * sin[angle]) - Cof)>>19;

//get bottom of the floor area
var RAYX2 = (p.x + (FloorDist[240] * cos[angle]) - Sof)>>19;
var RAYY2 = (p.y - (FloorDist[240] * sin[angle]) - Cof)>>19;

//start drawing everything
do{
t=(i-100)/140; //work out how the position in the line
RAYX=(RAYX1+ ((RAYX2-RAYX1) *t)); //get the interpolated coords
RAYY=(RAYY1+ ((RAYY2-RAYY1) *t));

...carry on as normal


...however it doesn''t seem to work too well. Take a look at http://www.elephantsneverforget.co.uk/mode7.htm, it''s very distorted. I think the line "t=(i-100)/140" might be wrong, but I''ve never done any interpolation before so I don''t know how to fix it..

Share this post


Link to post
Share on other sites
Neoteric    122
Looks like you're interpolating top to bottom on screen coordinates, that's non-linear. Interpolation is linear left to right like this.


L-Ray R-Ray
\ /
........... <- Interpolated texture coordinates.
\ /
.......
\ /
.


Some dodgy old code of mine, it's setup for arbritrary size textures but changing it to a bit shift division is easy enough.


for(int x=0; x<half_height;x++)
{
//far left floor ray

floor_dist = Math.abs(world_height/(Math.cos(floor_ray_ang
* radian_conv)));
sx = (floor_dist * Math.cos(left_ang));
sy = (floor_dist * Math.sin(left_ang));

//far right floor ray

floor_dist = Math.abs(world_height/(Math.cos(floor_ray_ang
* radian_conv)));
fx = (floor_dist * Math.cos(right_ang));
fy = (floor_dist * Math.sin(right_ang));

//interpolation values

dx = (fx-sx)/screen_width; dy = (fy-sy)/screen_width;
u = sx; v = sy;

//plot floor and ceiling

for (int j = 0; j<screen_width;j++)
{
mu = (int)Math.abs((u+p1.getPlayerX()) % 200);
mv = (int)Math.abs((v-p1.getPlayerY()) % 200);
pixels[p_index++] = ((255<<24) | (Tex1[2][mu][mv]<<16) | (Tex1[2][mu][mv]<<8) | Tex1[0][mu][mv]<<0);
pixels[p2_index++] = ((255<<24) | (Tex1[2][mu][mv]<<16) | (Tex1[2][mu][mv]<<8) | Tex1[0][mu][mv]<<0);
u+=dx;v+=dy;
}

//increment angle

p2_index-=(screen_width*2); floor_ray_ang+=angstep;
}


Remember to keep divisions out of the innter loops.


[edited by - Neoteric on September 10, 2003 3:01:09 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Neoteric, with that suggestion it''s interesting that you do in fact have two divisions in your inner loop. The % operator does a division. Use & and power-of-two sized maps instead

Share this post


Link to post
Share on other sites
Neoteric    122
quote:
Original post by Anonymous Poster
Neoteric, with that suggestion it's interesting that you do in fact have two divisions in your inner loop. The % operator does a division. Use & and power-of-two sized maps instead


Yeah I edited that in 5 seconds too late. The project needed any size textures for arrangements of tiling (which never got put in) so I was going to move the mods into a look up table, never got around to it.



[edited by - Neoteric on September 10, 2003 3:25:23 PM]

Share this post


Link to post
Share on other sites
robertgamble    122
Neoteric, thanks for your example it was very helpful

I''ve got it kind of working now, the only problem is if you move left or right it starts to get distorted. http://www.elephantsneverforget.co.uk/mode7b.htm

I think it''s how I''m working out the angle, how are you working out floor_ray_ang and angstep in your program?

Thanks for your help

Share this post


Link to post
Share on other sites
Neoteric    122
Ray-ang step is 45 degrees / screen_height.


/
/
/
o ___________________ <-- line of sight
z \
| \
___|___\________________ <-- intersection on floor
\
\
\ <==90 degree FOV / 2 = 45 / screen_height =
interpolattion_between_hight_&_low_scanlines



I don''t think that''s the problem though, left_ang and right_ang seem to be going wrong. Hope that helps.

Share this post


Link to post
Share on other sites
robertgamble    122
Doesn''t seem to be anything wrong with left_ang and right_ang, unless I''m missing something.. It almost looks like I''m getting radians & degrees mixed up somewhere, but that shouldn''t happen as I''m using luts for the trig functions...

Share this post


Link to post
Share on other sites
robertgamble    122
Sorted it, the interpolation increments were being calculated wrong. Shouldn''t be using the absolute value, as it was causing the ray to always go up,right when it shouldn''t.

Thanks for your help with this, it seems faster now and hopefully I''ll get a nice boost in the GP32 version

Share this post


Link to post
Share on other sites
robertgamble    122
I''m still having trouble transforming and projecting the coordinates for cars and trackside objects though

this is how did tranform / projection in my proper 3d thing:-


while(curVect //project, draw and transform this vector
distanceZ=(dspList[curObj].faces[curFace].points[curVect].z+dspList[curObj].z)-this.z;
distanceX=(dspList[curObj].faces[curFace].points[curVect].x+dspList[curObj].x)-this.x;
distanceY=(dspList[curObj].faces[curFace].points[curVect].y+dspList[curObj].y)-this.y;

ntY = parseInt(distanceY*cos[this.xa] - distanceZ*sin[this.xa])
ndistance = parseInt(distanceZ*cos[this.xa] + distanceY*sin[this.xa])

distanceY=ntY;
distanceZ=ndistance

ndistance = parseInt(distanceZ*cos[this.ya]) - (distanceX*sin[this.ya])
ntX = parseInt(distanceX*cos[this.ya]) + (distanceZ*sin[this.ya])

distanceZ=ndistance
distanceX=ntX

ntX = parseInt(distanceX*cos[this.za]) - (distanceY*sin[this.za])
ntY = parseInt(distanceY*cos[this.za]) + (distanceX*sin[this.za])

distanceX=ntX;
distanceY=ntY;
distanceZ+=0.001;


tmpvec[curVect]=new vector3D();
tmpvec[curVect].z=distanceZ;
tmpvec[curVect].x=(lens*distanceX/distanceZ)+viewarea.centerx;
tmpvec[curVect].y=viewarea.centery-(lens*distanceY/distanceZ);
curVect++;
}


I think I understand how to transform the coordinates, but not how to project them without a Z coordinate.. bah! Do you know of any simple open source games/demos that do this, it would be nice to see an example..

Share this post


Link to post
Share on other sites