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

📄 shotgame.c

📁 一款很适合初学者的射击游戏
💻 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 + -