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

📄 pfly.c

📁 brew开发与入门的第九章原代码,均可运行,请放心使用
💻 C
字号:
/*===========================================================================
	FILE: pfly.c
	DESCRIPTION: This file contains a simple game built with ISprite.
===========================================================================*/
#include "AEEAppGen.h"
#include "AEESprite.h"
#include "AEEStdLib.h"
#include "pfly.bid"

#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}; 

typedef struct {
	AEEApplet		a;
	ISprite*		pISprite;
	AEESpriteCmd	rgCmds[14];		// wall sprites 2*4 + plane + 4 score sprites + terminator
	AEETileMap		rgMaps[2];      // one background layers + terminator
	AEECallback		cbTimer;
   	AEEPoint		frameStart;		//屏幕的逻辑起始坐标
	AEEPoint		frameMax;		//屏幕的逻辑最大长宽
	byte			direction;		//飞行角度
	int				layer;			//游戏分数
	int				crashCounter;	//crash之后的计数器
	boolean			keyRight;		//右键是否按下
	boolean			keyLeft;		//左键是否按下
	boolean			isCrash;		//是否分解
	uint16			BackGroundLayer[16];//Tile 索引数组
} PflyApp;

//函数声明
static boolean Pfly_HandleEvent(PflyApp * pme, AEEEvent eCode,uint16 wParam, uint32 dwParam);
static void Pfly_Init(PflyApp *pMe);
static void Pfly_Free(PflyApp *pMe);
static boolean Pfly_HandleKeyEvent(PflyApp *pMe, AEEEvent eCode, uint16 wParam);
static void Pfly_NextFrame(PflyApp *pMe);
static int Pfly_LoadResources(PflyApp *pMe);
static void Pfly_UnloadResources(PflyApp *pMe);
static void Pfly_LoadSprites(PflyApp *pMe, const char * pszFile, uint8 unSpriteSize, boolean isTile);
static boolean Pfly_IsCrash(PflyApp *pMe);
static int16 Random(int16 range);

int AEEClsCreateInstance(AEECLSID ClsId,IShell * pIShell,IModule * pMod,void ** ppObj)
{
	*ppObj = NULL;
	
	if (!AEEApplet_New(sizeof(PflyApp),     // Size of our private class
		ClsId,                              // Our class ID
		pIShell,                            // Shell interface
		pMod,                               // Module instance
		(IApplet**)ppObj,                   // Return object
		(AEEHANDLER)Pfly_HandleEvent,		// Our event handler
		(PFNFREEAPPDATA)Pfly_Free))			// No special "cleanup" function
		return EFAILED;
	
	return SUCCESS;
}

static boolean Pfly_HandleEvent(PflyApp * pMe, AEEEvent eCode, uint16 wParam, uint32 dwParam)
{
	switch (eCode) {
	case EVT_APP_START:
		Pfly_Init(pMe);
		if (SUCCESS != Pfly_LoadResources(pMe)) {
			return FALSE;
		}
		ISHELL_SetTimerEx(pMe->a.m_pIShell, 0, &pMe->cbTimer);
		return TRUE;
		
	case EVT_APP_SUSPEND:
		CALLBACK_Cancel(&pMe->cbTimer);
		return TRUE;
		
	case EVT_APP_RESUME:
		ISHELL_SetTimerEx(pMe->a.m_pIShell, 0, &pMe->cbTimer);
		return TRUE;
		
	case EVT_APP_STOP:
		CALLBACK_Cancel(&pMe->cbTimer);
		Pfly_UnloadResources(pMe);
		return TRUE;
		
	case EVT_APP_NO_SLEEP:
		// catching this event prevent BREW from going to "sleep"
		return TRUE;
		
	default:
		return Pfly_HandleKeyEvent((PflyApp*)pMe, eCode, wParam);
	}
	return FALSE;
}

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

static void Pfly_Free(PflyApp *pMe)
{
	Pfly_UnloadResources(pMe);
}

static boolean Pfly_HandleKeyEvent(PflyApp *pMe, AEEEvent eCode, uint16 wParam)
{
	switch (eCode) {
	case EVT_KEY_PRESS:
		switch (wParam) {
		case AVK_RIGHT:
			if (pMe->keyLeft == FALSE) {
				pMe->keyRight = TRUE;
			}
			break;
		case AVK_LEFT:
			if (pMe->keyRight == FALSE) {
				pMe->keyLeft = TRUE;
			}
			break;
		default:
			return FALSE;
		}
		return TRUE;
		
		case EVT_KEY_RELEASE:
			switch (wParam) {
			case AVK_RIGHT:
				pMe->keyRight = FALSE;
				break;
			case AVK_LEFT:
				pMe->keyLeft = FALSE;
				break;
			default:
				return FALSE;
			}
			return TRUE;
			default:
				return FALSE;
	}
}

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

static int Pfly_LoadResources(PflyApp *pMe)
{
	IBitmap	*pbmScreen;
	
	//creates instance of ISprite
	ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_SPRITE, 
		(void**)&pMe->pISprite);
	//sets IDisplay as its destination
	pbmScreen = IDISPLAY_GetDestination(pMe->a.m_pIDisplay);
	ISPRITE_SetDestination(pMe->pISprite, pbmScreen);
	IBITMAP_Release(pbmScreen);
	
	//load image for tile
	Pfly_LoadSprites(pMe, "bg16.bmp", TILE_SIZE_16X16, TRUE);
	
	//load image for sprite
	Pfly_LoadSprites(pMe, "sprite16.bmp", SPRITE_SIZE_16X16, FALSE);
	Pfly_LoadSprites(pMe, "sprite32.bmp", SPRITE_SIZE_32X32, FALSE);
	
	return SUCCESS;
}

static void Pfly_LoadSprites(PflyApp *pMe, const char * pszFile, 
							 uint8 unSpriteSize, boolean isTile)
{
	IBitmap       *pbmScreen = NULL;
	IBitmap       *pbmDib = NULL;
	IBitmap       *pbmDdb = NULL;
	NativeColor    color;
	AEEBitmapInfo  bi;
	
	pbmScreen = IDISPLAY_GetDestination(pMe->a.m_pIDisplay);
	
	pbmDib = ISHELL_LoadBitmap(pMe->a.m_pIShell, pszFile);
	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(pMe->pISprite, unSpriteSize, pbmDdb);
	} else {
		ISPRITE_SetSpriteBuffer(pMe->pISprite, unSpriteSize, pbmDdb);
	}
	IBITMAP_Release(pbmDdb);
	IBITMAP_Release(pbmScreen);
}

static void Pfly_UnloadResources(PflyApp *pMe)
{
	if (pMe->pISprite) {
		ISPRITE_Release(pMe->pISprite);
		pMe->pISprite = NULL;
	}
}

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