fpc/packages/libndsfpc/examples/gl2d/2Dplus3D/2Dplus3D.pp
Legolas 659b386f02 + Added Easy gl2d library for Nintendo DS and 6 new examples
* libndsfpc: Fixed glMaterialShinyness()

git-svn-id: trunk@19932 -
2011-12-31 14:14:12 +00:00

332 lines
10 KiB
ObjectPascal

(*
Easy GL2D
Relminator 2011
Richard Eric M. Lope BSN RN
Http://Rel.Phatcode.Net
A very small, simple, yet very fast DS 2D rendering lib using the DS' 3D core.
--
Translated in Object Pascal by Francesco Lombardi - 2012
http://itaprogaming.free.fr
*)
program TwoDplusThreeD;
{$mode objfpc}
{$H+}
{$L build/flyer.o}
{$L build/shuttle.o}
{$L build/enemies.o}
{$L build/organ16.o}
uses
ctypes, nds9, gl2d, cearn_atan, vbuffer, uvcoord_enemies;
const
flyerBitmapLen = 2048;
flyerPalLen = 512;
shuttleBitmapLen = 2048;
shuttlePalLen = 32;
enemiesBitmapLen = 65536;
enemiesPalLen = 512;
organ16BitmapLen = 32768;
var
flyerBitmap: array [0..0] of cuint; cvar; external;
flyerPal: array [0..0] of cushort; cvar; external;
shuttleBitmap: array [0..0] of cuint; cvar; external;
shuttlePal: array [0..0] of cushort; cvar; external;
enemiesBitmap: array [0..0] of cuint; cvar; external;
enemiesPal: array [0..0] of cushort; cvar; external;
organ16Bitmap: array [0..0] of cuint; cvar; external;
const
// Mode7-like 3D effect parameters
GRID_RINGS: cint = 2;
GRID_BANDS: cint = 2;
GRID_WIDTH: cint = 15;
GRID_HEIGHT: cint = 12;
// PI for our binary radian measure
BRAD_PI = 1 shl 14;
var
// Our sprites
Enemies: array [0..ENEMIES_NUM_IMAGES-1] of glImage; // spriteset
Shuttle: array [0..0] of glImage; // single image
Flyer: array [0..0] of glImage; // single image
vb: PVertexBuffer;
EnemiesTextureID: cint;
ShuttleTextureID: cint;
FlyerTextureID: cint;
TextureSize: cint;
ox, oy: cint32;
Frame, PhoenixFrame, BeeFrame, Rotation: cint; // rotation value of the rotating sprites
x, y: cint;
sx, sy, angle: cint32;
// function to draw our mode7 fx
// draws 2 planes
// for a fake mode7 effect
procedure draw_grid();
const
text_off_u: cint32 = 0;
text_off_v: cint32 = 0;
frame: cint = 0;
begin
inc(frame);
glPushMatrix();
glLoadIdentity();
glTranslate3f32( 0, 0, floattof32(3.0) );
glScalef32(floattof32(1),floattof32(1.5),floattof32(1.5));
// floor
glPushMatrix();
glTranslate3f32( 0, -1 shl 12, -2 shl 12 );
glRotateXi( inttof32(244) );
vb^.render( text_off_u, text_off_v, true );
glPopMatrix( 1 );
// ceiling
glPushMatrix();
glTranslate3f32( 0, 1 shl 12, -2 shl 12 );
glRotateXi( inttof32(180) );
vb^.render( text_off_u ,text_off_v, true );
glPopMatrix( 1 );
glPopMatrix( 1 );
// "move" the floor and ceiling
text_off_u := (sinLerp(frame*30)*2) and 4095;
text_off_v := (sinLerp(-frame*50)*3) and 4095;
end;
begin
// Initialize fake mode7 planes
vb := init_grid (GRID_RINGS, GRID_BANDS, GRID_WIDTH, GRID_HEIGHT, 8, 8);
//set mode 5, enable BG0 and set it to 3D
videoSetMode(MODE_5_3D);
consoleDemoInit();
// initialize gl2d
glScreen2D();
//set up enough texture memory for our textures
vramSetBankA( VRAM_A_TEXTURE );
// Very Important!!! Or you get black sprites
vramSetBankE(VRAM_E_TEX_PALETTE); // Allocate VRAM bank for all the palettes
// Load our texture for our mode7 effect
vb^.load_texture( @organ16Bitmap );
// Load our Enemies texture
// We used glLoadSpriteSet since the texture was made
// with my texture packer.
EnemiesTextureID := glLoadSpriteSet(
Enemies, // pointer to glImage array
ENEMIES_NUM_IMAGES, // Texture packer auto-generated #define
@enemies_texcoords, // Texture packer auto-generated array
GL_RGB256, // texture type for glTexImage2D() in videoGL.h
TEXTURE_SIZE_256, // sizeX for glTexImage2D() in videoGL.h
TEXTURE_SIZE_256, // sizeY for glTexImage2D() in videoGL.h
GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T or TEXGEN_OFF or GL_TEXTURE_COLOR0_TRANSPARENT, // param for glTexImage2D() in videoGL.h
256, // Length of the palette to use (256 colors)
@enemiesPal, // Load our 256 color enemies palette
@enemiesBitmap // image data generated by GRIT
);
// Shuttle
// Since the shuttle is just a single 64x64 image,
// We use glLoadTileSet() giving the right dimensions.
ShuttleTextureID := glLoadTileSet(
Shuttle, // pointer to glImage array
64, // sprite width
64, // sprite height
64, // bitmap image width
64, // bitmap image height
GL_RGB16, // texture type for glTexImage2D() in videoGL.h
TEXTURE_SIZE_64, // sizeX for glTexImage2D() in videoGL.h
TEXTURE_SIZE_64, // sizeY for glTexImage2D() in videoGL.h
GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T or TEXGEN_OFF or GL_TEXTURE_COLOR0_TRANSPARENT,
16, // Length of the palette to use (16 colors)
@shuttlePal, // Load our 16 color Shuttle palette
@shuttleBitmap // image data generated by GRIT
);
// Flyer
FlyerTextureID := glLoadTileSet(
Flyer,
64,
64,
64,
64,
GL_RGB16,
TEXTURE_SIZE_64,
TEXTURE_SIZE_64,
GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T or TEXGEN_OFF or GL_TEXTURE_COLOR0_TRANSPARENT,
16, // Length of the palette to use (16 colors)
@flyerPal, // Load our 16 color Flyer palette
@flyerBitmap
);
// Print some console stuff
iprintf(#$1b'[1;1HEasy GL2D + 3D');
iprintf(#$1b'[2;1HRelminator');
iprintf(#$1b'[4;1HHttp://Rel.Phatcode.Net');
iprintf(#$1b'[6;1HA demo showing a very easy');
iprintf(#$1b'[7;1Hway to combine 3D and 2D');
iprintf(#$1b'[ 9;1HSprites by:');
iprintf(#$1b'[10;1H Adigun A. Polack and Patater');
iprintf(#$1b'[11;1HFixed Point atan2Lerp By Cearn');
iprintf(#$1b'[13;1HEnemiesTextureID = %i', EnemiesTextureID);
iprintf(#$1b'[14;1HFlyerTextureID = %i', FlyerTextureID);
iprintf(#$1b'[15;1HShuttleTextureID = %i', ShuttleTextureID);
iprintf(#$1b'[17;1HEnemies use a 256 color pal');
iprintf(#$1b'[18;1HShuttle uses a 16 color pal');
iprintf(#$1b'[19;1HFlyer uses a 16 color pal');
iprintf(#$1b'[20;1H3D plane is a 16 bit image');
TextureSize := enemiesBitmapLen + flyerBitmapLen + organ16BitmapLen + shuttleBitmapLen;
iprintf(#$1b'[22;1HTotal Texture size= %i kb', TextureSize div 1024);
// some variables for our demo
ox := 0; oy := 0; // needed for shuttle angle calculation
Frame := 0; // just the standard frame counter
PhoenixFrame := 0; // animation frame for our firebird
BeeFrame := 0; // animation frame for the bee
Rotation := 0; // rotation value of the rotating sprites
while true do
begin
inc(frame);
rotation := frame * 240; // speed up our rotation
// animate some of our animated sprites
// every 8th frame
if ( (Frame and 7) = 0 ) then
begin
BeeFrame := (BeeFrame + 1) and 1;
inc(PhoenixFrame);
if (PhoenixFrame > 2) then
PhoenixFrame := 0;
end;
// calculate positions for our rotating sprites
x := 128 + SarLongint((cosLerp(Frame) + sinLerp(BRAD_PI + Rotation) * 70), 12);
y := 96 + SarLongint((cosLerp(Frame) + cosLerp(-Rotation) * 50), 12);
// Calculate moving shuttle position
// Get new ship position in f32 format for accuracy since
// shifting here by >> 12 looses accuracy
sx := (cosLerp(Frame * 150) + sinLerp(Frame * 70)) * (SCREEN_WIDTH div 4) ;
sy := (sinLerp(-(Frame * 80)) + sinLerp(Frame * 190)) * (SCREEN_HEIGHT div 4) ;
// get angle(binary radian) to draw the rotated shuttle
angle := atan2Lerp(ox - sx, oy - sy);
// save positions for use on the nexgt frame to get the new angle
ox := sx;
oy := sy;
// Get new shuttle position
// Shifting by >> 12 so that we can screen coordinates to draw
sx := SCREEN_WIDTH div 2 + SarLongint(sx, 12);
sy := SCREEN_HEIGHT div 2 + SarLongint(sy, 12);
// Drawing the fake mode7 FX in 3D mode
draw_grid();
// End drawing in 3D mode
// Start 2D mode
glBegin2D();
// Draw our enemies
// draw some rotated and/or animated sprites
glSpriteRotate( x, y, Rotation, GL_FLIP_NONE, @Enemies[30+BeeFrame]);
glSpriteRotate(255-x, 191-y, Rotation * 4, GL_FLIP_H, @Enemies[84]);
glSpriteRotate(255-x, y, -Rotation, GL_FLIP_V, @Enemies[32]);
glSpriteRotate( x, 191-y, -Rotation * 3, GL_FLIP_H or GL_FLIP_V, @Enemies[81]);
// Some phoenix enemies on the right
// Note the flipmodes
// Also shows how we can draw in "color mode" and shadow mode
glSprite(200, 30, GL_FLIP_NONE, @Enemies[87 + PhoenixFrame]);
glColor( RGB15(31,0,0) );
glSprite(200, 60, GL_FLIP_H, @Enemies[87 + PhoenixFrame]);
// Make the last two sprites translucent
glPolyFmt(POLY_ALPHA(20) or POLY_CULL_NONE or POLY_ID(1));
glColor( RGB15(0,31,20) );
glSprite(200, 90, GL_FLIP_V, @Enemies[87 + PhoenixFrame]);
glColor( RGB15(0,0,0) );
glSprite(200, 130, GL_FLIP_V or GL_FLIP_H , @Enemies[87 + PhoenixFrame]);
//Restore color and translucency to normal
glColor( RGB15(31,31,31) );
glPolyFmt(POLY_ALPHA(31) or POLY_CULL_NONE );
// Offset the angle by -PI/2 since Patater's
// Original sprite faces upwards
glSpriteRotate( sx, sy, angle - (BRAD_PI div 2), GL_FLIP_NONE, @Shuttle);
// Make the flyer translucent just for kicks
glPolyFmt(POLY_ALPHA(20) or POLY_CULL_NONE or POLY_ID(2));
glSpriteRotateScaleXY(SCREEN_WIDTH div 2, SCREEN_HEIGHT div 2, Frame * 140, sinLerp(Frame * 120) * 3, sinLerp(Frame * 210) * 2, GL_FLIP_NONE, @Flyer);
// Restore to normal rendering just to be safe
glPolyFmt(POLY_ALPHA(31) or POLY_CULL_NONE );
glEnd2D();
glFlush( 0 );
swiWaitForVBlank();
end;
end.