⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gamewnd.c

📁 《深入BREW&#61650 手机游戏开发》附录光盘例2——Chapter12.rar
💻 C
字号:
#include "GameWnd.h"

#include "AEEStdLib.h"
#include "AEEAppGen.h"

#include "pfly_res.h"
#include "pfly.h"
#include "commondef.h"

#define MAX_HEIGHT			12800
#define WALL_START_POS_Y	150
#define SCORE_START_X		9
#define DIGIT_WEIGHT		7		

//rgCmds中各种对象的索引
#define SPRITE_DIGIT		8
#define SPRITE_PLANE		12

//各种对象的源图像贴索引
#define PIC_START_DIGIT		15
#define PIC_START_WALL		13

//纸飞机在不同飞行角度下的速度表
static const uint16 speedTableX[] = {-4, -3, -3, -2, -1, 0, 1, 2, 3, 3, 4};
static const uint16 speedTableY[] = { 3,  3,  4,  4,  5, 6, 5, 4, 4, 3, 3}; 

static int GameWnd_LoadResources(GameWnd *pthis);
static void GameWnd_UnloadResources(GameWnd *pthis);
static boolean GameWnd_HandleKeyEvent(GameWnd *pthis, AEEEvent eCode, uint16 wParam);
static void GameWnd_NextFrame(GameWnd *pthis);
static boolean GameWnd_IsCrash(GameWnd *pthis);
static void GameWnd_LoadSprites(GameWnd *pthis, const char * pszFile, 
				uint16 resID, uint8 unSpriteSize, boolean isTile);
static int16 Random(int16 range);

boolean GameWnd_New(GameWnd *pthis, PflyApp* pMe)
{
	pthis->pMe = pMe;

	return TRUE;
}

boolean GameWnd_HandleEvent(GameWnd * pthis, AEEEvent eCode, uint16 wParam, uint32 dwParam)
{
	switch (eCode) {
	case EVT_APP_SUSPEND:
		CALLBACK_Cancel(&pthis->cbTimer);
		return TRUE;
		
	case EVT_APP_RESUME:
		ISHELL_SetTimerEx(pthis->pMe->a.m_pIShell, 0, &pthis->cbTimer);
		return TRUE;
		
	case EVT_APP_NO_SLEEP:
		// catching this event prevent BREW from going to "sleep"
		return TRUE;
		
	default:
		return GameWnd_HandleKeyEvent(pthis, eCode, wParam);		 
	}
}

boolean GameWnd_Open(GameWnd *pthis)
{
	AEEDeviceInfo di;
	int i;
	int8 gridCntX;
	
	pthis->direction = 5;
	pthis->keyLeft = FALSE;
	pthis->keyRight = FALSE;
	pthis->layer = 0;
	pthis->crashCounter = 0;
	pthis->isCrash = FALSE;
	
	ISHELL_GetDeviceInfo(pthis->pMe->a.m_pIShell, &di);
	
	gridCntX = ((di.cxScreen+12)/16 > 9) ? 9 : (di.cxScreen+12)/16;
	
	//tile索引数组
	MEMSET(pthis->BackGroundLayer,0,sizeof(pthis->BackGroundLayer));
    pthis->BackGroundLayer[0] = 2;
	pthis->BackGroundLayer[gridCntX-1] = 1;
	pthis->BackGroundLayer[gridCntX] = 3;
	pthis->BackGroundLayer[15] = 3;
	
	pthis->frameMax.x = gridCntX*16;
	pthis->frameMax.y = 256;
	
	pthis->frameStart.x = (di.cxScreen - pthis->frameMax.x)/2;
	pthis->frameStart.y = 0;
	
	CALLBACK_Init(&pthis->cbTimer, GameWnd_NextFrame, pthis);
	
	//sprite
	MEMSET(pthis->rgCmds, 0, sizeof(pthis->rgCmds));
	
	//score digit
	for (i = SPRITE_DIGIT; i < 4+SPRITE_DIGIT; i++) {
		pthis->rgCmds[i].x = pthis->frameStart.x 
			+ SCORE_START_X + (i-SPRITE_DIGIT)*DIGIT_WEIGHT; 
		pthis->rgCmds[i].y = pthis->frameStart.y + 0;
		pthis->rgCmds[i].unSpriteIndex = PIC_START_DIGIT;
		pthis->rgCmds[i].unSpriteSize = SPRITE_SIZE_16X16;
		pthis->rgCmds[i].unComposite = 0;
		pthis->rgCmds[i].unLayer = 2;
	}
	
	//wall
	for (i = 0; i < 4; i++) {
		pthis->rgCmds[i].x = pthis->frameStart.x 
			+ 4 + Random((int16) (pthis->frameMax.x - 8 - 32));
		pthis->rgCmds[i].y = WALL_START_POS_Y + 56*i;
		pthis->rgCmds[i].unSpriteIndex = PIC_START_WALL;
		pthis->rgCmds[i].unSpriteSize = SPRITE_SIZE_16X16;
		pthis->rgCmds[i].unComposite = 0;
		pthis->rgCmds[i].unLayer = 0;
		
		pthis->rgCmds[i+4].x = pthis->rgCmds[i].x + 16;
		pthis->rgCmds[i+4].y = pthis->rgCmds[i].y;
		pthis->rgCmds[i+4].unSpriteIndex = PIC_START_WALL+1;
		pthis->rgCmds[i+4].unSpriteSize = SPRITE_SIZE_16X16;
		pthis->rgCmds[i+4].unComposite = 0;
		pthis->rgCmds[i+4].unLayer = 0;
	}
	
	//plane
	pthis->rgCmds[SPRITE_PLANE].x = pthis->frameStart.x + 50;
	pthis->rgCmds[SPRITE_PLANE].y = pthis->frameStart.y + 40;
	pthis->rgCmds[SPRITE_PLANE].unSpriteIndex = pthis->direction;
	pthis->rgCmds[SPRITE_PLANE].unSpriteSize = SPRITE_SIZE_16X16;
	pthis->rgCmds[SPRITE_PLANE].unComposite = 0;
	pthis->rgCmds[SPRITE_PLANE].unLayer = 1;
	
	//terminator
	pthis->rgCmds[SPRITE_PLANE+1].unSpriteSize = SPRITE_SIZE_END;
	
	//tile
	MEMSET(pthis->rgMaps, 0, sizeof(pthis->rgMaps));
	
	pthis->rgMaps[0].pMapArray = (uint16*) pthis->BackGroundLayer;
	pthis->rgMaps[0].x = pthis->frameStart.x;
	pthis->rgMaps[0].y = pthis->frameStart.y;
	pthis->rgMaps[0].w = MAP_SIZE_16;
	pthis->rgMaps[0].h = MAP_SIZE_1;
	pthis->rgMaps[0].unTileSize = TILE_SIZE_16X16;
	pthis->rgMaps[0].unFlags = MAP_FLAG_WRAP;

	if (GameWnd_LoadResources(pthis) != SUCCESS) {
		return FALSE;
	}	
	ISHELL_SetTimerEx(pthis->pMe->a.m_pIShell, 0, &pthis->cbTimer);

	return TRUE;
}

void GameWnd_Close(GameWnd *pthis)
{
	CALLBACK_Cancel(&pthis->cbTimer);
	GameWnd_UnloadResources(pthis);
}

void GameWnd_Free(GameWnd *pthis)
{
	CALLBACK_Cancel(&pthis->cbTimer);
	GameWnd_UnloadResources(pthis);
}

static int GameWnd_LoadResources(GameWnd *pthis)
{
	IBitmap	*pbmScreen;
	
	//creates instance of ISprite
	ISHELL_CreateInstance(pthis->pMe->a.m_pIShell, AEECLSID_SPRITE, 
		(void**)&pthis->pISprite);
	//sets IDisplay as its destination
	pbmScreen = IDISPLAY_GetDestination(pthis->pMe->a.m_pIDisplay);
	ISPRITE_SetDestination(pthis->pISprite, pbmScreen);
	IBITMAP_Release(pbmScreen);
	
	//load image for tile
	GameWnd_LoadSprites(pthis, PFLY_RES_FILE, IDB_BACKGROUND, TILE_SIZE_16X16, TRUE);
	
	//load image for sprite
	GameWnd_LoadSprites(pthis, PFLY_RES_FILE, IDB_SPRITE16, SPRITE_SIZE_16X16, FALSE);
	GameWnd_LoadSprites(pthis, PFLY_RES_FILE, IDB_SPRITE32, SPRITE_SIZE_32X32, FALSE);
	
	return SUCCESS;
}

static boolean GameWnd_HandleKeyEvent(GameWnd *pthis, AEEEvent eCode, uint16 wParam)
{
	if (eCode == EVT_KEY_PRESS)  {
		switch (wParam) {
		case AVK_RIGHT:
			if (pthis->keyLeft == FALSE) {
				pthis->keyRight = TRUE;
			}
			break;
		case AVK_LEFT:
			if (pthis->keyRight == FALSE) {
				pthis->keyLeft = TRUE;
			}
			break;
		default:
			return FALSE;
		}
		return TRUE;
	} else if (eCode == EVT_KEY_RELEASE) {
		switch (wParam) {
		case AVK_RIGHT:
			pthis->keyRight = FALSE;
			break;
		case AVK_LEFT:
			pthis->keyLeft = FALSE;
			break;
		default:
			return FALSE;
		}
		return TRUE;
		
	} else if(eCode == EVT_KEY) {
		switch(wParam) {
		case AVK_CLR:
			return Pfly_SetActiveWnd(pthis->pMe, IDW_MAINMENU);
		default:
			return FALSE;
		}
	}
	return FALSE;
}

static void GameWnd_NextFrame(GameWnd *pthis)
{
	int i;
	ISHELL_SetTimerEx(pthis->pMe->a.m_pIShell, 80, &pthis->cbTimer);
	
	//飞机是否分解
	if (pthis->isCrash == FALSE) {
		
		pthis->isCrash = GameWnd_IsCrash(pthis);
		
		if(pthis->keyRight == TRUE ) {
			if (pthis->direction<10) {
				pthis->direction++;
			}		
		} else if (pthis->keyLeft == TRUE ) {
			if (pthis->direction>0) {
				pthis->direction--;
			}		
		}	
		
		//update coordinate
		pthis->rgMaps[0].y += speedTableY[pthis->direction];
		if (pthis->rgMaps[0].y >= MAX_HEIGHT) {
			pthis->rgMaps[0].y -= MAX_HEIGHT;
		}
		
		//update wall
		for(i=0; i<4; i++) {
			if ((pthis->rgCmds[SPRITE_PLANE].y > 
				pthis->rgCmds[i].y+16-speedTableY[pthis->direction])
				&& pthis->rgCmds[SPRITE_PLANE].y <= pthis->rgCmds[i].y+16) {
				pthis->layer++;
			}
			if (pthis->rgCmds[i].y < -16) {
				//init wall
				pthis->rgCmds[i].x = pthis->frameStart.x 
					+ 4 + Random((int16) (pthis->frameMax.x - 8 - 32));
				pthis->rgCmds[i].y += 224;
				pthis->rgCmds[i].unSpriteIndex = PIC_START_WALL;
				pthis->rgCmds[i].unSpriteSize = SPRITE_SIZE_16X16;
				pthis->rgCmds[i].unComposite = 0;
				pthis->rgCmds[i].unLayer = 0;
				
				pthis->rgCmds[i+4].x = pthis->rgCmds[i].x + 16;
				pthis->rgCmds[i+4].y = pthis->rgCmds[i].y;
				pthis->rgCmds[i+4].unSpriteIndex = PIC_START_WALL+1;
				pthis->rgCmds[i+4].unSpriteSize = SPRITE_SIZE_16X16;
				pthis->rgCmds[i+4].unComposite = 0;
				pthis->rgCmds[i+4].unLayer = 0;
			}
			//move wall
			pthis->rgCmds[i].y -= speedTableY[pthis->direction];
			pthis->rgCmds[i+4].y = pthis->rgCmds[i].y;
		}
		
		//update plane
		pthis->rgCmds[SPRITE_PLANE].x += speedTableX[pthis->direction]; 
		pthis->rgCmds[SPRITE_PLANE].unSpriteIndex = pthis->direction;
		
		//update score digit
		pthis->rgCmds[SPRITE_DIGIT+0].unSpriteIndex = PIC_START_DIGIT 
			+ (pthis->layer/1000)%10;
		pthis->rgCmds[SPRITE_DIGIT+1].unSpriteIndex = PIC_START_DIGIT 
			+ (pthis->layer/100)%10;
		pthis->rgCmds[SPRITE_DIGIT+2].unSpriteIndex = PIC_START_DIGIT 
			+ (pthis->layer/10)%10;
		pthis->rgCmds[SPRITE_DIGIT+3].unSpriteIndex = PIC_START_DIGIT 
			+ pthis->layer%10;
		
	} else {
		if(pthis->crashCounter == 1) {
			//update image to crash plane
			pthis->rgCmds[SPRITE_PLANE].x -= 8;
			pthis->rgCmds[SPRITE_PLANE].y -= 8;
			pthis->rgCmds[SPRITE_PLANE].unSpriteIndex = 0;
			pthis->rgCmds[SPRITE_PLANE].unSpriteSize = SPRITE_SIZE_32X32;
			pthis->rgCmds[SPRITE_PLANE].unComposite = 0;
			pthis->rgCmds[SPRITE_PLANE].unLayer = 1;
		} else if (pthis->crashCounter == 4) {
			//update crash image
			pthis->rgCmds[SPRITE_PLANE].unSpriteIndex = 1;
		} else if (pthis->crashCounter == 7) {
			//game over
			Pfly_SetActiveWnd(pthis->pMe, IDW_GAMEEND);
			return;
		}
		pthis->crashCounter++;
	}
	
	//update tiles and sprites
	ISPRITE_DrawTiles(pthis->pISprite, pthis->rgMaps);
	ISPRITE_DrawSprites(pthis->pISprite, pthis->rgCmds);
	IDISPLAY_Update(pthis->pMe->a.m_pIDisplay);
}


static void GameWnd_LoadSprites(GameWnd *pthis, const char * pszFile, 
				uint16 resID, uint8 unSpriteSize, boolean isTile)
{
	IBitmap       *pbmScreen = NULL;
	IBitmap       *pbmDib = NULL;
	IBitmap       *pbmDdb = NULL;
	NativeColor    color;
	AEEBitmapInfo  bi;
	
	pbmScreen = IDISPLAY_GetDestination(pthis->pMe->a.m_pIDisplay);
	
	pbmDib = ISHELL_LoadResBitmap(pthis->pMe->a.m_pIShell, pszFile, resID);
	IBITMAP_GetInfo(pbmDib, &bi, sizeof(bi));
	IBITMAP_CreateCompatibleBitmap(pbmScreen, 
		&pbmDdb, (uint16)bi.cx, (uint16)bi.cy);
	IBITMAP_BltIn(pbmDdb, 0, 0, (uint16)bi.cx, (uint16)bi.cy, 
		pbmDib, 0, 0, AEE_RO_COPY);
	IBITMAP_Release(pbmDib);
	IBITMAP_GetPixel(pbmDdb, 0, 0, &color);
	IBITMAP_SetTransparencyColor(pbmDdb, color);
	if (isTile == TRUE) {
		ISPRITE_SetTileBuffer(pthis->pISprite, unSpriteSize, pbmDdb);
	} else {
		ISPRITE_SetSpriteBuffer(pthis->pISprite, unSpriteSize, pbmDdb);
	}
	IBITMAP_Release(pbmDdb);
	IBITMAP_Release(pbmScreen);
}

static void GameWnd_UnloadResources(GameWnd *pthis)
{
	if (pthis->pISprite) {
		ISPRITE_Release(pthis->pISprite);
		pthis->pISprite = NULL;
	}
}

static boolean GameWnd_IsCrash(GameWnd *pthis)
{
	int i;
	//判断是否撞边
	if (pthis->rgCmds[SPRITE_PLANE].x - pthis->frameStart.x < 8 
		|| pthis->rgCmds[SPRITE_PLANE].x - pthis->frameStart.x > pthis->frameMax.x - 24) {
		return TRUE;
	}
	//判断是否撞墙
	for(i=0; i<4; i++) {
		if (pthis->rgCmds[SPRITE_PLANE].x >= pthis->rgCmds[i].x-13 && pthis->rgCmds[SPRITE_PLANE].x <= pthis->rgCmds[i].x+29) {
			if (pthis->rgCmds[SPRITE_PLANE].y >= pthis->rgCmds[i].y-14 && pthis->rgCmds[SPRITE_PLANE].y <= pthis->rgCmds[i].y+14) {
				return TRUE;
			}
		}
	}
	return FALSE;
}

static int16 Random(int16 range)
{
	uint16 rand;
	GETRAND((byte *)&rand,2);
	return range == 0 ? 0 : rand%range;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -