📄 gamewnd.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 + -