Mario Kart clone animation problem

Previous topic - Next topic

Wampus

Thought it would be fun today to do some tests to see what it might take to make a clone of the Super Mario Kart battle mode (and only battle mode). Ideally I would want such a thing to be playable on slow computers with the possibility, if all goes well, of making it playable over a LAN network. So far I've been playing around with perspective and map reading/rendering. Next I want to work on player movement but before I got to that I ran into a problem I can't seem to resolve.

In the original Super Mario Kart the maps themselves were animated; water and lava for example. I'm not sure how that was achieved but I'm getting what you can see here: -



...by drawing the map as 1024 x 1024 textures on four 3D objects surrounded by grass large textures for boundaries. Doing this is very fast even on my netbook. However, I've tried two ways to animate the map without success:-

1) I tried to convert every map tile into an individual 3D object that could be animated with X_SETTEXTUREOFFSET. That meant 16384 3D objects just for the map. It wasn't possible. The app crashed whenever I got somewhere between the 4000 to 5000 objects range.

2) I tried to make all four large textures for the map as screens I could write the map tiles to each frame. Using CREATESCREEN and USESCREEN seems ideal for this. That worked but on my netbook I saw the framerate go from 150-180 FPS to 1-2 FPS. So, I can't use that either.

Any suggestions about how I could overcome this problem? I've thought about just having pre-animated textures all at 1024 x 1024 size but that seems inelegant and slow. 64 1024x1024 textures to achieve what the SNES mode 7 could do on the fly? Dunno...seems excessive.

erico

I´m not a pro but...

What if you have you map on a 2d array (that you could read from a data statement).
Then you use this array to paste blocks of gfx(128x128) to create a 2d image of the map.
Get this image on a distorted plane. display

if this can be done on the fly on a slow comp with a huge map, it would be fine, if not, you could try to check players position on the 2d array and display/create screen only what is visible for him, lets say a triangle from his position and facing.

I´m not sure I´m making any sense, but helping is the first amendment :)

looks great so far.

EDIT: Mario??? oh that is so cheeesy, go for xtreme racing! hehe

quangdx

The problem is the mode 7 effect is done with hardware and tiles,
where as the drawing system on GLBasic is not.
This is how the SNES could do it on the fly, you would create a background image built up of tiles, 128x128 tiles,
and the mode 7 would skew it,
by changing the tiles, you would get your animation, as it redrew the background image and skewed it each frame.

Unfortunately to do the equivalent in GLBasic is quite processor intensive.
Redrawing 128x128 (16384) tiles each frame is a helluva lot.
You're better of doing as erico suggests, work out what part of the map is in view,
and only redraw that, almost like a flat raycaster.

http://en.wikipedia.org/wiki/Mode_7
Asobi tech - the science of play.
Spare time indiegame developer.

erico

128x128 sprites may even be too much, you could easily pass with less.
keep it up! :)

Slydog

#4
I would use a tile map, with an integer for all possible tile types (ie: grass=1, road=2, lava=3, etc).
Sample:
11111113
12222213
12131213
12222211
13331111

In my 3D maze, I pre-create all possible 'tiles' ahead of time.
Then to display the maze, I figure out the view bounds (don't draw every 3D 'tile' each frame, only the ones in player's view radius) first.
Then step through my maze/map array (3D array) and draw the 3D tile corresponding to that array location.
The same 3D tile (pre-generated 3D model) is used multiple times in the maze (ie. all left-up corners), and therefore used multiple times per frame.
You don't need a unique 3d model for each unique location if they are the same shape.

So you could try pre-generating the animation tiles (say lava), each animation frame would only be one quad, and sharing the same texture atlas, you would set each 'frame' to point to different portions of the sprite for the animation effect.  Then have a global animation frame counter and when you draw your map and you need to draw a lava tile, pick the one for the current animation frame.
I hope this makes sense.

Here's my entire, unedited 'DrawMap' routine for reference:
Code (glbasic) Select
FUNCTION Level_DrawMap:
LOCAL x%, y%, z%,   x1%, y1%, z1%,   x2%, y2%, z2%,   bx%, by%, bz%
ALIAS p AS _player.location
ALIAS v AS _player.view_radius
bx = level.size.x
by = level.size.y
bz = level.size.z

x1 = p.x - v.x; IF x1 < 0  THEN x1 = 0
x2 = p.x + v.x; IF x2 > bx THEN x2 = bx
y1 = p.y - v.y; IF y1 < 0  THEN y1 = 0
y2 = p.y + v.y; IF y2 > by THEN y2 = by
z1 = p.z - v.z; IF z1 < 0  THEN z1 = 0
z2 = p.z + v.z; IF z2 > bz THEN z2 = bz

X_SETTEXTURE sp_tiles, -1//sp_tiles_b
ALPHAMODE 0//-1.0
FOR y = y1 TO y2
FOR z = z1 TO z2
FOR x = x1 TO x2
ALIAS tile AS level.map[y][z][x]
IF tile <= 0 THEN CONTINUE

// DRAW NODE
X_MOVEMENT x, y-0.001, z
X_DRAWOBJ maze_parts[OBJ_XX].id, 0


// NORTH EVEN?
IF bAND(tile, MAP_ND) = MAP_NH
X_MOVEMENT x, y-0.001, z-0.0
X_DRAWOBJ maze_parts[OBJ_BE].id, 0
ENDIF

// NORTH UP?
IF bAND(tile, MAP_ND) = MAP_NU
X_MOVEMENT x, y-0.001, z-0.0
X_DRAWOBJ maze_parts[OBJ_BS].id, 0
ENDIF

// NORTH DOWN?
IF bAND(tile, MAP_ND) = MAP_ND
X_MOVEMENT x, y-1.001, z-2.0
X_ROTATION 180, 0, 1, 0
X_DRAWOBJ maze_parts[OBJ_BS].id, 0
ENDIF


// EAST EVEN?
IF bAND(tile, MAP_ED) = MAP_EH
X_MOVEMENT x+0.0, y-0.001, z
X_ROTATION 270, 0, 1, 0
X_DRAWOBJ maze_parts[OBJ_BE].id, 0
ENDIF

// EAST UP?
IF bAND(tile, MAP_ED) = MAP_EU
X_MOVEMENT x+0.0, y-0.001, z
X_ROTATION 270, 0, 1, 0
X_DRAWOBJ maze_parts[OBJ_BS].id, 0
ENDIF

// EAST DOWN?
IF bAND(tile, MAP_ED) = MAP_ED
X_MOVEMENT x+2.0, y-1.001, z
X_ROTATION 90, 0, 1, 0
X_DRAWOBJ maze_parts[OBJ_BS].id, 0
ENDIF

NEXT
NEXT
NEXT
ENDFUNCTION


[Edit] To see what I'm talking about, here's a forum post with an early screenshot of my game.
Each frame I choose what 'pieces' to place on the screen to create the maze in memory.
http://www.glbasic.com/forum/index.php?topic=1335.msg42337#msg42337
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Wampus

Thanks for the great suggestions & feedback. :booze:

I tried Slydog's method of tiling, which was a lot more efficient than my attempt before of creating 16384 identical objects and copying from a separate texture atlas each tile! Or creating whole new 1024x1024 textures each frame! Unfortunately even the improvement with Slydog's method was resulting in low FPS; on my faster system too. The amount of map that is shown at any one time in a SMK battle map is so troublesome. I tried restricting the number of tiles loosely based on player view but even in better than average circumstances the FPS was too low.

If I really want to keep animation and super-fast FPS I could just bust the texture resolution down to the original SNES game, for that truly nostalgic old school look.  :-[

BUT! For now, until I'm a little better acquainted with the X_ functions, I'm going to try to complete a simple 3D horror game instead - something that would better suit what I can do. Officially I'm meant to be sick atm  :sick: but not so bad that I can't code. I reckon I can justify another day just coding for fun.