View difference between Paste ID: iApiBywT and
SHOW: | | - or go back to the newest paste.
1-
1+
/*===========================================
2
        GRRLIB (GX Version)
3
        - Template Code -
4
5
        Minimum Code To Use GRRLIB
6
============================================*/
7
#include <grrlib.h>
8
9
#include <stdlib.h>
10
#include <wiiuse/wpad.h>
11
12
#include "custcolors.h"
13
#include "objects.h"
14
#include "font.h"
15
#include "font.c"
16
17
extern const unsigned char font[];
18
extern const int font_size;
19
20
struct cursor
21
{
22
	int x;
23
	int y;
24
	int rot;
25
};
26
27
struct gametile
28
{
29
	unsigned char chunk_id;
30
	GRRLIB_texImg *tile_bottom; // this is the backgrond tile
31
	GRRLIB_texImg *tile_top; // this is the foreground tile
32
	GRRLIB_texImg *tile_col; // this one will be used for collision
33
};
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
struct gametile tiledata[256]; // This holds the tile structure data
64
u8 tilearray[10][256];
65
66
bool LoadMap(u8 level)
67
{
68
	u16 h;
69
	FILE *leveldata;
70
	//u8 levelarray[2560];
71
	char levelpath[35];
72
	char FG_path[35];
73
	char BG_path[35];
74
	char COL_path[35];
75
	char sizemessage[30];
76
	unsigned short filesize;
77
	GRRLIB_texImg *tex_load = GRRLIB_LoadTextureFromFile("images/loading.png");	
78
	GRRLIB_ttfFont *error_font = GRRLIB_LoadTTF(font, font_size);
79
	
80
	sprintf(levelpath,"sd:/apps/SonicWii/maps/%d/%d.bin", level, level);
81
	GRRLIB_FillScreen(GRRLIB_BLACK);
82
	GRRLIB_DrawImg(140, 300, tex_load, 0,1,1,GRRLIB_WHITE);
83
	GRRLIB_Render();
84
	
85
	leveldata = fopen(levelpath, "rb");
86
	
87
	if (leveldata == NULL)
88
	{
89
		while(1)
90
		{
91
			WPAD_ScanPads();
92
			GRRLIB_FillScreen(GRRLIB_BLACK);
93
			GRRLIB_PrintfTTF(90,90, error_font, "Error Loading Map", 18, GRRLIB_WHITE);
94
			GRRLIB_PrintfTTF(90,110, error_font, levelpath, 18, GRRLIB_WHITE);
95
			GRRLIB_PrintfTTF(90,130, error_font, "Press [HOME] to exit.", 14, GRRLIB_WHITE);
96
			
97
			if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_HOME) 
98
			{
99
				GRRLIB_Exit();
100
				exit(0);
101
			}
102
			GRRLIB_Render();
103
		}
104
		return false; // error protection, file didn't load
105
	}
106
	
107
	/*if (false) // old tile debugging routine. Use for checking GRRLIB_LoadTextureFromFile
108
	{
109
		tile_error:
110
		while(1)
111
		{
112
			WPAD_ScanPads();
113
			GRRLIB_FillScreen(GRRLIB_BLACK);
114
			GRRLIB_PrintfTTF(90,90, error_font, "Error Loading Tile", 18, GRRLIB_WHITE);
115
			GRRLIB_PrintfTTF(90,110, error_font, COL_path, 18, GRRLIB_WHITE);
116
			GRRLIB_PrintfTTF(90,130, error_font, "Press [HOME] to exit.", 14, GRRLIB_WHITE);
117
			
118
			if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_HOME) 
119
			{
120
				GRRLIB_Exit();
121
				exit(0);
122
			}
123
			GRRLIB_Render();
124
		}
125
		return false; // error protection, file didn't load
126
	}*/
127
128
	fseek(leveldata, 0 , SEEK_END);
129
	filesize = ftell(leveldata);
130
	if (ftell(leveldata) != 0xa00)
131
	{
132
		sprintf(sizemessage,"filesize is %d, expected 2560", filesize);
133
		while(1)
134
		{
135
			WPAD_ScanPads();
136
			GRRLIB_FillScreen(GRRLIB_BLACK);
137
			GRRLIB_PrintfTTF(90,90, error_font, "Error Loading Map: Size Mismatch", 18, GRRLIB_WHITE);
138
			GRRLIB_PrintfTTF(90,110, error_font, sizemessage, 18, GRRLIB_WHITE);
139
			GRRLIB_PrintfTTF(90,130, error_font, "Press [HOME] to exit.", 14, GRRLIB_WHITE);
140
			
141
			if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_HOME) 
142
			{
143
				GRRLIB_Exit();
144
				exit(0);
145
			}
146
			GRRLIB_Render();
147
		}
148
		return false; // error protection, file didn't load
149
	}
150
	
151
	rewind(leveldata);
152
	fread(&tilearray, 1,2560,leveldata);
153
	
154
	/*for(h=0;h < 2560;h++)
155
	{
156
		tilearray[h] = levelarray[h];// walk through file byte by byte and assign tile ID's accordingly
157
	}*/
158
	
159
	for(h=0; h <= 255; h++)
160
	{
161
		sprintf(COL_path,"maps/%d/%02d.png", level, h);
162
		tiledata[h].chunk_id = h;		
163
		if (GRRLIB_LoadTextureFromFile(COL_path) != NULL) 
164
		{
165
			tiledata[h].tile_col = GRRLIB_LoadTextureFromFile(COL_path);
166
			//GRRLIB_InitTileSet(tiledata[h].tile_col, 256, 256, 0);
167
		}
168
		/*tiledata[h].tile_top = GRRLIB_CreateEmptyTexture(2,2);
169
		tiledata[h].tile_bottom = GRRLIB_CreateEmptyTexture(2,2);*/
170
	}
171
	
172
	fclose(leveldata);
173
	return true;
174
}
175
176
/*------------------------------------------------------------------------------------------
177
	ProcessPlayer()
178
	----------------
179
	All of the player's physics and collision calculations will be processed by this function.
180
	First, the player's state gets passed to a switch statement that decides wether to apply air
181
	physics, ground physics, etc.
182
-------------------------------------------------------------------------------------------*/
183
184
void ProcessPlayer(struct PLAYEROBJ *player)
185
{
186
	enum player_states playerstate;
187
	
188
	player->gnd_speed = player->x_speed + player->y_speed;
189
190
	switch(playerstate)
191
	{
192
		case(PLAYER_GROUND): // All ground physics/collision calcs go here.
193
			if ((WPAD_ButtonsUp(0) & WIIMOTE_BUTTON_UP) && (WPAD_ButtonsUp(0) & WIIMOTE_BUTTON_DOWN))
194
			{
195
				// no D-Pad input, we need to apply surface friction value
196
				// We'll also need to add Collision checks here and at the D-Pad hold to make sure
197
				// sonic doesn't go out of bounds
198
				if (abs(player->x_speed) < FRICTION) player->x_speed = 0;
199
				else if (player->x_speed < 0) player->x_speed = player->x_speed += (FRICTION*-1);
200
				else if (player->x_speed > 0) player->x_speed = player->x_speed += (FRICTION*1);
201
			}
202
			
203
			if (WPAD_ButtonsHeld(0) & WIIMOTE_BUTTON_UP)
204
			{
205
				/* we're holding left on the D-Pad. First we'll need to check our ground speed is
206
				over the limit, then if it isn't, start adding acceleration to the x_speed value.
207
				We'll also want to branch out of this if collision to the left returns true.*/
208
				if (abs(player->x_speed) > MAXSPEED)
209
				{
210
					if (player->x_speed > 0) player->x_speed = MAXSPEED;
211
					if (player->x_speed < 0) player->x_speed = NEG_MAXSPD;
212
				}
213
				
214
				if ((player->x_speed != MAXSPEED) && (player->x_speed != NEG_MAXSPD))
215
				{
216
					if (player->x_speed > 0) player->x_speed += DECELERATION;
217
					if (player->x_speed < 0) player->x_speed -= ACCELERATION;
218
				}
219
			} else if (WPAD_ButtonsHeld(0) & WIIMOTE_BUTTON_DOWN)
220
			{
221
				/* we're holding right on the D-Pad. First we'll need to check our ground speed is
222
				over the limit, then if it isn't, start adding acceleration to the x_speed value.
223
				We'll also want to branch out of this if collision to the left returns true.*/
224
				if (abs(player->x_speed) > MAXSPEED)
225
				{
226
					if (player->x_speed > 0) player->x_speed = MAXSPEED;
227
					if (player->x_speed < 0) player->x_speed = NEG_MAXSPD;
228
				}
229
				
230
				if ((player->x_speed != MAXSPEED) && (player->x_speed != NEG_MAXSPD))
231
				{
232
					if (player->x_speed < 0) player->x_speed += DECELERATION;
233
					if (player->x_speed > 0) player->x_speed -= ACCELERATION;
234
				}
235
			}
236
			break; // Done with ground physics
237
		
238
		case(PLAYER_AIR): // All player air physics/collision goes here
239
		break;
240
		
241
		case(PLAYER_LEFT_WALL): // player left wall physics
242
		break;
243
		
244
		case(PLAYER_RIGHT_WALL): // player right wall physics
245
		break;
246
		
247
		case(PLAYER_CEILING): // player right wall physics
248
		break;
249
		
250
		default: // insert some error handling here, as this state is 'unreachable'
251
		break;
252
	}
253
}
254
255
/*---------------------------------------------------------------------------------
256
	GameLoop() is where most of the real action happens, all of the game's runtime calculations
257
	occur here or are initiated here. Expect this function to change the most. The first thing
258
	we need to do is to load all of P1's graphics. Don't forget that the wii's screen real
259
	estate is 640x480, approximately double the Genesis' 320x244, with some black bars 
260
	on top for proper aspect ratio keeping.
261
-----------------------------------------------------------------------------------*/
262
void GameLoop()
263
{
264
	ir_t ir;
265
	u8 level=1;
266
	
267
	// sonic	
268
	GRRLIB_texImg *tex_sonic_walk = GRRLIB_LoadTextureFromFile("images/sonic/sonic_walk.png");
269
	GRRLIB_texImg *tex_sonic_stand = GRRLIB_LoadTextureFromFile("images/sonic/sonic_stand.png");
270
	GRRLIB_texImg *tex_sonic_ball = GRRLIB_LoadTextureFromFile("images/sonic/sonic_ball.png");
271
	GRRLIB_texImg *tex_sonic_run = GRRLIB_LoadTextureFromFile("images/sonic/sonic_run.png");
272
	GRRLIB_InitTileSet(tex_sonic_walk, 80, 80, 0);
273
	GRRLIB_InitTileSet(tex_sonic_stand, 80, 80, 0);
274
	GRRLIB_InitTileSet(tex_sonic_ball, 80, 80, 0);
275
	GRRLIB_InitTileSet(tex_sonic_run, 80, 80, 0);
276
	unsigned int count;
277
	struct CAMOBJ camera;
278
	struct PLAYEROBJ sonic_obj;
279
	sonic_obj.score = 0;
280
	sonic_obj.lives = 4;
281
	sonic_obj.anim = 0;
282
	sonic_obj.frame = 0;
283
	sonic_obj.x_coord = 368;
284
	sonic_obj.y_coord = 434;
285
	
286
	// ring
287
	GRRLIB_texImg *tex_ring = GRRLIB_LoadTextureFromFile("images/ring.png");	
288
	GRRLIB_ttfFont *font1 = GRRLIB_LoadTTF(font, font_size);
289
	GRRLIB_texImg *tex_pointer = GRRLIB_LoadTextureFromFile("images/cursor.png");
290
	
291
	// cursor for collision picking
292
	struct cursor pointer;
293
	pointer.x=200;
294
	pointer.y=200;
295
	
296
	/*----------------======Game Variables=========----------------------*/
297
	unsigned int tickcounter=0;
298
	u8 framecounter=0;
299
	u8 secondcounter=0;
300
	unsigned int minutecounter=0;	
301
	char time_string[15]="";
302
	char debug_ln1[30]="";
303
	char debug_ln2[30]="";
304
	char debug_ln3[30]="";
305
	char debug_ln4[30]="";
306
	bool debugflag=false;
307
	bool mapflag=false;
308
	camera.x=6;
309
	camera.y=222;
310
	sonic_obj.score = 0;
311
	sonic_obj.rings = 0;
312
	
313
	sprintf(sonic_obj.score_string, "Score: %d", sonic_obj.score);
314
	sprintf(sonic_obj.ring_string, "Rings: %d", sonic_obj.rings);
315
	/*----------------======END Game Variables=====-----------------------*/
316
	
317
	
318
	/*----------------=======Level Processing=====------------------------*/
319
	unsigned int vis_tiles[4][4];
320
	unsigned int first_tile[2];
321
	unsigned int x_current,y_current;
322
	unsigned short h,v;
323
	LoadMap(level);
324
	/*---------------------=========END level processing====----------------------------*/	
325
	
326
	// Done loading, begin game loop.
327
	while(1)
328
	{
329
		tickcounter++;
330
		
331
		if (framecounter < 60) framecounter ++;
332
	
333
		if ((framecounter == 60) && (secondcounter < 60))
334
		{
335
			framecounter = 0;
336
			secondcounter++;
337
		}
338
		
339
		if ((framecounter == 60) && (secondcounter == 60)) 
340
		{
341
			framecounter = 0;
342
			secondcounter = 0;
343
			minutecounter++;
344
		}
345
		
346
		/*------------====Control Collection/Gameplay Calc=====-------------
347
		Obviously comes before drawing =P
348
		--------------------------------------------------------------------*/
349
		WPAD_ScanPads();  // Scan the Wiimotes
350
		WPAD_IR(WPAD_CHAN_0, &ir);
351
		
352
		pointer.x = ir.x;
353
		pointer.y = ir.y;
354
		
355
		if ((WPAD_ButtonsHeld(0) & WPAD_BUTTON_RIGHT) && (camera.y >= 1)) camera.y--;
356
		else if ((WPAD_ButtonsHeld(0) & WPAD_BUTTON_RIGHT) && (camera.y == 0)) camera.y = 0;
357
		
358
		if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_LEFT) camera.y++;
359
		
360
		if ((WPAD_ButtonsHeld(0) & WPAD_BUTTON_UP) && (camera.x >= 1)) camera.x--;		
361
		else if((WPAD_ButtonsHeld(0) & WPAD_BUTTON_UP) && (camera.x == 0))  camera.x = 0;
362
		
363
		if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_DOWN) camera.x++;
364
		
365
		if ((WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_ONE)) debugflag = !debugflag;
366
		
367
		if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_TWO) mapflag = true;
368
		
369
		/*--------------========END game calc===========--------------------*/
370
		
371
		GRRLIB_FillScreen(GRRLIB_BLACK);
372
		
373
		/*---------------------------------------------------------------
374
		Map drawing will need to be split into 2 different passes, so that the characters can
375
		be drawn inbetween the 2 layers. This is the first of 2 passes. At any given time, 16
376
		tiles will be in the level renderer. To figure out which tiles to draw and how far to
377
		offset them, we'll need to use the camera's coordinates and divide by 256 to find our
378
		starting tile. The rest can be filled in automatically, as each line is 4 tiles long.
379
		4 arrays were created for holding this render queue, named "vis_tiles_x[4]" 
380
		respectively. A member of CAMOBJ called in_tile was added for computing where in the 
381
		main tile array to search.
382
		-------------------------------------------------------------------*/
383
		// first we fill our screen cache
384
		camera.in_tile[0] = camera.x/256; // row
385
		camera.in_tile[1] = camera.y/256; // column		
386
		
387
		first_tile[0] = camera.in_tile[0];
388
		first_tile[1] = camera.in_tile[1];
389
		
390
		for(h=0; h < 4; h++) // first row
391
		{
392
			for(v=0; v < 4; v++)
393
			{
394
				vis_tiles[h][v] = tilearray[first_tile[1] + v][first_tile[0] + h];
395
			}
396
		}
397
		
398
		// this is the actual display loop, first pass
399
		for(h = 0; h < 4; h++)
400
		{
401
			for(v=0; v < 4; v++)
402
			{
403
				x_current = (first_tile[0] + h) * 256;
404
				y_current = (first_tile[1] + v) * 256;
405
				GRRLIB_DrawImg(x_current - camera.x, y_current - camera.y, tiledata[vis_tiles[h][v]].tile_col, 0, 1, 1, GRRLIB_WHITE);
406
			}
407
		}
408
		
409
		// Draw Sonic 
410
		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);
411
		GRRLIB_Rectangle(pointer.x, pointer.y, 4, 4, GRRLIB_RED, true);
412
		
413
		// second level render pass goes here.
414
		
415
		// Drawing HUD - this will need to get moved to the end of the drawchain to show up
416
		// on top of everything else
417
		sprintf(time_string, "Time: %d:%d:%d", minutecounter,secondcounter,framecounter);
418
		GRRLIB_PrintfTTF(32,32, font1, sonic_obj.score_string, 26, GRRLIB_WHITE);
419
		GRRLIB_PrintfTTF(32,64, font1, time_string, 26, GRRLIB_WHITE);
420
		GRRLIB_PrintfTTF(32,98, font1, sonic_obj.ring_string, 26, GRRLIB_WHITE);
421
		
422
		if ((debugflag == true) && (mapflag == false))
423
		{
424
			sprintf(debug_ln1, "x: %d", camera.x);
425
			sprintf(debug_ln2, "y: %d", camera.y);
426
			sprintf(debug_ln3, "it: %d:%d | %d x %d", camera.in_tile[0], camera.in_tile[1], (camera.x % 256), (camera.y % 256));
427
			GRRLIB_PrintfTTF(420,32, font1, debug_ln1, 18, GRRLIB_RED);
428
			GRRLIB_PrintfTTF(420,64, font1, debug_ln2, 18, GRRLIB_RED);
429
			GRRLIB_PrintfTTF(420,98, font1, debug_ln3, 18, GRRLIB_RED);
430
		}
431
		
432
		while (mapflag == true)
433
		{
434
			WPAD_ScanPads();
435
			debugflag = false;
436
			sprintf(debug_ln1, "%d | %d | %d | %d", vis_tiles[0][0], vis_tiles[1][0], vis_tiles[2][0], vis_tiles[3][0]);
437
			sprintf(debug_ln2, "%d | %d | %d | %d", vis_tiles[0][1], vis_tiles[1][1], vis_tiles[2][1], vis_tiles[3][1]);
438
			sprintf(debug_ln3, "%d | %d | %d | %d", vis_tiles[0][2], vis_tiles[1][2], vis_tiles[2][2], vis_tiles[3][2]);
439
			sprintf(debug_ln4, "%d | %d | %d | %d", vis_tiles[0][3], vis_tiles[1][3], vis_tiles[2][3], vis_tiles[3][3]);
440
			GRRLIB_PrintfTTF(50,32, font1, debug_ln1, 22, GRRLIB_WHITE);
441
			GRRLIB_PrintfTTF(50,64, font1, debug_ln2, 22, GRRLIB_WHITE);
442
			GRRLIB_PrintfTTF(50,98, font1, debug_ln3, 22, GRRLIB_WHITE);
443
			//GRRLIB_PrintfTTF(50,130, font1, debug_ln4, 22, GRRLIB_WHITE);
444
			
445
			if (WPAD_ButtonsHeld(0) & WIIMOTE_BUTTON_ONE)
446
			{
447
				mapflag = false;
448
				break;
449
			} else if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_HOME) 
450
			{
451
				GRRLIB_Exit();
452
				exit(0);
453
			}
454
			
455
			GRRLIB_Render();
456
		}
457
		
458
		
459
		if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) break;
460
		if (WPAD_ButtonsDown(0) & WIIMOTE_BUTTON_A) GRRLIB_ScrShot("screenshot.png");
461
		
462
		GRRLIB_Render();
463
	}
464
	return;
465
}
466
467
int main(int argc, char **argv) 
468
{
469
    // Initialise the Graphics & Video subsystem
470
    GRRLIB_Init();
471
472
    // Initialise the Wiimotes
473
    WPAD_Init();
474
	WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);
475
476
	GameLoop();
477
	
478
    GRRLIB_Exit(); // Be a good boy, clear the memory allocated by GRRLIB
479
480
    exit(0);  // Use exit() to exit a program, do not use 'return' from main()
481
}