📄 shotgame.c
字号:
#include "AEEModGen.h" // Module interface definitions
#include "AEEAppGen.h" // Applet interface definitions
#include "AEEShell.h" // Shell interface definitions
#include "AEEFile.h" // File interface definitions
#include "AEENet.h" // Socket interface definitions
#include "AEESprite.h"
#include "AEEStdLib.h"
#include "ShotGame.bid"
#define PLANE_SPEED 5 //飞机移动的速度
#define BALL_SPEED 30 //子弹飞行速度
#define BALL_AMOUNT 5 //子弹数量
#define BALL_INIT_COORDINATE -32 //子弹消失时的坐标
static const uint16 gBGLayer1[] = { //背景图
0, 1, 2, 0,
1, 2, 0, 1,
2, 0, 1, 2,
1, 2, 0, 1
};
static const uint16 gEnemySpeed[] = {4, 4, 5, 6}; //4架敌机的速度
typedef struct _ShotGameApp
{
AEEApplet a;
ISprite *pISprite;
AEESpriteCmd rgCmds[1 + BALL_AMOUNT + 4 + 1]; //1架我方飞机+10发子弹+4架敌机+terminator
AEETileMap rgMaps[2]; //地图+terminator
AEECallback cbTimer; //回调函数,每格80毫秒调一次
boolean bKeyLeft; //左方向键是否被按下
boolean bKeyRight; //右方向键是否被按下
boolean bKeyUp; //上方向键是否被按下
boolean bKeyDown; //下方向键是否被按下
boolean bKeySelect; //回车键是否被按下
uint16 w; //屏幕宽度
uint16 h; //屏幕高度
uint16 bgdx; //绘制背景的x坐标
uint16 bgdy; //绘制背景的y坐标
boolean bBallFlicker; //子弹的闪烁效果
boolean bGameOver; //游戏结束
}ShotGameApp;
//函数声名
static boolean ShotGame_HandleEvent(ShotGameApp *pi, AEEEvent eCode,
uint16 wParam, uint32 dwParam);
static boolean ShotGame_AppStart(ShotGameApp *pMe);
static boolean ShotGame_AppInit(ShotGameApp *pMe);
static void ShotGame_AppFree(ShotGameApp *pMe);
static void ShotGame_NextFrame(ShotGameApp *pMe);
static int ShotGame_LoadResources(ShotGameApp *pMe);
static void ShotGame_LoadSprite(ShotGameApp *pMe, const char *pszFile,
uint8 unSpriteSize, boolean isTile);
static void ShotGame_UnloadResources(ShotGameApp *pMe);
static boolean ShotGame_HandleKeyEvent(ShotGameApp *pMe, AEEEvent eCode, uint16 wParam);
static int16 Random(int16 range);
//函数定义
int AEEClsCreateInstance(AEECLSID ClsId,IShell *pIShell,IModule *po,void **ppObj)
{
*ppObj = NULL;
if(ClsId == AEECLSID_SHOTGAME){
if(AEEApplet_New(sizeof(ShotGameApp), ClsId, pIShell, po, (IApplet**)ppObj,
(AEEHANDLER)ShotGame_HandleEvent, (PFNFREEAPPDATA)ShotGame_AppFree)
== TRUE)
{
// Add your code here .....
return (AEE_SUCCESS);
}
}
return (EFAILED);
}
static boolean ShotGame_HandleEvent(ShotGameApp *pMe, AEEEvent eCode, uint16 wParam, uint32 dwParam)
{
switch (eCode)
{
case EVT_APP_START:
return ShotGame_AppStart(pMe);
case EVT_APP_STOP:
//取消定时器
CALLBACK_Cancel(&pMe->cbTimer);
//释放资源
ShotGame_AppFree(pMe);
return TRUE;
default:
return ShotGame_HandleKeyEvent(pMe, eCode, wParam);
}
return FALSE;
}
static boolean ShotGame_AppInit(ShotGameApp *pMe)
{
int i;
//获取屏幕信息
AEEDeviceInfo di;
ISHELL_GetDeviceInfo(pMe->a.m_pIShell, &di);
pMe->w = di.cxScreen;
pMe->h = di.cyScreen;
//初始化回调函数
CALLBACK_Init(&pMe->cbTimer, (PFNNOTIFY)ShotGame_NextFrame, pMe);
//初始化精灵坐标
MEMSET(pMe->rgCmds, 0, sizeof(pMe->rgCmds));
//我方飞机,开始出现在屏幕底部中央
pMe->rgCmds[0].x = pMe->w / 2 - 16;
pMe->rgCmds[0].y = pMe->h -32 - 5;
pMe->rgCmds[0].unSpriteIndex = 2;
pMe->rgCmds[0].unSpriteSize = SPRITE_SIZE_32X32;
pMe->rgCmds[0].unComposite = 0;
pMe->rgCmds[0].unLayer = 2;
//子弹
for (i = 1; i < BALL_AMOUNT + 1; i++)
{
pMe->rgCmds[i].x = BALL_INIT_COORDINATE;
pMe->rgCmds[i].y = BALL_INIT_COORDINATE;
pMe->rgCmds[i].unSpriteIndex = 0;
pMe->rgCmds[i].unSpriteSize = SPRITE_SIZE_32X32;
pMe->rgCmds[i].unComposite = 0;
pMe->rgCmds[i].unLayer = 1;
}
//敌机
for (i = BALL_AMOUNT + 1; i < BALL_AMOUNT + 5; i++)
{
pMe->rgCmds[i].x = 0;
pMe->rgCmds[i].y = pMe->h + (i - BALL_AMOUNT - 1) * 32;
pMe->rgCmds[i].unSpriteIndex = 1;
pMe->rgCmds[i].unSpriteSize = SPRITE_SIZE_32X32;
pMe->rgCmds[i].unComposite = 0;
pMe->rgCmds[i].unLayer = 0;
}
//精灵结束
pMe->rgCmds[BALL_AMOUNT + 5].unSpriteSize = SPRITE_SIZE_END;
//初始化背景
MEMSET(pMe->rgMaps, 0, sizeof(pMe->rgMaps));
pMe->rgMaps[0].pMapArray = (uint16 *)gBGLayer1;
pMe->rgMaps[0].x = 0;
pMe->rgMaps[0].y = 0;
pMe->rgMaps[0].w = MAP_SIZE_4;
pMe->rgMaps[0].h = MAP_SIZE_4;
pMe->rgMaps[0].unTileSize = TILE_SIZE_32X32;
pMe->rgMaps[0].unFlags = MAP_FLAG_WRAP;
//初始化背景绘制坐标
pMe->bgdx = 0;
pMe->bgdy = 0;
//初始化按键信息
pMe->bKeyLeft = FALSE;
pMe->bKeyRight = FALSE;
pMe->bKeyUp = FALSE;
pMe->bKeyDown = FALSE;
pMe->bKeySelect = FALSE;
//子弹闪烁,上下偏移几个象素
pMe->bBallFlicker = TRUE;
//游戏是否结束
pMe->bGameOver = FALSE;
return TRUE;
}
static void ShotGame_AppFree(ShotGameApp *pMe)
{
ShotGame_UnloadResources(pMe);
}
static boolean ShotGame_HandleKeyEvent(ShotGameApp *pMe, AEEEvent eCode, uint16 wParam)
{
switch (eCode)
{
case EVT_KEY_PRESS:
switch (wParam)
{
case AVK_RIGHT:
if (FALSE == pMe->bKeyLeft)
{
pMe->bKeyRight = TRUE;
}
break;
case AVK_LEFT:
if (FALSE == pMe->bKeyRight)
{
pMe->bKeyLeft = TRUE;
}
break;
case AVK_UP:
if (FALSE == pMe->bKeyDown)
{
pMe->bKeyUp = TRUE;
}
break;
case AVK_DOWN:
if (FALSE == pMe->bKeyUp)
{
pMe->bKeyDown = TRUE;
}
break;
case AVK_SELECT:
pMe->bKeySelect = TRUE;
break;
case AVK_0:
ShotGame_AppStart(pMe);
default:
return FALSE;
}
return TRUE;
case EVT_KEY_RELEASE:
switch (wParam)
{
case AVK_RIGHT:
pMe->bKeyRight = FALSE;
break;
case AVK_LEFT:
pMe->bKeyLeft = FALSE;
break;
case AVK_UP:
pMe->bKeyUp = FALSE;
break;
case AVK_DOWN:
pMe->bKeyDown = FALSE;
break;
case AVK_SELECT:
pMe->bKeySelect = FALSE;
default:
return FALSE;
}
return TRUE;
default:
return FALSE;
}
}
static void ShotGame_NextFrame(ShotGameApp *pMe)
{
int16 nBall = 1; //第几发子弹,从1开始
int16 i, j, m, n; //循环计数
//重新设置定时器
ISHELL_SetTimerEx(pMe->a.m_pIShell, 80, &pMe->cbTimer);
//更新屏幕
ISPRITE_DrawTiles(pMe->pISprite, pMe->rgMaps);
ISPRITE_DrawSprites(pMe->pISprite, pMe->rgCmds);
IDISPLAY_Update(pMe->a.m_pIDisplay);
//交替偏移
pMe->bBallFlicker = !pMe->bBallFlicker;
//移动背景
pMe->rgMaps[0].y += 1;
//移动敌机
for (i = BALL_AMOUNT + 1; i < BALL_AMOUNT + 5; i++)
{
pMe->rgCmds[i].y += gEnemySpeed[i - BALL_AMOUNT - 1];
if (pMe->rgCmds[i].y < pMe->h)
{
//计算和我方飞机的碰撞,如果碰撞,则游戏挂起
m = pMe->rgCmds[0].x - pMe->rgCmds[i].x;
n = pMe->rgCmds[0].y - pMe->rgCmds[i].y;
if ((n > -28 && n < 20) && (m > -28 && m < 28))
{
CALLBACK_Cancel(&pMe->cbTimer);
ShotGame_AppFree(pMe);
pMe->bGameOver = TRUE;
return;
}
}
if (pMe->rgCmds[i].y >= pMe->h + 3 * 32)
{
//重新设置坐标
pMe->rgCmds[i].x = Random((int16)(pMe->w - 32));
pMe->rgCmds[i].y = -32;
}
}
//移动已经发射,但还没有消失的子弹
for (i = 1; i < BALL_AMOUNT + 1; i++)
{
pMe->rgCmds[i].y -= BALL_SPEED + (pMe->bBallFlicker ? 1 : -1);
//计算碰撞,如果碰撞,则子弹和敌机都消失
for (j = BALL_AMOUNT + 1; j < BALL_AMOUNT + 5; j++)
{
m = pMe->rgCmds[i].x - pMe->rgCmds[j].x;
n = pMe->rgCmds[i].y - pMe->rgCmds[j].y;
if ((m > -20 && m < 20) && (n > -20 && n < 20))
{
pMe->rgCmds[i].y = BALL_INIT_COORDINATE;
pMe->rgCmds[j].y = pMe->h + Random(4) * 32;
}
}
}
for (i = 1; i < BALL_AMOUNT + 1; i++)
{
if (pMe->rgCmds[i].y > BALL_INIT_COORDINATE)
{
nBall++;
}
else
{
break;
}
}
if (BALL_AMOUNT == nBall)
{
nBall = 1;
}
//移动我方飞机
if (pMe->rgMaps[0].y == pMe->h)
{
pMe->rgMaps[0].y = 32 - pMe->h % 32;
}
if (pMe->bKeyLeft)
{
pMe->rgCmds[0].x -= PLANE_SPEED;
if (pMe->rgCmds[0].x < 0)
{
pMe->rgCmds[0].x = 0;
}
}
if (pMe->bKeyRight)
{
pMe->rgCmds[0].x += PLANE_SPEED;
if (pMe->rgCmds[0].x > pMe->w - 32)
{
pMe->rgCmds[0].x = pMe->w - 32;
}
}
if (pMe->bKeyUp)
{
pMe->rgCmds[0].y -= PLANE_SPEED;
if (pMe->rgCmds[0].y < 32)
{
pMe->rgCmds[0].y = 32;
}
}
if (pMe->bKeyDown)
{
pMe->rgCmds[0].y += PLANE_SPEED;
if (pMe->rgCmds[0].y > pMe->h - 10)
{
pMe->rgCmds[0].y = pMe->h - 10;
}
}
//发射子弹
if (pMe->bKeySelect)
{
pMe->rgCmds[nBall].x = pMe->rgCmds[0].x;
pMe->rgCmds[nBall].y = pMe->rgCmds[0].y - 20 + (pMe->bBallFlicker ? 1 : -1);
}
}
static int ShotGame_LoadResources(ShotGameApp *pMe)
{
IBitmap *pbmScreen = NULL;
//初始化sprite接口
if (SUCCESS != ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_SPRITE, (void **)&pMe->pISprite))
{
return FALSE;
}
pbmScreen = IDISPLAY_GetDestination(pMe->a.m_pIDisplay);
ISPRITE_SetDestination(pMe->pISprite, pbmScreen);
IBITMAP_Release(pbmScreen);
ShotGame_LoadSprite(pMe, "bg32.bmp", TILE_SIZE_32X32, TRUE);
ShotGame_LoadSprite(pMe, "sprite32.bmp", TILE_SIZE_32X32, FALSE);
return SUCCESS;
}
static void ShotGame_LoadSprite(ShotGameApp *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 ShotGame_UnloadResources(ShotGameApp *pMe)
{
if (pMe->pISprite)
{
ISPRITE_Release(pMe->pISprite);
pMe->pISprite = NULL;
}
}
static boolean ShotGame_AppStart(ShotGameApp *pMe)
{
//初始化
if (!ShotGame_AppInit(pMe))
{
return FALSE;
}
//加载资源
if (SUCCESS != ShotGame_LoadResources(pMe))
{
return FALSE;
}
//设置定时器
ISHELL_SetTimerEx(pMe->a.m_pIShell, 0, &pMe->cbTimer);
return TRUE;
}
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 + -