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