(* 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.