mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-05-07 01:12:33 +02:00
332 lines
10 KiB
ObjectPascal
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.
|
|
|