0 registered members (),
1,397
guests, and 7
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
SNES Mode-7
#406103
08/13/12 21:05
08/13/12 21:05
|
Joined: Apr 2008
Posts: 139 Japan, Osaka
Tails01
OP
Member
|
OP
Member
Joined: Apr 2008
Posts: 139
Japan, Osaka
|
SNES MODE 7 examples:FZERO 1990 (c)Nintendo MARIO KART 1992 (c)Nintendo Do you remember these times Almost no one reminds himself back to the beginning of 3d, where everthing starts with a stretched plane that simulated a 3d-space mixed with some nice painted sprites.But if you want to inform yourself about the "making of" you only meet faulty or incomplete code. So I've decided to publish a version of mine here. For those who doesn't know what Mode-7 actually is. MODE 7 WIKIPEDIA^^ I hope the lines are well commented and I hope you guys have some fun with it. Maybe I hand in the mathematical part later, it's to hard to explain it in engl. PS. some feedback would be nice and some hints about performance-improvement. Thanks
// Pseudo-Mode-7!
/* written in August 2012 by Tommy - "tommy.draeger@googlemail.com" */
#include <acknex.h>
#include <litec.h>
#define xres 320
#define yres 240
BMAP* blank_16;
BMAP* blank_32;
BMAP* sphere = "...";
BMAP* displace = "...";
BMAP* background = "...";
PANEL* framebuffer = { layer = 10; flags = VISIBLE; }
PANEL* framedepth = { layer = 11; flags = VISIBLE; }
PANEL* obj_01 = { layer = 12; flags = VISIBLE | OVERLAY; bmap = sphere; }
function mode_7_level(BMAP* screen, BMAP* source, BMAP* distfog, BMAP* backdrop);
function mode_7_sprite(PANEL* sprite,int px, int py, float obj_dir, float obj_org);
typedef struct /* MODE 7 SETTINGS */
{
int foclength;//FOCALLENGTH
int horizon;
int scale;//SCALEFACTOR FOR LEVELGROUND
int obj_scale;//SCALEFACTOR FOR SPRITES
}M7_OPT;
//THESE ARE VALUES THAT WORKS FINE FOR
//ME AT A RESOLUTION OF 320 X 240
M7_OPT* m7 =
{
foclength = 400;
horizon = 80;
scale = 60;
obj_scale = 15;
}
float angle = 0;
float xOffset = 0;
float yOffset = 0;
//SCREEN AND DISTFOG ARE THE BMAPS
//TO DRAW ON. THE OTHERS SERVES AS
//LEVELGROUND AND SKYBACKDROP
function mode_7_level(BMAP* screen, BMAP* source, BMAP* distfog, BMAP* backdrop)
{
fixed count;
DWORD blend;
int x,y;
//FRAME
int frm;
//JUST FOR PERFORMANCE IMPROVEMENT
int dx,dy;
int mask_x,mask_y;
int mask_x_backdrop;
float space_x, space_y, space_z;
float screen_x, screen_y;
float px, py, pz;
float sx, sy;
mask_x = bmap_width(source) -1;
mask_y = bmap_height(source) -1;
mask_x_backdrop = bmap_width(backdrop) -1;
while(1)
{
//STEERING
angle += (key_cur - key_cul)*time_step / 15;
xOffset += (key_cuu - key_cud)*sin(angle)*time_step*8;
yOffset -= (key_cuu - key_cud)*cos(angle)*time_step*8;
bmap_lock(screen,4444);
bmap_lock(source,888);
bmap_lock(distfog,4444);
bmap_lock(backdrop,888);
for(y = -yres/2; y < yres/2; y++)
{
dy = y+yres/2;
//"BLEND" HOLDS THE ALPHAVALUE
//FOR THE DISTANCE-FOGGING
blend = ((dy)-60) * -100/110 - 10;
blend = clamp(blend,-100,0);
//JUST TO CREATE A NON-LINEAR EFFECT
//505 WAS DETERMINE BY ME
blend &= 505;
//MAKE A SLICE AT 70
//TO RENDER THE BACKDROP
if(y >= (-yres/2)+70)
{
for(x = -xres/2; x < xres/2; x++)
{
dx = x+xres/2;
/******* ACTUAL MODE 7 EFFECT ********/
//ASSIGN SOME TEMPVARS FOR
//A BETTER OVERVIEW
px = x;
py = y + m7.foclength;
pz = y + m7.horizon;
//MATHEMATICAL PROJECTION
//FOR TURNING A 3D POINT TO
//A 2D SCREENPIXEL
//Y STANDS FOR Z RESP. THE DEPTH
space_x = px / pz;
space_y = py / pz * -1;
//INVERT THE Y DIRECTION
//SO THAT EVERTHING IS
//IN A CORRECT WAY
//A TRIGONOMETRIC EQUATION TO BE ABLE
//TO ROTATE THE BMAP SO YOU CAN
//LOOK AROUND 360°
screen_x = space_x * cos(angle) - space_y * sin(angle);
screen_y = space_x * sin(angle) + space_y * cos(angle);
//FINAL TRANSFORMATION AND SCALING
sx = screen_x * m7.scale + xOffset;
sy = screen_y * m7.scale + yOffset;
//USE THE AND-OPERATOR TO CREATE AN INFINTIY-PATTERN
pixel_to_bmap(screen,dx,dy,pixel_for_bmap(source,(int)sx & mask_x,(int)sy & mask_y)+0x001200);
pixel_to_bmap(distfog,dx,dy,pixel_for_vec(vector(240,254,160),blend,8888));
/***************************************/
}
}
else
{
for(x = 0; x < xres; x++)
pixel_to_bmap(screen,x,dy,pixel_for_bmap(backdrop,(int)(x+angle*200) & mask_x_backdrop,dy));
}
}
//EVERYTIME YOU WANT TO ADD AN OBJECT YOU'VE
//TO PLACE A NEW MODE_7_SPRITE FUNCTION HERE
//IT'S PLACED HERE BECAUSE OF THE PERFORMANCE
mode_7_sprite(obj_01, 10 , -100 );
bmap_unlock(backdrop);
bmap_unlock(distfog);
bmap_unlock(source);
bmap_unlock(screen);
//THE NEXT LINES AREN'T NECESSARY
//THESE JUST CREATING AN ANIMATED
//WATERSURFACE, YOU CAN DELETE
//THESE IF YOU LIKE
//*******//
count += (int)4*time_step;
if(count > 10){count %= 10;frm++;}
if(frm >= 7)frm = 0; //if(frm == 7)frm %= 7; //frm &= 7;
switch(frm)
{
case 0:bmap_purge(source);
case 1:bmap_load(source,"...",0);
case 2:bmap_load(source,"...",0);
case 3:bmap_load(source,"...",0);
case 4:bmap_load(source,"...",0);
case 5:bmap_load(source,"...",0);
case 6:bmap_load(source,"...",0);
case 7:bmap_load(source,"...",0);
}
//*******//
wait(1);
}
}
function mode_7_sprite(PANEL* sprite, int px, int py, float obj_dir, float obj_org)
{
float width, height;
float space_x, space_y;
float screen_x, screen_y;
float obj_x = px + xOffset;
float obj_y = py - yOffset;
//EQUATIONS STANDS IN EVERY FORMULARY
float distance = sqrt(pow(obj_x,2)+pow(obj_y,2));
space_x = obj_x * cos(angle) - obj_y * sin(angle);
space_y = obj_x * sin(angle) + obj_y * cos(angle);
//SPACE_Y IS THE DEPTH
//IF YOU WANT TO REPRODUCE THESE EQUATION JUST LOOK
//FOR "MATHEMATICAL PROJECTION" RESP. "SIMILAR TRIANGLES"
screen_x = xres/2 + (space_x * m7.foclength) / space_y;
screen_y = (m7.foclength / space_y) + m7.horizon - 10;
//CALCULATE THE NEW HEIGHT:
//INVERSELY PROPORTIONAL TO THE
//DISTANCE
height = (m7.scale / distance);
width = (m7.scale / distance);
sprite.scale_x = width;
sprite.scale_y = height;
sprite.pos_x = screen_x - (width*sprite.size_x/2);
sprite.pos_y = screen_y + (height*sprite.size_y/2);
//JUST A SMALL SOLUTION FOR CULLING
//SO YOU DOESN'T SEE THE SPRITE TWICE
//CONVERT VECTOR TO +-180 ANGLE
vec_to_angle(obj_dir,vector(space_x,space_y,0));
vec_to_angle(obj_org,vector(px,py,0));
//CONVERT +-180 ANGLE TO 0...360 ANGLE
obj_dir = cycle(obj_dir,0,360);
obj_org = cycle(obj_org,0,360);
//DETERMINE WHETER THE OBJECT IS IN EYESIGHT
if(obj_dir > (obj_org - 90) && obj_dir < (obj_org + 90)) { sprite.flags |= VISIBLE; }
else { sprite.flags &= ~VISIBLE; }
return;
}
function main()
{
level_load("");
wait(2);
video_set(xres,yres,16,0);
//CREATE TWO BLANK BMAPS FOR THE SCREEN
//AND THE DISTANCE FOGGING (BECAUSE OF
//THE TRANSPERANTY WE WANT TO USE)
blank_16 = bmap_createblack(xres, yres, 16);
blank_32 = bmap_createblack(xres, yres, 32);
framebuffer.bmap = blank_16;
framedepth.bmap = blank_32;
//fps_max = 20;
mode_7_level(blank_16, displace, blank_32, background);
}
So this is what it looks like. ANIMATED VERSION DOWNLOAD Mode7_Example Gruß Tommy
Last edited by Tails01; 10/26/12 18:46.
An implemented second-rate idea is better than a good idea, which gathering dust in your brain.
|
|
|
Re: SNES Mode-7
[Re: Tails01]
#406106
08/13/12 21:43
08/13/12 21:43
|
Joined: Apr 2008
Posts: 2,488
ratchet
Expert
|
Expert
Joined: Apr 2008
Posts: 2,488
|
On PC with 3DGS ? No interest at all, or for fun programming only ? We have polygons, textures, shaders , why going back ? Perhaps some retro game in Minecraft style , but with racing features ?
|
|
|
Re: SNES Mode-7
[Re: ratchet]
#406112
08/13/12 22:12
08/13/12 22:12
|
Joined: Jul 2002
Posts: 3,208 Germany
Error014
Expert
|
Expert
Joined: Jul 2002
Posts: 3,208
Germany
|
Ah, thats neat! Don't have the time to test it, sadly. I know this is a lot to ask, but I'd love to see a video or animated gif from that nice, relaxing, vacation-like scene you have up there! Also, while I have no use for something like that at this point, thanks for contributing that! We need more people like you contributing what they've made. Do you plan on creating a game or something with that? Or was it a pure "just-for-fun"/learning exercise?
Perhaps this post will get me points for originality at least.
Check out Dungeon Deities! It's amazing and will make you happy, successful and almost certainly more attractive! It might be true!
|
|
|
Re: SNES Mode-7
[Re: Error014]
#406118
08/14/12 00:56
08/14/12 00:56
|
Joined: Apr 2008
Posts: 139 Japan, Osaka
Tails01
OP
Member
|
OP
Member
Joined: Apr 2008
Posts: 139
Japan, Osaka
|
@Error014 yepp, these mode is an sailing-extension for a 2D rpg-game that was allready finished. But now I want to enhance it a little bit more. Because this project was a qualifying examination, I'm not allowed to publish it yet. your requested animated scene @ratchet We have polygons, textures, shaders , why going back laugh ? Perhaps some retro game in Minecraft style , but with racing features ? I think 2d-games are very much underestimated. The choice of the appearance for a game it's a matter of taste, even if the majority only likes 3dimensional games . there isn't only the feature for racing, you can handle other effects with it too. think back of street fighter, where this technique was used to create an sidescroll-parralax, or in any other Jump'n'Run game.
An implemented second-rate idea is better than a good idea, which gathering dust in your brain.
|
|
|
Re: SNES Mode-7
[Re: Tails01]
#406120
08/14/12 05:29
08/14/12 05:29
|
Joined: Mar 2006
Posts: 2,252
Hummel
Expert
|
Expert
Joined: Mar 2006
Posts: 2,252
|
I think 2d-games are very much underestimated. The choice of the appearance for a game it's a matter of taste, even if the majority only likes 3dimensional games . I think what ratchet wanted say was that you can achieve the same results using modern technology (which is available anyway) at frame rates hundred times higher (srsly) with much less development effort. EDIT: Nahh, he probably didn't mean that...
|
|
|
Re: SNES Mode-7
[Re: rayp]
#406156
08/14/12 16:07
08/14/12 16:07
|
Joined: Apr 2008
Posts: 139 Japan, Osaka
Tails01
OP
Member
|
OP
Member
Joined: Apr 2008
Posts: 139
Japan, Osaka
|
I already thought there would be nobody how appreciate it.
An implemented second-rate idea is better than a good idea, which gathering dust in your brain.
|
|
|
Re: SNES Mode-7
[Re: Tails01]
#406159
08/14/12 18:04
08/14/12 18:04
|
Joined: Jul 2002
Posts: 3,208 Germany
Error014
Expert
|
Expert
Joined: Jul 2002
Posts: 3,208
Germany
|
Hey, thank you for the video! It does remind me a lot of those old, tropical-themed SNES-Mario Kart tracks. Koopa Troopa Beach, or what was it called? performance-wise, in this line:
switch(frm)
{
case 0:bmap_purge(source);
case 1:bmap_load(source,"...",0);
case 2:bmap_load(source,"...",0);
case 3:bmap_load(source,"...",0);
case 4:bmap_load(source,"...",0);
case 5:bmap_load(source,"...",0);
case 6:bmap_load(source,"...",0);
case 7:bmap_load(source,"...",0);
}
Do you actually reload the frame everytime you need it? In this case, I'd rather sacrifice some memory and load all frames in advance, and then just switch to the correct one (for instance, by using a BMAP*-array).
Perhaps this post will get me points for originality at least.
Check out Dungeon Deities! It's amazing and will make you happy, successful and almost certainly more attractive! It might be true!
|
|
|
Re: SNES Mode-7
[Re: Error014]
#406173
08/14/12 20:40
08/14/12 20:40
|
Joined: Apr 2008
Posts: 139 Japan, Osaka
Tails01
OP
Member
|
OP
Member
Joined: Apr 2008
Posts: 139
Japan, Osaka
|
@Error014 I've implemented your suggestion into action and sure you're right a BMAP*-array looks neater but it's doesn't speed up the framerate, even if I delete the switch-loop I got no more fps than 44fps.
An implemented second-rate idea is better than a good idea, which gathering dust in your brain.
|
|
|
|