/packages/libndsfpc/examples/gl2d/sprites/sprites.pp

https://github.com/slibre/freepascal · Puppet · 460 lines · 425 code · 35 blank · 0 comment · 20 complexity · 0921f0006001a3a21ab45aa3f29f6fb8 MD5 · raw file

  1. (*
  2. Easy GL2D
  3. Relminator 2011
  4. Richard Eric M. Lope BSN RN
  5. Http://Rel.Phatcode.Net
  6. A very small, simple, yet very fast DS 2D rendering lib using the DS' 3D core.
  7. --
  8. Translated in Object Pascal by Francesco Lombardi - 2012
  9. http://itaprogaming.free.fr
  10. *)
  11. program sprites;
  12. {$L build/enemies.o}
  13. {$L build/zero.o}
  14. {$L build/tiles.o}
  15. {$L build/shuttle.o}
  16. {$L build/anya.o}
  17. {$L build/font.o}
  18. {$L build/fontbubble.o}
  19. {$mode objfpc}
  20. {$H+}
  21. uses
  22. ctypes, nds9, gl2d,
  23. cearn_atan,
  24. uvcoord_enemies, uvcoord_zero;
  25. // GRIT auto-generated files
  26. const
  27. enemiesBitmapLen = 65536;
  28. enemiesPalLen = 512;
  29. zeroBitmapLen = 32768;
  30. tilesBitmapLen = 65536;
  31. tilesPalLen = 512;
  32. shuttleBitmapLen = 2048;
  33. shuttlePalLen = 32;
  34. anyaBitmapLen = 32768;
  35. fontTilesLen = 3072;
  36. fontPalLen = 512;
  37. fontbubbleTilesLen = 2048;
  38. fontbubblePalLen = 512;
  39. var
  40. enemiesBitmap: array [0..0] of cuint; cvar; external;
  41. enemiesPal: array [0..0] of cushort; cvar; external;
  42. zeroBitmap: array [0..0] of cuint; cvar; external;
  43. tilesBitmap: array [0..0] of cuint; cvar; external;
  44. tilesPal: array [0..0] of cushort; cvar; external;
  45. shuttleBitmap: array [0..0] of cuint; cvar; external;
  46. shuttlePal: array [0..0] of cushort; cvar; external;
  47. anyaBitmap: array [0..0] of cuint; cvar; external;
  48. fontTiles: array [0..0] of cuint; cvar; external;
  49. fontPal: array [0..0] of cushort; cvar; external;
  50. fontbubbleTiles: array [0..0] of cuint; cvar; external;
  51. fontbubblePal: array [0..0] of cushort; cvar; external;
  52. // Declare our BG drawing routine
  53. procedure DrawBG(images: pglImage);
  54. var
  55. x, y, i: integer;
  56. begin
  57. for y := 0 to (256 div 16) - 1 do
  58. for x := 0 to (256 div 16) - 1 do
  59. begin
  60. i := y * 16 + x;
  61. glSprite(x * 16, y * 16, GL_FLIP_NONE, @images[i and 255]);
  62. end;
  63. end;
  64. var
  65. BRAD_PI: cint = 1 shl 14;
  66. // This imagesets would use our texture packer generated coords so it's kinda
  67. // safe and easy to use
  68. // ENEMIES_NUM_IMAGES is a value from "uvcoord_crono.h"
  69. // ZERO_NUM_IMAGES is a value from "uvcoord_zero.h"
  70. Enemies: array [0..ENEMIES_NUM_IMAGES -1] of glImage; // spriteset
  71. Zero: array [0..ZERO_NUM_IMAGES - 1] of glImage; // spriteset
  72. // This tileset won't make use of our texture packer generated coords.
  73. // Messy, manual and prone to errors.
  74. // BMP is 256x256 and tiles are 16x16 so.. (256/16) * (256 /16) = 16 * 16
  75. Tiles: array [0..(256 div 16) * (256 div 16) - 1] of glImage;
  76. // These sprites are single texture only so no need to
  77. // do anything special
  78. Shuttle: array [0..0] of glImage;
  79. Anya: array [0..0] of glImage;
  80. topScreen, bottomScreen: TPrintConsole;
  81. font, fontbubble: consoleFont;
  82. hitPal: array of cushort;
  83. i: cint;
  84. PaletteID: cint; // the all-white pal
  85. OriginalPaletteID: cint; // Original palette
  86. EnemiesTextureID: cint;
  87. ZeroTextureID: cint;
  88. TilesTextureID: cint;
  89. ShuttleTextureID: cint;
  90. AnyaTextureID: cint;
  91. TextureSize: cint;
  92. Frame: cint; // just the standard frame counter
  93. PhoenixFrame: cint; // animation frame for our firebird
  94. BeeFrame: cint; // animation frame for the bee
  95. ZeroFrame: cint; // animation frame for zero
  96. Rotation: cint; // rotation value of the rotating sprites
  97. x, y: integer;
  98. color: cint;
  99. begin
  100. // set mode 5, enable BG0 and set it to 3D
  101. videoSetMode(MODE_5_3D);
  102. videoSetModeSub(MODE_0_2D);
  103. // initialize gl2d
  104. glScreen2D();
  105. // Set up enough texture memory for our textures
  106. // Bank A is just 128kb and we are using 194 kb of
  107. // sprites
  108. vramSetBankA(VRAM_A_TEXTURE);
  109. vramSetBankB(VRAM_B_TEXTURE);
  110. vramSetBankF(VRAM_F_TEX_PALETTE); // Allocate VRAM bank for all the palettes
  111. vramSetBankE(VRAM_E_MAIN_BG); // Main bg text/8bit bg. Bank E size == 64kb, exactly enough for 8bit * 256 * 192 + text layer
  112. // Load our custom font for the top screen
  113. consoleInit(@topScreen, 1, BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, false);
  114. //put bg 0 at a lower priority than the text background
  115. bgSetPriority(0, 1);
  116. // Bottom screeen
  117. vramSetBankI(VRAM_I_SUB_BG_0x06208000);
  118. consoleInit(@bottomScreen, 0, BgType_Text4bpp, BgSize_T_256x256, 20, 0, false, false);
  119. font.gfx := pcuint16(@fontTiles);
  120. font.pal := pcuint16(@fontPal);
  121. font.numChars := 95;
  122. font.numColors := fontPalLen div 2;
  123. font.bpp := 4;
  124. font.asciiOffset := 32;
  125. font.convertSingleColor := false;
  126. // Top Screen
  127. fontbubble.gfx := pcuint16(@fontbubbleTiles);
  128. fontbubble.pal := pcuint16(@fontbubblePal);
  129. fontbubble.numChars := 64;
  130. fontbubble.numColors := fontbubblePalLen div 2;
  131. fontbubble.bpp := 4;
  132. fontbubble.asciiOffset := 32;
  133. fontbubble.convertSingleColor := false;
  134. consoleSetFont(@bottomScreen, @font);
  135. consoleSetFont(@topScreen, @fontbubble);
  136. setlength(hitPal, 256);
  137. for i := 0 to 255 do
  138. hitPal[i] := ($FF shl 8) or $FF;
  139. // Generate the texture and load the all-white palette
  140. glGenTextures(1, @PaletteID);
  141. glBindTexture(0, PaletteID);
  142. glColorTableEXT(0, 0, 256, 0, 0, @hitPal[0]);
  143. // Generate another palette for our original image palette
  144. glGenTextures(1, @OriginalPaletteID);
  145. glBindTexture(0, OriginalPaletteID);
  146. glColorTableEXT(0, 0, 256, 0, 0, enemiesPal);
  147. // free some memory
  148. setLength(hitPal, 0);
  149. // Load our Enemies texture
  150. // We used glLoadSpriteSet since the texture was made
  151. // with my texture packer.
  152. EnemiesTextureID := glLoadSpriteSet(
  153. Enemies, // pointer to glImage array
  154. ENEMIES_NUM_IMAGES, // Texture packer auto-generated #define
  155. @enemies_texcoords, // Texture packer auto-generated array
  156. GL_RGB256, // texture type for glTexImage2D() in videoGL.h
  157. TEXTURE_SIZE_256, // sizeX for glTexImage2D() in videoGL.h
  158. TEXTURE_SIZE_256, // sizeY for glTexImage2D() in videoGL.h
  159. GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T or TEXGEN_OFF or
  160. GL_TEXTURE_COLOR0_TRANSPARENT, // param for glTexImage2D() in videoGL.h
  161. 256, // Length of the palette to use (256 colors)
  162. @enemiesPal, // Load our 256 color enemies palette
  163. @enemiesBitmap // image data generated by GRIT
  164. );
  165. // Load our Zero texture
  166. // We used glLoadSpriteSet since the texture was made
  167. // with my texture packer.
  168. // No need for another palette since enemies and zero
  169. // share the same palette.
  170. ZeroTextureID := glLoadSpriteSet(
  171. Zero, // pointer to glImage array
  172. ZERO_NUM_IMAGES, // Texture packer auto-generated #define
  173. @zero_texcoords, // Texture packer auto-generated array
  174. GL_RGB256, // texture type for glTexImage2D() in videoGL.h
  175. TEXTURE_SIZE_128, // sizeX for glTexImage2D() in videoGL.h
  176. TEXTURE_SIZE_256, // sizeY for glTexImage2D() in videoGL.h
  177. GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T or TEXGEN_OFF or
  178. GL_TEXTURE_COLOR0_TRANSPARENT, // param for glTexImage2D() in videoGL.h
  179. 256, // Length of the palette to use (256 colors)
  180. @enemiesPal, // Zero and Enemies share the same palette
  181. @zeroBitmap // image data generated by GRIT
  182. );
  183. // Our texture handle for our tiles
  184. // I used glLoadTileSet since the texture
  185. // is just a bunch of 16x16 tiles in a 256x256
  186. // tileset so we don't need a texture packer for this.
  187. TilesTextureID := glLoadTileSet(
  188. Tiles, // pointer to glImage array
  189. 16, // sprite width
  190. 16, // sprite height
  191. 256, // bitmap width
  192. 256, // bitmap height
  193. GL_RGB256, // texture type for glTexImage2D() in videoGL.h
  194. TEXTURE_SIZE_256, // sizeX for glTexImage2D() in videoGL.h
  195. TEXTURE_SIZE_256, // sizeY for glTexImage2D() in videoGL.h
  196. GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T or TEXGEN_OFF or
  197. GL_TEXTURE_COLOR0_TRANSPARENT, // param for glTexImage2D() in videoGL.h
  198. 256, // Length of the palette to use (256 colors)
  199. @tilesPal, // Load our 256 color tiles palette
  200. @tilesBitmap // image data generated by GRIT
  201. );
  202. // Shuttle
  203. // Since the shuttle is just a single 64x64 image,
  204. // We use glLoadTileSet() giving the right dimensions.
  205. ShuttleTextureID := glLoadTileSet(
  206. Shuttle, // pointer to glImage array
  207. 64, // sprite width
  208. 64, // sprite height
  209. 64, // bitmap image width
  210. 64, // bitmap image height
  211. GL_RGB16, // texture type for glTexImage2D() in videoGL.h
  212. TEXTURE_SIZE_64, // sizeX for glTexImage2D() in videoGL.h
  213. TEXTURE_SIZE_64, // sizeY for glTexImage2D() in videoGL.h
  214. GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T or TEXGEN_OFF or
  215. GL_TEXTURE_COLOR0_TRANSPARENT,
  216. 16, // Length of the palette to use (16 colors)
  217. @shuttlePal, // Load our 256 color tiles palette
  218. @shuttleBitmap // image data generated by GRIT
  219. );
  220. // Anya
  221. // This is a 16 bit image
  222. AnyaTextureID := glLoadTileSet(
  223. Anya,
  224. 128,
  225. 128,
  226. 128,
  227. 128,
  228. GL_RGB,
  229. TEXTURE_SIZE_128,
  230. TEXTURE_SIZE_128,
  231. GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T or TEXGEN_OFF,
  232. 0, // Just use 0 if palette is not in use
  233. nil, // Just use nil if palette is not in use
  234. @anyaBitmap
  235. );
  236. // Print some console stuff
  237. // Top
  238. consoleSelect(@topScreen);
  239. iprintf(#10#10#10#10#9'WOOT!'#10);
  240. iprintf(#9'TOPSCREEN 3D+TEXT'#10);
  241. // Bottom
  242. consoleSelect(@bottomScreen);
  243. iprintf(#$1b'[1;1HEasy GL2D Sprites Demo');
  244. iprintf(#$1b'[2;1HRelminator');
  245. iprintf(#$1b'[4;1HHttp://Rel.Phatcode.Net');
  246. iprintf(#$1b'[6;1HA demo showing some sprite');
  247. iprintf(#$1b'[7;1Hcapabilities of Easy GL2D');
  248. iprintf(#$1b'[ 9;1HSprites by:');
  249. iprintf(#$1b'[10;1HAdigun A. Polack, Patater,');
  250. iprintf(#$1b'[11;1HCapcom and Anya Therese Lope');
  251. iprintf(#$1b'[13;1HTextureIDs = %i, %i, %i, %i, %i',
  252. EnemiesTextureID,
  253. ZeroTextureID,
  254. TilesTextureID,
  255. ShuttleTextureID,
  256. AnyaTextureID );
  257. // calculate the amount of
  258. // memory uploaded to VRAM in KB
  259. TextureSize := enemiesBitmapLen + zeroBitmapLen + tilesBitmapLen + shuttleBitmapLen + anyaBitmapLen;
  260. iprintf(#$1b'[15;1HTotal Texture size= %i kb', TextureSize div 1024);
  261. iprintf(#$1b'[17;1HEnemies use a 256 color pal');
  262. iprintf(#$1b'[18;1HZero uses a 256 color pal');
  263. iprintf(#$1b'[19;1HTiles use a 256 color pal');
  264. iprintf(#$1b'[20;1HShuttle uses a 16 color pal');
  265. iprintf(#$1b'[21;1HAnya is a 16 bit image');
  266. // some variables for our demo
  267. Frame := 0; // just the standard frame counter
  268. PhoenixFrame := 0; // animation frame for our firebird
  269. BeeFrame := 0; // animation frame for the bee
  270. ZeroFrame := 0; // animation frame for zero
  271. Rotation := 0; // rotation value of the rotating sprites
  272. while true do
  273. begin
  274. inc(Frame);
  275. Rotation := Frame * 240; // speed up our rotation
  276. // animate some of our animated sprites
  277. // every 8th frame
  278. if (Frame and 7) = 0 then
  279. begin
  280. BeeFrame := (BeeFrame + 1) and 1;
  281. inc(PhoenixFrame);
  282. if (PhoenixFrame > 2) then
  283. PhoenixFrame := 0;
  284. end;
  285. // Faster zero animation
  286. if (Frame and 3) = 0 then
  287. begin
  288. inc(ZeroFrame);
  289. if (ZeroFrame > 9) then
  290. ZeroFrame := 0;
  291. end;
  292. // calculate positions for our rotating sprites
  293. x := 128 + SarLongInt((cosLerp(Frame) + sinLerp(BRAD_PI + Rotation) * 100), 12);
  294. y := 96 + SarLongInt((cosLerp(Frame) + cosLerp(-Rotation) * 80), 12);
  295. // Start 2D mode
  296. glBegin2D();
  297. // Set our palette to our tiles (256 colors)
  298. // and draw our background
  299. DrawBG(@Tiles);
  300. // Make the Anya's rotoscaled sprite translucent just for kicks
  301. // Use glSpriteRotateScaleXY() for some effect
  302. // Give it a polygon ID so that transluceny would work
  303. glPolyFmt(POLY_ALPHA(20) or POLY_CULL_NONE or POLY_ID(1));
  304. glSpriteRotateScaleXY(SCREEN_WIDTH div 2, SCREEN_HEIGHT div 2,
  305. Frame * 140, sinLerp(Frame * 120) * 3, sinLerp(Frame * 210) * 2,
  306. GL_FLIP_NONE,
  307. @Anya);
  308. // Draw our enemies
  309. // draw some rotated and/or animated sprites
  310. // Give the other sprites different polygon IDs
  311. // so that translucency works
  312. glPolyFmt(POLY_ALPHA(20) or POLY_CULL_NONE or POLY_ID(2));
  313. glSpriteRotate( x, y, Rotation, GL_FLIP_NONE, @Enemies[30 + BeeFrame]);
  314. glSpriteRotate(255 - x, 191 - y, Rotation * 4, GL_FLIP_H, @Enemies[84]);
  315. glSpriteRotate(255 - x, y, -Rotation, GL_FLIP_V, @Enemies[32]);
  316. glSpriteRotate( x, 191 - y, -Rotation * 3, GL_FLIP_H or GL_FLIP_V, @Enemies[81]);
  317. // Some phoenix enemies on the right
  318. // Note the flipmodes
  319. // Also shows how we can draw in "color mode" and shadow mode
  320. glPolyFmt(POLY_ALPHA(20) or POLY_CULL_NONE or POLY_ID(3));
  321. glSprite(200, 0, GL_FLIP_NONE, @Enemies[87 + PhoenixFrame]);
  322. glColor(RGB15(31, 0, 0));
  323. glSprite(200, 30, GL_FLIP_H, @Enemies[87 + PhoenixFrame]);
  324. // Make the last two sprites translucent
  325. glPolyFmt(POLY_ALPHA(20) or POLY_CULL_NONE or POLY_ID(4));
  326. glColor(RGB15(0, 31, 20) );
  327. glSprite(200, 60, GL_FLIP_V, @Enemies[87 + PhoenixFrame]);
  328. glColor(RGB15(0, 0, 0));
  329. glSprite(200, 90, GL_FLIP_V or GL_FLIP_H, @Enemies[87 + PhoenixFrame]);
  330. //Restore color and translucency to normal
  331. glColor(RGB15(31, 31, 31));
  332. glPolyFmt(POLY_ALPHA(31) or POLY_CULL_NONE or POLY_ID(5));
  333. // "Clean Stretch" the sprite
  334. // Useful for lasers and some effects
  335. glSpriteStretchHorizontal(0, 135, 64 + (abs(sinLerp(Frame * 100) * 200) shr 12), @Shuttle);
  336. // USING DIFFERENT PALETTES
  337. // Set the active texture to Zero
  338. // and use our special all white palette
  339. glSetActiveTexture(ZeroTextureID);
  340. glAssignColorTable(0, PaletteID);
  341. // Zero Sprite is drawn all white
  342. glSprite(0, 42 * 0, GL_FLIP_NONE, @Zero[ZeroFrame]);
  343. // Draw a horizontally flipped "disco" zero
  344. // Disco fx is done with glColor
  345. color := (Frame * 4) and 31;
  346. glColor(RGB15(color, 31 - color, 16 + color * 2));
  347. glSprite(0, 42 * 1, GL_FLIP_H, @Zero[ZeroFrame]);
  348. // Restore our palette
  349. glAssignColorTable(0, OriginalPaletteID);
  350. // restore pal to enemies
  351. glColor(RGB15(31 - color, 16 + color * 2, color));
  352. glSprite(0, 42 * 2, GL_FLIP_V, @Zero[ZeroFrame]);
  353. // Normalize color
  354. glColor(RGB15(31, 31, 31));
  355. glSprite(0, 42 * 3, GL_FLIP_V or GL_FLIP_H, @Zero[ZeroFrame]);
  356. glEnd2D();
  357. glFlush(0);
  358. swiWaitForVBlank();
  359. end;
  360. end.