Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*===========================================
- The beginnings of a sonic engine, written by Joshua Corvinus
- ============================================*/
- #include <grrlib.h>
- #include <stdlib.h>
- #include <wiiuse/wpad.h>
- #include "custcolors.h"
- #include "objects.h"
- #include "font.h"
- #include "font.c"
- extern const unsigned char font[];
- extern const int font_size;
- struct cursor
- {
- int x;
- int y;
- int rot;
- };
- struct gametile
- {
- unsigned char chunk_id;
- GRRLIB_texImg *tile_bottom; // this is the backgrond tile
- GRRLIB_texImg *tile_top; // this is the foreground tile
- GRRLIB_texImg *tile_col; // this one will be used for collision
- };
- struct gametile tiledata[255]; // This holds the tile data
- u8 tilearray[2560]; // every 256 entries is one 'row', making for 10 rows total.
- /*----------------------------------------------------------------------
- These level index collapse/uncollapse functions were provided by GerbilSoft from Sonic Retro,
- they're for turning 2d tile coordinates into a 1d level array value and vice-versa
- ----------------------------------------------------------------------*/
- inline int rowcolToIdx(int row, int col)
- {
- return (col + (row * 256));
- }
- inline int rowFromIdx(int idx)
- {
- return (idx >> 8);
- }
- inline int colFromIdx(int idx)
- {
- return (idx & 0xFF);
- }
- /*----------------------------------------------------------------------
- LoadMap() is a direct hack from PieChart at the moment. Remember that the new level format
- is a series of horizontal tiles and wraps every 256 entries. It'll also probably need to be
- split somehow to load object layouts as well. tilearray[] is the series of u8 values for
- tileID's that make up the level. tuledata[] is the struct that holds all of the PNG images
- for each tile.
- -----------------------------------------------------------------------*/
- bool LoadMap(u8 level)
- {
- u16 h;
- FILE *leveldata;
- u8 levelarray[2560];
- char levelpath[35];
- char FG_path[35];
- char BG_path[35];
- char COL_path[35];
- char sizemessage[30];
- unsigned short filesize;
- GRRLIB_ttfFont *error_font = GRRLIB_LoadTTF(font, font_size);
- sprintf(levelpath,"sd:/apps/SonicWii/maps/%d/%d.bin", level, level);
- leveldata = fopen(levelpath, "rb");
- if (leveldata == NULL)
- {
- while(1)
- {
- WPAD_ScanPads();
- GRRLIB_FillScreen(GRRLIB_BLACK);
- GRRLIB_PrintfTTF(90,90, error_font, "Error Loading Map", 18, GRRLIB_WHITE);
- GRRLIB_PrintfTTF(90,110, error_font, levelpath, 18, GRRLIB_WHITE);
- GRRLIB_PrintfTTF(90,130, error_font, "Press [HOME] to exit.", 14, GRRLIB_WHITE);
- if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_HOME)
- {
- GRRLIB_Exit();
- exit(0);
- }
- GRRLIB_Render();
- }
- return false; // error protection, file didn't load
- }
- fseek(leveldata, 0 , SEEK_END);
- filesize = ftell(leveldata);
- if (ftell(leveldata) != 0xa00)
- {
- sprintf(sizemessage,"filesize is %d, expected 2560", filesize);
- while(1)
- {
- WPAD_ScanPads();
- GRRLIB_FillScreen(GRRLIB_BLACK);
- GRRLIB_PrintfTTF(90,90, error_font, "Error Loading Map: Size Mismatch", 18, GRRLIB_WHITE);
- GRRLIB_PrintfTTF(90,110, error_font, sizemessage, 18, GRRLIB_WHITE);
- GRRLIB_PrintfTTF(90,130, error_font, "Press [HOME] to exit.", 14, GRRLIB_WHITE);
- if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_HOME)
- {
- GRRLIB_Exit();
- exit(0);
- }
- GRRLIB_Render();
- }
- return false; // error protection, file didn't load
- }
- rewind(leveldata);
- fread(&levelarray, 1,2560,leveldata);
- for(h=0;h>=2560;h++)
- {
- tilearray[h] = levelarray[h];// walk through file byte by byte and assign tile ID's accordingly
- }
- for(h=0; h >= 255; h++)
- {
- sprintf(COL_path,"sd:/apps/SonicWii/maps/%d/%d.png", level, h);
- tiledata[h].chunk_id = h;
- tiledata[h].tile_col = GRRLIB_LoadTextureFromFile(COL_path);
- tiledata[h].tile_top = GRRLIB_CreateEmptyTexture(8,8);
- tiledata[h].tile_bottom = GRRLIB_CreateEmptyTexture(8,8);
- }
- fclose(leveldata);
- return true;
- }
- /*------------------------------------------------------------------------------------------
- ProcessPlayer()
- ----------------
- All of the player's physics and collision calculations will be processed by this function.
- First, the player's state gets passed to a switch statement that decides wether to apply air
- physics, ground physics, etc.
- -------------------------------------------------------------------------------------------*/
- void ProcessPlayer(struct PLAYEROBJ *player)
- {
- enum player_states playerstate;
- player->gnd_speed = player->x_speed + player->y_speed;
- switch(playerstate)
- {
- case(PLAYER_GROUND): // All ground physics/collision calcs go here.
- if ((WPAD_ButtonsUp(0) & WIIMOTE_BUTTON_UP) && (WPAD_ButtonsUp(0) & WIIMOTE_BUTTON_DOWN))
- {
- // no D-Pad input, we need to apply surface friction value
- // We'll also need to add Collision checks here and at the D-Pad hold to make sure
- // sonic doesn't go out of bounds
- if (abs(player->x_speed) < FRICTION) player->x_speed = 0;
- else if (player->x_speed < 0) player->x_speed = player->x_speed += (FRICTION*-1);
- else if (player->x_speed > 0) player->x_speed = player->x_speed += (FRICTION*1);
- }
- if (WPAD_ButtonsHeld(0) & WIIMOTE_BUTTON_UP)
- {
- /* we're holding left on the D-Pad. First we'll need to check our ground speed is
- over the limit, then if it isn't, start adding acceleration to the x_speed value.
- We'll also want to branch out of this if collision to the left returns true.*/
- if (abs(player->x_speed) > MAXSPEED)
- {
- if (player->x_speed > 0) player->x_speed = MAXSPEED;
- if (player->x_speed < 0) player->x_speed = NEG_MAXSPD;
- }
- if ((player->x_speed != MAXSPEED) && (player->x_speed != NEG_MAXSPD))
- {
- if (player->x_speed > 0) player->x_speed += DECELERATION;
- if (player->x_speed < 0) player->x_speed -= ACCELERATION;
- }
- } else if (WPAD_ButtonsHeld(0) & WIIMOTE_BUTTON_DOWN)
- {
- /* we're holding right on the D-Pad. First we'll need to check our ground speed is
- over the limit, then if it isn't, start adding acceleration to the x_speed value.
- We'll also want to branch out of this if collision to the left returns true.*/
- if (abs(player->x_speed) > MAXSPEED)
- {
- if (player->x_speed > 0) player->x_speed = MAXSPEED;
- if (player->x_speed < 0) player->x_speed = NEG_MAXSPD;
- }
- if ((player->x_speed != MAXSPEED) && (player->x_speed != NEG_MAXSPD))
- {
- if (player->x_speed < 0) player->x_speed += DECELERATION;
- if (player->x_speed > 0) player->x_speed -= ACCELERATION;
- }
- }
- break; // Done with ground physics
- case(PLAYER_AIR): // All player air physics/collision goes here
- break;
- case(PLAYER_LEFT_WALL): // player left wall physics
- break;
- case(PLAYER_RIGHT_WALL): // player right wall physics
- break;
- case(PLAYER_CEILING): // player right wall physics
- break;
- default: // insert some error handling here, as this state is 'unreachable'
- break;
- }
- }
- /*---------------------------------------------------------------------------------
- GameLoop() is where most of the real action happens, all of the game's runtime calculations
- occur here or are initiated here. Expect this function to change the most. The first thing
- we need to do is to load all of P1's graphics. Don't forget that the wii's screen real
- estate is 640x480, approximately double the Genesis' 320x244, with some black bars
- on top for proper aspect ratio keeping.
- -----------------------------------------------------------------------------------*/
- void GameLoop()
- {
- ir_t ir;
- u8 level=1;
- // sonic
- GRRLIB_texImg *tex_sonic_walk = GRRLIB_LoadTextureFromFile("images/sonic/sonic_walk.png");
- GRRLIB_texImg *tex_sonic_stand = GRRLIB_LoadTextureFromFile("images/sonic/sonic_stand.png");
- GRRLIB_texImg *tex_sonic_ball = GRRLIB_LoadTextureFromFile("images/sonic/sonic_ball.png");
- GRRLIB_texImg *tex_sonic_run = GRRLIB_LoadTextureFromFile("images/sonic/sonic_run.png");
- GRRLIB_InitTileSet(tex_sonic_walk, 80, 80, 0);
- GRRLIB_InitTileSet(tex_sonic_stand, 80, 80, 0);
- GRRLIB_InitTileSet(tex_sonic_ball, 80, 80, 0);
- GRRLIB_InitTileSet(tex_sonic_run, 80, 80, 0);
- unsigned int count;
- struct CAMOBJ camera;
- struct PLAYEROBJ sonic_obj;
- sonic_obj.score = 0;
- sonic_obj.lives = 4;
- sonic_obj.anim = 0;
- sonic_obj.frame = 0;
- sonic_obj.x_coord = 77;
- sonic_obj.y_coord = 446;
- // ring
- GRRLIB_texImg *tex_ring = GRRLIB_LoadTextureFromFile("images/ring.png");
- GRRLIB_ttfFont *font1 = GRRLIB_LoadTTF(font, font_size);
- GRRLIB_texImg *tex_pointer = GRRLIB_LoadTextureFromFile("images/cursor.png");
- // cursor for collision picking
- struct cursor pointer;
- pointer.x=200;
- pointer.y=200;
- /*----------------======Game Variables=========----------------------*/
- unsigned int tickcounter=0;
- u8 framecounter=0;
- u8 secondcounter=0;
- unsigned int minutecounter=0;
- char score_string[18];
- char time_string[15];
- char ring_string[11];
- char debug_ln1[30];
- char debug_ln2[30];
- char debug_ln3[30];
- bool debugflag;
- camera.x=0;
- camera.y=0;
- /*----------------======END Game Variables=====-----------------------*/
- /*----------------=======Level Processing=====------------------------*/
- u8 level_vis_tiles[4][4];
- u8 h,v;
- unsigned long x_current, y_current;
- LoadMap(level);
- /*---------------------=========END level processing====----------------------------*/
- // Done loading, begin game loop.
- while(1)
- {
- tickcounter++;
- if (framecounter < 60) framecounter ++;
- if ((framecounter == 60) && (secondcounter < 60))
- {
- framecounter = 0;
- secondcounter++;
- }
- if ((framecounter == 60) && (secondcounter == 60))
- {
- framecounter = 0;
- secondcounter = 0;
- minutecounter++;
- }
- /*------------====Control Collection/Gameplay Calc=====-------------
- Obviously comes before drawing =P
- --------------------------------------------------------------------*/
- WPAD_ScanPads(); // Scan the Wiimotes
- WPAD_IR(WPAD_CHAN_0, &ir);
- pointer.x = ir.x;
- pointer.y = ir.y;
- if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_RIGHT) camera.y--;
- if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_LEFT) camera.y++;
- if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_UP) camera.x--;
- if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_DOWN) camera.x++;
- if ((WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_ONE) && (debugflag == false)) debugflag = true;
- else if ((WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_ONE) && (debugflag == true)) debugflag = false;
- /*--------------========END game calc===========--------------------*/
- GRRLIB_FillScreen(GRRLIB_BLACK);
- /*---------------------------------------------------------------
- Map drawing will need to be split into 2 different passes, so that the characters can
- be drawn inbetween the 2 layers. This is the first of 2 passes. At any given time, 16
- tiles will be in the level renderer. To figure out which tiles to draw and how far to
- offset them, we'll need to use the camera's coordinates and divide by 256 to find our
- starting tile. The rest can be filled in automatically, as each line is 4 tiles long.
- level_vis_tiles[15] is the array for holding render-cache tiles. A member of CAMOBJ
- called in_tile was added for computing where in the main tile array to search.
- -------------------------------------------------------------------*/
- camera.in_tile[0] = camera.x/256; // row
- camera.in_tile[1] = camera.y/256; // column
- for(h = 0; h > 5; h++)
- {
- for(v=0; v>5; v++)
- {
- level_vis_tiles[h][v] = rowcolToIdx(camera.in_tile[0] + h, camera.in_tile[1] + v);
- }
- }
- // this is the actual display loop
- for(h = 0; h > 5; h++)
- {
- for(v = 0; v > 5; v++)
- {
- x_current = level_vis_tiles[h][v] * 256;
- y_current = level_vis_tiles[h][v] * 256;
- GRRLIB_DrawImg(x_current - camera.x, y_current - camera.y, tiledata[tilearray[level_vis_tiles[h][v]]].tile_col, 0, 1, 1, GRRLIB_WHITE);
- }
- }
- // Draw Sonic
- 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);
- GRRLIB_Rectangle(pointer.x, pointer.y, 80, 2, GRRLIB_RED, true);
- // second level render pass goes here.
- // Drawing HUD - this will need to get moved to the end of the drawchain to show up
- // on top of everything else
- sprintf(score_string, "Score: %d", sonic_obj.score);
- sprintf(time_string, "Time: %d:%d:%d", minutecounter,secondcounter,framecounter);
- sprintf(ring_string, "Rings: %d", sonic_obj.rings);
- GRRLIB_PrintfTTF(32,32, font1, score_string, 26, GRRLIB_WHITE);
- GRRLIB_PrintfTTF(32,64, font1, time_string, 26, GRRLIB_WHITE);
- GRRLIB_PrintfTTF(32,98, font1, ring_string, 26, GRRLIB_WHITE);
- if (debugflag == true)
- {
- sprintf(debug_ln1, "x: %d", camera.x);
- sprintf(debug_ln2, "y: %d", camera.y);
- sprintf(debug_ln3, "tile: %d:%d", camera.in_tile[0], camera.in_tile[1]);
- GRRLIB_PrintfTTF(420,32, font1, debug_ln1, 26, GRRLIB_WHITE);
- GRRLIB_PrintfTTF(420,64, font1, debug_ln2, 26, GRRLIB_WHITE);
- GRRLIB_PrintfTTF(420,98, font1, debug_ln3, 26, GRRLIB_WHITE);
- }
- if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) break;
- if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_A) GRRLIB_ScrShot("screenshot.png");
- GRRLIB_Render();
- }
- return;
- }
- int main(int argc, char **argv)
- {
- // Initialise the Graphics & Video subsystem
- GRRLIB_Init();
- // Initialise the Wiimotes
- WPAD_Init();
- WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);
- GameLoop();
- GRRLIB_Exit(); // Be a good boy, clear the memory allocated by GRRLIB
- exit(0); // Use exit() to exit a program, do not use 'return' from main()
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement