(* 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 sprites; {$L build/enemies.o} {$L build/zero.o} {$L build/tiles.o} {$L build/shuttle.o} {$L build/anya.o} {$L build/font.o} {$L build/fontbubble.o} {$mode objfpc} {$H+} uses ctypes, nds9, gl2d, cearn_atan, uvcoord_enemies, uvcoord_zero; // GRIT auto-generated files const enemiesBitmapLen = 65536; enemiesPalLen = 512; zeroBitmapLen = 32768; tilesBitmapLen = 65536; tilesPalLen = 512; shuttleBitmapLen = 2048; shuttlePalLen = 32; anyaBitmapLen = 32768; fontTilesLen = 3072; fontPalLen = 512; fontbubbleTilesLen = 2048; fontbubblePalLen = 512; var enemiesBitmap: array [0..0] of cuint; cvar; external; enemiesPal: array [0..0] of cushort; cvar; external; zeroBitmap: array [0..0] of cuint; cvar; external; tilesBitmap: array [0..0] of cuint; cvar; external; tilesPal: array [0..0] of cushort; cvar; external; shuttleBitmap: array [0..0] of cuint; cvar; external; shuttlePal: array [0..0] of cushort; cvar; external; anyaBitmap: array [0..0] of cuint; cvar; external; fontTiles: array [0..0] of cuint; cvar; external; fontPal: array [0..0] of cushort; cvar; external; fontbubbleTiles: array [0..0] of cuint; cvar; external; fontbubblePal: array [0..0] of cushort; cvar; external; // Declare our BG drawing routine procedure DrawBG(images: pglImage); var x, y, i: integer; begin for y := 0 to (256 div 16) - 1 do for x := 0 to (256 div 16) - 1 do begin i := y * 16 + x; glSprite(x * 16, y * 16, GL_FLIP_NONE, @images[i and 255]); end; end; var BRAD_PI: cint = 1 shl 14; // This imagesets would use our texture packer generated coords so it's kinda // safe and easy to use // ENEMIES_NUM_IMAGES is a value from "uvcoord_crono.h" // ZERO_NUM_IMAGES is a value from "uvcoord_zero.h" Enemies: array [0..ENEMIES_NUM_IMAGES -1] of glImage; // spriteset Zero: array [0..ZERO_NUM_IMAGES - 1] of glImage; // spriteset // This tileset won't make use of our texture packer generated coords. // Messy, manual and prone to errors. // BMP is 256x256 and tiles are 16x16 so.. (256/16) * (256 /16) = 16 * 16 Tiles: array [0..(256 div 16) * (256 div 16) - 1] of glImage; // These sprites are single texture only so no need to // do anything special Shuttle: array [0..0] of glImage; Anya: array [0..0] of glImage; topScreen, bottomScreen: TPrintConsole; font, fontbubble: consoleFont; hitPal: array of cushort; i: cint; PaletteID: cint; // the all-white pal OriginalPaletteID: cint; // Original palette EnemiesTextureID: cint; ZeroTextureID: cint; TilesTextureID: cint; ShuttleTextureID: cint; AnyaTextureID: cint; TextureSize: cint; Frame: cint; // just the standard frame counter PhoenixFrame: cint; // animation frame for our firebird BeeFrame: cint; // animation frame for the bee ZeroFrame: cint; // animation frame for zero Rotation: cint; // rotation value of the rotating sprites x, y: integer; color: cint; begin // set mode 5, enable BG0 and set it to 3D videoSetMode(MODE_5_3D); videoSetModeSub(MODE_0_2D); // initialize gl2d glScreen2D(); // Set up enough texture memory for our textures // Bank A is just 128kb and we are using 194 kb of // sprites vramSetBankA(VRAM_A_TEXTURE); vramSetBankB(VRAM_B_TEXTURE); vramSetBankF(VRAM_F_TEX_PALETTE); // Allocate VRAM bank for all the palettes vramSetBankE(VRAM_E_MAIN_BG); // Main bg text/8bit bg. Bank E size == 64kb, exactly enough for 8bit * 256 * 192 + text layer // Load our custom font for the top screen consoleInit(@topScreen, 1, BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, false); //put bg 0 at a lower priority than the text background bgSetPriority(0, 1); // Bottom screeen vramSetBankI(VRAM_I_SUB_BG_0x06208000); consoleInit(@bottomScreen, 0, BgType_Text4bpp, BgSize_T_256x256, 20, 0, false, false); font.gfx := pcuint16(@fontTiles); font.pal := pcuint16(@fontPal); font.numChars := 95; font.numColors := fontPalLen div 2; font.bpp := 4; font.asciiOffset := 32; font.convertSingleColor := false; // Top Screen fontbubble.gfx := pcuint16(@fontbubbleTiles); fontbubble.pal := pcuint16(@fontbubblePal); fontbubble.numChars := 64; fontbubble.numColors := fontbubblePalLen div 2; fontbubble.bpp := 4; fontbubble.asciiOffset := 32; fontbubble.convertSingleColor := false; consoleSetFont(@bottomScreen, @font); consoleSetFont(@topScreen, @fontbubble); setlength(hitPal, 256); for i := 0 to 255 do hitPal[i] := ($FF shl 8) or $FF; // Generate the texture and load the all-white palette glGenTextures(1, @PaletteID); glBindTexture(0, PaletteID); glColorTableEXT(0, 0, 256, 0, 0, @hitPal[0]); // Generate another palette for our original image palette glGenTextures(1, @OriginalPaletteID); glBindTexture(0, OriginalPaletteID); glColorTableEXT(0, 0, 256, 0, 0, enemiesPal); // free some memory setLength(hitPal, 0); // 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 ); // Load our Zero texture // We used glLoadSpriteSet since the texture was made // with my texture packer. // No need for another palette since enemies and zero // share the same palette. ZeroTextureID := glLoadSpriteSet( Zero, // pointer to glImage array ZERO_NUM_IMAGES, // Texture packer auto-generated #define @zero_texcoords, // Texture packer auto-generated array GL_RGB256, // texture type for glTexImage2D() in videoGL.h TEXTURE_SIZE_128, // 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, // Zero and Enemies share the same palette @zeroBitmap // image data generated by GRIT ); // Our texture handle for our tiles // I used glLoadTileSet since the texture // is just a bunch of 16x16 tiles in a 256x256 // tileset so we don't need a texture packer for this. TilesTextureID := glLoadTileSet( Tiles, // pointer to glImage array 16, // sprite width 16, // sprite height 256, // bitmap width 256, // bitmap height 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) @tilesPal, // Load our 256 color tiles palette @tilesBitmap // 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 256 color tiles palette @shuttleBitmap // image data generated by GRIT ); // Anya // This is a 16 bit image AnyaTextureID := glLoadTileSet( Anya, 128, 128, 128, 128, GL_RGB, TEXTURE_SIZE_128, TEXTURE_SIZE_128, GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T or TEXGEN_OFF, 0, // Just use 0 if palette is not in use nil, // Just use nil if palette is not in use @anyaBitmap ); // Print some console stuff // Top consoleSelect(@topScreen); iprintf(#10#10#10#10#9'WOOT!'#10); iprintf(#9'TOPSCREEN 3D+TEXT'#10); // Bottom consoleSelect(@bottomScreen); iprintf(#$1b'[1;1HEasy GL2D Sprites Demo'); iprintf(#$1b'[2;1HRelminator'); iprintf(#$1b'[4;1HHttp://Rel.Phatcode.Net'); iprintf(#$1b'[6;1HA demo showing some sprite'); iprintf(#$1b'[7;1Hcapabilities of Easy GL2D'); iprintf(#$1b'[ 9;1HSprites by:'); iprintf(#$1b'[10;1HAdigun A. Polack, Patater,'); iprintf(#$1b'[11;1HCapcom and Anya Therese Lope'); iprintf(#$1b'[13;1HTextureIDs = %i, %i, %i, %i, %i', EnemiesTextureID, ZeroTextureID, TilesTextureID, ShuttleTextureID, AnyaTextureID ); // calculate the amount of // memory uploaded to VRAM in KB TextureSize := enemiesBitmapLen + zeroBitmapLen + tilesBitmapLen + shuttleBitmapLen + anyaBitmapLen; iprintf(#$1b'[15;1HTotal Texture size= %i kb', TextureSize div 1024); iprintf(#$1b'[17;1HEnemies use a 256 color pal'); iprintf(#$1b'[18;1HZero uses a 256 color pal'); iprintf(#$1b'[19;1HTiles use a 256 color pal'); iprintf(#$1b'[20;1HShuttle uses a 16 color pal'); iprintf(#$1b'[21;1HAnya is a 16 bit image'); // some variables for our demo Frame := 0; // just the standard frame counter PhoenixFrame := 0; // animation frame for our firebird BeeFrame := 0; // animation frame for the bee ZeroFrame := 0; // animation frame for zero 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; // Faster zero animation if (Frame and 3) = 0 then begin inc(ZeroFrame); if (ZeroFrame > 9) then ZeroFrame := 0; end; // calculate positions for our rotating sprites x := 128 + SarLongInt((cosLerp(Frame) + sinLerp(BRAD_PI + Rotation) * 100), 12); y := 96 + SarLongInt((cosLerp(Frame) + cosLerp(-Rotation) * 80), 12); // Start 2D mode glBegin2D(); // Set our palette to our tiles (256 colors) // and draw our background DrawBG(@Tiles); // Make the Anya's rotoscaled sprite translucent just for kicks // Use glSpriteRotateScaleXY() for some effect // Give it a polygon ID so that transluceny would work glPolyFmt(POLY_ALPHA(20) or POLY_CULL_NONE or POLY_ID(1)); glSpriteRotateScaleXY(SCREEN_WIDTH div 2, SCREEN_HEIGHT div 2, Frame * 140, sinLerp(Frame * 120) * 3, sinLerp(Frame * 210) * 2, GL_FLIP_NONE, @Anya); // Draw our enemies // draw some rotated and/or animated sprites // Give the other sprites different polygon IDs // so that translucency works glPolyFmt(POLY_ALPHA(20) or POLY_CULL_NONE or POLY_ID(2)); 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 glPolyFmt(POLY_ALPHA(20) or POLY_CULL_NONE or POLY_ID(3)); glSprite(200, 0, GL_FLIP_NONE, @Enemies[87 + PhoenixFrame]); glColor(RGB15(31, 0, 0)); glSprite(200, 30, GL_FLIP_H, @Enemies[87 + PhoenixFrame]); // Make the last two sprites translucent glPolyFmt(POLY_ALPHA(20) or POLY_CULL_NONE or POLY_ID(4)); glColor(RGB15(0, 31, 20) ); glSprite(200, 60, GL_FLIP_V, @Enemies[87 + PhoenixFrame]); glColor(RGB15(0, 0, 0)); glSprite(200, 90, 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 or POLY_ID(5)); // "Clean Stretch" the sprite // Useful for lasers and some effects glSpriteStretchHorizontal(0, 135, 64 + (abs(sinLerp(Frame * 100) * 200) shr 12), @Shuttle); // USING DIFFERENT PALETTES // Set the active texture to Zero // and use our special all white palette glSetActiveTexture(ZeroTextureID); glAssignColorTable(0, PaletteID); // Zero Sprite is drawn all white glSprite(0, 42 * 0, GL_FLIP_NONE, @Zero[ZeroFrame]); // Draw a horizontally flipped "disco" zero // Disco fx is done with glColor color := (Frame * 4) and 31; glColor(RGB15(color, 31 - color, 16 + color * 2)); glSprite(0, 42 * 1, GL_FLIP_H, @Zero[ZeroFrame]); // Restore our palette glAssignColorTable(0, OriginalPaletteID); // restore pal to enemies glColor(RGB15(31 - color, 16 + color * 2, color)); glSprite(0, 42 * 2, GL_FLIP_V, @Zero[ZeroFrame]); // Normalize color glColor(RGB15(31, 31, 31)); glSprite(0, 42 * 3, GL_FLIP_V or GL_FLIP_H, @Zero[ZeroFrame]); glEnd2D(); glFlush(0); swiWaitForVBlank(); end; end.