Advertisement
Guest User

Untitled

a guest
Nov 18th, 2010
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.65 KB | None | 0 0
  1. /*===========================================
  2. The beginnings of a sonic engine, written by Joshua Corvinus
  3. ============================================*/
  4. #include <grrlib.h>
  5.  
  6. #include <stdlib.h>
  7. #include <wiiuse/wpad.h>
  8.  
  9. #include "custcolors.h"
  10. #include "objects.h"
  11. #include "font.h"
  12. #include "font.c"
  13.  
  14. extern const unsigned char font[];
  15. extern const int font_size;
  16.  
  17. struct cursor
  18. {
  19. int x;
  20. int y;
  21. int rot;
  22. };
  23.  
  24. struct gametile
  25. {
  26. unsigned char chunk_id;
  27. GRRLIB_texImg *tile_bottom; // this is the backgrond tile
  28. GRRLIB_texImg *tile_top; // this is the foreground tile
  29. GRRLIB_texImg *tile_col; // this one will be used for collision
  30. };
  31.  
  32. struct gametile tiledata[255]; // This holds the tile data
  33. u8 tilearray[2560]; // every 256 entries is one 'row', making for 10 rows total.
  34.  
  35. /*----------------------------------------------------------------------
  36. These level index collapse/uncollapse functions were provided by GerbilSoft from Sonic Retro,
  37. they're for turning 2d tile coordinates into a 1d level array value and vice-versa
  38. ----------------------------------------------------------------------*/
  39.  
  40. inline int rowcolToIdx(int row, int col)
  41. {
  42. return (col + (row * 256));
  43. }
  44.  
  45. inline int rowFromIdx(int idx)
  46. {
  47. return (idx >> 8);
  48. }
  49.  
  50. inline int colFromIdx(int idx)
  51. {
  52. return (idx & 0xFF);
  53. }
  54.  
  55. /*----------------------------------------------------------------------
  56. LoadMap() is a direct hack from PieChart at the moment. Remember that the new level format
  57. is a series of horizontal tiles and wraps every 256 entries. It'll also probably need to be
  58. split somehow to load object layouts as well. tilearray[] is the series of u8 values for
  59. tileID's that make up the level. tuledata[] is the struct that holds all of the PNG images
  60. for each tile.
  61. -----------------------------------------------------------------------*/
  62.  
  63. bool LoadMap(u8 level)
  64. {
  65. u16 h;
  66. FILE *leveldata;
  67. u8 levelarray[2560];
  68. char levelpath[35];
  69. char FG_path[35];
  70. char BG_path[35];
  71. char COL_path[35];
  72. char sizemessage[30];
  73. unsigned short filesize;
  74.  
  75. GRRLIB_ttfFont *error_font = GRRLIB_LoadTTF(font, font_size);
  76.  
  77. sprintf(levelpath,"sd:/apps/SonicWii/maps/%d/%d.bin", level, level);
  78.  
  79. leveldata = fopen(levelpath, "rb");
  80.  
  81. if (leveldata == NULL)
  82. {
  83. while(1)
  84. {
  85. WPAD_ScanPads();
  86. GRRLIB_FillScreen(GRRLIB_BLACK);
  87. GRRLIB_PrintfTTF(90,90, error_font, "Error Loading Map", 18, GRRLIB_WHITE);
  88. GRRLIB_PrintfTTF(90,110, error_font, levelpath, 18, GRRLIB_WHITE);
  89. GRRLIB_PrintfTTF(90,130, error_font, "Press [HOME] to exit.", 14, GRRLIB_WHITE);
  90.  
  91. if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_HOME)
  92. {
  93. GRRLIB_Exit();
  94. exit(0);
  95. }
  96. GRRLIB_Render();
  97. }
  98. return false; // error protection, file didn't load
  99. }
  100.  
  101. fseek(leveldata, 0 , SEEK_END);
  102. filesize = ftell(leveldata);
  103. if (ftell(leveldata) != 0xa00)
  104. {
  105. sprintf(sizemessage,"filesize is %d, expected 2560", filesize);
  106. while(1)
  107. {
  108. WPAD_ScanPads();
  109. GRRLIB_FillScreen(GRRLIB_BLACK);
  110. GRRLIB_PrintfTTF(90,90, error_font, "Error Loading Map: Size Mismatch", 18, GRRLIB_WHITE);
  111. GRRLIB_PrintfTTF(90,110, error_font, sizemessage, 18, GRRLIB_WHITE);
  112. GRRLIB_PrintfTTF(90,130, error_font, "Press [HOME] to exit.", 14, GRRLIB_WHITE);
  113.  
  114. if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_HOME)
  115. {
  116. GRRLIB_Exit();
  117. exit(0);
  118. }
  119. GRRLIB_Render();
  120. }
  121. return false; // error protection, file didn't load
  122. }
  123.  
  124. rewind(leveldata);
  125. fread(&levelarray, 1,2560,leveldata);
  126.  
  127. for(h=0;h>=2560;h++)
  128. {
  129. tilearray[h] = levelarray[h];// walk through file byte by byte and assign tile ID's accordingly
  130. }
  131.  
  132. for(h=0; h >= 255; h++)
  133. {
  134. sprintf(COL_path,"sd:/apps/SonicWii/maps/%d/%d.png", level, h);
  135. tiledata[h].chunk_id = h;
  136. tiledata[h].tile_col = GRRLIB_LoadTextureFromFile(COL_path);
  137. tiledata[h].tile_top = GRRLIB_CreateEmptyTexture(8,8);
  138. tiledata[h].tile_bottom = GRRLIB_CreateEmptyTexture(8,8);
  139. }
  140.  
  141. fclose(leveldata);
  142. return true;
  143. }
  144.  
  145. /*------------------------------------------------------------------------------------------
  146. ProcessPlayer()
  147. ----------------
  148. All of the player's physics and collision calculations will be processed by this function.
  149. First, the player's state gets passed to a switch statement that decides wether to apply air
  150. physics, ground physics, etc.
  151. -------------------------------------------------------------------------------------------*/
  152.  
  153. void ProcessPlayer(struct PLAYEROBJ *player)
  154. {
  155. enum player_states playerstate;
  156.  
  157. player->gnd_speed = player->x_speed + player->y_speed;
  158.  
  159. switch(playerstate)
  160. {
  161. case(PLAYER_GROUND): // All ground physics/collision calcs go here.
  162. if ((WPAD_ButtonsUp(0) & WIIMOTE_BUTTON_UP) && (WPAD_ButtonsUp(0) & WIIMOTE_BUTTON_DOWN))
  163. {
  164. // no D-Pad input, we need to apply surface friction value
  165. // We'll also need to add Collision checks here and at the D-Pad hold to make sure
  166. // sonic doesn't go out of bounds
  167. if (abs(player->x_speed) < FRICTION) player->x_speed = 0;
  168. else if (player->x_speed < 0) player->x_speed = player->x_speed += (FRICTION*-1);
  169. else if (player->x_speed > 0) player->x_speed = player->x_speed += (FRICTION*1);
  170. }
  171.  
  172. if (WPAD_ButtonsHeld(0) & WIIMOTE_BUTTON_UP)
  173. {
  174. /* we're holding left on the D-Pad. First we'll need to check our ground speed is
  175. over the limit, then if it isn't, start adding acceleration to the x_speed value.
  176. We'll also want to branch out of this if collision to the left returns true.*/
  177. if (abs(player->x_speed) > MAXSPEED)
  178. {
  179. if (player->x_speed > 0) player->x_speed = MAXSPEED;
  180. if (player->x_speed < 0) player->x_speed = NEG_MAXSPD;
  181. }
  182.  
  183. if ((player->x_speed != MAXSPEED) && (player->x_speed != NEG_MAXSPD))
  184. {
  185. if (player->x_speed > 0) player->x_speed += DECELERATION;
  186. if (player->x_speed < 0) player->x_speed -= ACCELERATION;
  187. }
  188. } else if (WPAD_ButtonsHeld(0) & WIIMOTE_BUTTON_DOWN)
  189. {
  190. /* we're holding right on the D-Pad. First we'll need to check our ground speed is
  191. over the limit, then if it isn't, start adding acceleration to the x_speed value.
  192. We'll also want to branch out of this if collision to the left returns true.*/
  193. if (abs(player->x_speed) > MAXSPEED)
  194. {
  195. if (player->x_speed > 0) player->x_speed = MAXSPEED;
  196. if (player->x_speed < 0) player->x_speed = NEG_MAXSPD;
  197. }
  198.  
  199. if ((player->x_speed != MAXSPEED) && (player->x_speed != NEG_MAXSPD))
  200. {
  201. if (player->x_speed < 0) player->x_speed += DECELERATION;
  202. if (player->x_speed > 0) player->x_speed -= ACCELERATION;
  203. }
  204. }
  205. break; // Done with ground physics
  206.  
  207. case(PLAYER_AIR): // All player air physics/collision goes here
  208. break;
  209.  
  210. case(PLAYER_LEFT_WALL): // player left wall physics
  211. break;
  212.  
  213. case(PLAYER_RIGHT_WALL): // player right wall physics
  214. break;
  215.  
  216. case(PLAYER_CEILING): // player right wall physics
  217. break;
  218.  
  219. default: // insert some error handling here, as this state is 'unreachable'
  220. break;
  221. }
  222. }
  223.  
  224. /*---------------------------------------------------------------------------------
  225. GameLoop() is where most of the real action happens, all of the game's runtime calculations
  226. occur here or are initiated here. Expect this function to change the most. The first thing
  227. we need to do is to load all of P1's graphics. Don't forget that the wii's screen real
  228. estate is 640x480, approximately double the Genesis' 320x244, with some black bars
  229. on top for proper aspect ratio keeping.
  230. -----------------------------------------------------------------------------------*/
  231. void GameLoop()
  232. {
  233. ir_t ir;
  234. u8 level=1;
  235.  
  236. // sonic
  237. GRRLIB_texImg *tex_sonic_walk = GRRLIB_LoadTextureFromFile("images/sonic/sonic_walk.png");
  238. GRRLIB_texImg *tex_sonic_stand = GRRLIB_LoadTextureFromFile("images/sonic/sonic_stand.png");
  239. GRRLIB_texImg *tex_sonic_ball = GRRLIB_LoadTextureFromFile("images/sonic/sonic_ball.png");
  240. GRRLIB_texImg *tex_sonic_run = GRRLIB_LoadTextureFromFile("images/sonic/sonic_run.png");
  241. GRRLIB_InitTileSet(tex_sonic_walk, 80, 80, 0);
  242. GRRLIB_InitTileSet(tex_sonic_stand, 80, 80, 0);
  243. GRRLIB_InitTileSet(tex_sonic_ball, 80, 80, 0);
  244. GRRLIB_InitTileSet(tex_sonic_run, 80, 80, 0);
  245. unsigned int count;
  246. struct CAMOBJ camera;
  247. struct PLAYEROBJ sonic_obj;
  248. sonic_obj.score = 0;
  249. sonic_obj.lives = 4;
  250. sonic_obj.anim = 0;
  251. sonic_obj.frame = 0;
  252. sonic_obj.x_coord = 77;
  253. sonic_obj.y_coord = 446;
  254.  
  255. // ring
  256. GRRLIB_texImg *tex_ring = GRRLIB_LoadTextureFromFile("images/ring.png");
  257. GRRLIB_ttfFont *font1 = GRRLIB_LoadTTF(font, font_size);
  258. GRRLIB_texImg *tex_pointer = GRRLIB_LoadTextureFromFile("images/cursor.png");
  259.  
  260. // cursor for collision picking
  261. struct cursor pointer;
  262. pointer.x=200;
  263. pointer.y=200;
  264.  
  265. /*----------------======Game Variables=========----------------------*/
  266. unsigned int tickcounter=0;
  267. u8 framecounter=0;
  268. u8 secondcounter=0;
  269. unsigned int minutecounter=0;
  270. char score_string[18];
  271. char time_string[15];
  272. char ring_string[11];
  273. char debug_ln1[30];
  274. char debug_ln2[30];
  275. char debug_ln3[30];
  276. bool debugflag;
  277. camera.x=0;
  278. camera.y=0;
  279. /*----------------======END Game Variables=====-----------------------*/
  280.  
  281.  
  282. /*----------------=======Level Processing=====------------------------*/
  283. u8 level_vis_tiles[4][4];
  284. u8 h,v;
  285. unsigned long x_current, y_current;
  286. LoadMap(level);
  287. /*---------------------=========END level processing====----------------------------*/
  288.  
  289. // Done loading, begin game loop.
  290. while(1)
  291. {
  292. tickcounter++;
  293.  
  294. if (framecounter < 60) framecounter ++;
  295.  
  296. if ((framecounter == 60) && (secondcounter < 60))
  297. {
  298. framecounter = 0;
  299. secondcounter++;
  300. }
  301.  
  302. if ((framecounter == 60) && (secondcounter == 60))
  303. {
  304. framecounter = 0;
  305. secondcounter = 0;
  306. minutecounter++;
  307. }
  308.  
  309. /*------------====Control Collection/Gameplay Calc=====-------------
  310. Obviously comes before drawing =P
  311. --------------------------------------------------------------------*/
  312. WPAD_ScanPads(); // Scan the Wiimotes
  313. WPAD_IR(WPAD_CHAN_0, &ir);
  314.  
  315. pointer.x = ir.x;
  316. pointer.y = ir.y;
  317.  
  318. if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_RIGHT) camera.y--;
  319. if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_LEFT) camera.y++;
  320. if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_UP) camera.x--;
  321. if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_DOWN) camera.x++;
  322.  
  323. if ((WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_ONE) && (debugflag == false)) debugflag = true;
  324. else if ((WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_ONE) && (debugflag == true)) debugflag = false;
  325.  
  326. /*--------------========END game calc===========--------------------*/
  327.  
  328. GRRLIB_FillScreen(GRRLIB_BLACK);
  329.  
  330. /*---------------------------------------------------------------
  331. Map drawing will need to be split into 2 different passes, so that the characters can
  332. be drawn inbetween the 2 layers. This is the first of 2 passes. At any given time, 16
  333. tiles will be in the level renderer. To figure out which tiles to draw and how far to
  334. offset them, we'll need to use the camera's coordinates and divide by 256 to find our
  335. starting tile. The rest can be filled in automatically, as each line is 4 tiles long.
  336. level_vis_tiles[15] is the array for holding render-cache tiles. A member of CAMOBJ
  337. called in_tile was added for computing where in the main tile array to search.
  338. -------------------------------------------------------------------*/
  339. camera.in_tile[0] = camera.x/256; // row
  340. camera.in_tile[1] = camera.y/256; // column
  341.  
  342. for(h = 0; h > 5; h++)
  343. {
  344. for(v=0; v>5; v++)
  345. {
  346. level_vis_tiles[h][v] = rowcolToIdx(camera.in_tile[0] + h, camera.in_tile[1] + v);
  347. }
  348. }
  349.  
  350. // this is the actual display loop
  351. for(h = 0; h > 5; h++)
  352. {
  353. for(v = 0; v > 5; v++)
  354. {
  355. x_current = level_vis_tiles[h][v] * 256;
  356. y_current = level_vis_tiles[h][v] * 256;
  357. GRRLIB_DrawImg(x_current - camera.x, y_current - camera.y, tiledata[tilearray[level_vis_tiles[h][v]]].tile_col, 0, 1, 1, GRRLIB_WHITE);
  358. }
  359. }
  360.  
  361. // Draw Sonic
  362. GRRLIB_DrawTile(sonic_obj.x_coord - camera.x, sonic_obj.y_coord - camera.y, tex_sonic_stand, 0,1,1,GRRLIB_WHITE,sonic_obj.frame);
  363. GRRLIB_Rectangle(pointer.x, pointer.y, 80, 2, GRRLIB_RED, true);
  364.  
  365. // second level render pass goes here.
  366.  
  367. // Drawing HUD - this will need to get moved to the end of the drawchain to show up
  368. // on top of everything else
  369. sprintf(score_string, "Score: %d", sonic_obj.score);
  370. sprintf(time_string, "Time: %d:%d:%d", minutecounter,secondcounter,framecounter);
  371. sprintf(ring_string, "Rings: %d", sonic_obj.rings);
  372. GRRLIB_PrintfTTF(32,32, font1, score_string, 26, GRRLIB_WHITE);
  373. GRRLIB_PrintfTTF(32,64, font1, time_string, 26, GRRLIB_WHITE);
  374. GRRLIB_PrintfTTF(32,98, font1, ring_string, 26, GRRLIB_WHITE);
  375.  
  376. if (debugflag == true)
  377. {
  378. sprintf(debug_ln1, "x: %d", camera.x);
  379. sprintf(debug_ln2, "y: %d", camera.y);
  380. sprintf(debug_ln3, "tile: %d:%d", camera.in_tile[0], camera.in_tile[1]);
  381. GRRLIB_PrintfTTF(420,32, font1, debug_ln1, 26, GRRLIB_WHITE);
  382. GRRLIB_PrintfTTF(420,64, font1, debug_ln2, 26, GRRLIB_WHITE);
  383. GRRLIB_PrintfTTF(420,98, font1, debug_ln3, 26, GRRLIB_WHITE);
  384. }
  385.  
  386. if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) break;
  387. if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_A) GRRLIB_ScrShot("screenshot.png");
  388.  
  389. GRRLIB_Render();
  390. }
  391. return;
  392. }
  393.  
  394. int main(int argc, char **argv)
  395. {
  396. // Initialise the Graphics & Video subsystem
  397. GRRLIB_Init();
  398.  
  399. // Initialise the Wiimotes
  400. WPAD_Init();
  401. WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);
  402.  
  403. GameLoop();
  404.  
  405. GRRLIB_Exit(); // Be a good boy, clear the memory allocated by GRRLIB
  406.  
  407. exit(0); // Use exit() to exit a program, do not use 'return' from main()
  408. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement