Gamestudio Links
Zorro Links
Newest Posts
Trading Journey
by howardR. 04/28/24 09:55
basik85278
by basik85278. 04/28/24 08:56
Zorro Trader GPT
by TipmyPip. 04/27/24 13:50
Help with plotting multiple ZigZag
by M_D. 04/26/24 20:03
Data from CSV not parsed correctly
by jcl. 04/26/24 11:18
M1 Oversampling
by jcl. 04/26/24 11:12
Why Zorro supports up to 72 cores?
by jcl. 04/26/24 11:09
Eigenwerbung
by jcl. 04/26/24 11:08
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
0 registered members (), 744 guests, and 5 spiders.
Key: Admin, Global Mod, Mod
Newest Members
wandaluciaia, Mega_Rod, EternallyCurious, howardR, 11honza11
19049 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Page 1 of 2 1 2
SNES Mode-7 #406103
08/13/12 21:05
08/13/12 21:05
Joined: Apr 2008
Posts: 139
Japan, Osaka
Tails01 Offline OP
Member
Tails01  Offline 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

Code:
// 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 Offline
Expert
ratchet  Offline
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 laugh ?
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 Offline
Expert
Error014  Offline
Expert

Joined: Jul 2002
Posts: 3,208
Germany
Ah, thats neat! laugh

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. laugh

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 Offline OP
Member
Tails01  Offline 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
Quote:
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 frown .

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 Offline
Expert
Hummel  Offline
Expert

Joined: Mar 2006
Posts: 2,252
Quote:
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: Hummel] #406142
08/14/12 12:45
08/14/12 12:45
Joined: Jul 2001
Posts: 6,904
H
HeelX Offline
Senior Expert
HeelX  Offline
Senior Expert
H

Joined: Jul 2001
Posts: 6,904
This is great, thanks for sharing. Maybe you could use the power of HLSL shaders to make it faster, on the GPU?

Re: SNES Mode-7 [Re: HeelX] #406149
08/14/12 14:31
08/14/12 14:31
Joined: Jul 2008
Posts: 2,107
Germany
rayp Offline

X
rayp  Offline

X

Joined: Jul 2008
Posts: 2,107
Germany
Really cool. Thank you for sharing.


Acknex umgibt uns...zwischen Dir, mir, dem Stein dort...
"Hey Griswold ... where u gonna put a tree that big ?"
1998 i married my loved wife ... Sheeva from Mortal Kombat, not Evil-Lyn as might have been expected
rayp.flags |= UNTOUCHABLE;
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 Offline OP
Member
Tails01  Offline 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 Offline
Expert
Error014  Offline
Expert

Joined: Jul 2002
Posts: 3,208
Germany
Hey, thank you for the video! laugh It does remind me a lot of those old, tropical-themed SNES-Mario Kart tracks. Koopa Troopa Beach, or what was it called? laugh


performance-wise, in this line:

Code:
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 Offline OP
Member
Tails01  Offline 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.
Page 1 of 2 1 2

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