📄 cs_dust2.c
字号:
//******************************************************
//*Copyright(C)2004-3,NOTHEOREM(R).All rights reserved.*
//******************************************************
//This is a 3D engine for general purpose (Demo)
//NT3D v1.1
//建议:请先阅读NT3D v1.2的NFS-m , 里面有详细注释。
//另:图片加载透明色部分存在问题,请参阅NT3D v1.2
#include "AEEModGen.h"
#include "AEEAppGen.h"
#include "AEEShell.h"
#include "AEESprite.h"
#include "AEEStdLib.h"
#include "CS_Dust2.bid"
#define USE_TRANSFORMS
#define PLANE (60)
#define KEY_LEFT (1)
#define KEY_RIGHT (2)
#define KEY_UP (4)
#define KEY_DOWN (8)
#define KEY_HIGH (16)
#define KEY_LOW (32)
typedef struct
{
AEEApplet a;
ISprite *pISprite;
AEESpriteCmd pCmds[3];
AEETransformMatrix pTransform[2];
byte hW,hH,Key,planes;
short d3dPos[PLANE][10],userPos[3],frames,clocksec,clockmin;
AECHAR fps[9],sysclock[10],buf[16];
} Data;
static boolean CS_Dust2_HandleEvent(IApplet * pi, AEEEvent eCode, uint16 wParam, uint32 dwParam);
static void CS_Dust2_Init(Data *pMe);
static int CS_Dust2_LoadResources(Data *pMe);
static void CS_Dust2_UnloadResources(Data *pMe);
static void CS_Dust2_Display(Data *pMe);
static void CS_Dust2_KeyEvent(Data *pMe);
static void CS_Dust2_Help(Data *pMe);
int AEEClsCreateInstance(AEECLSID ClsId,IShell * pIShell,IModule * po,void ** ppObj)
{
*ppObj = NULL;
if(ClsId == AEECLSID_CS_Dust2){
if(AEEApplet_New(sizeof(Data), ClsId, pIShell,po,(IApplet**)ppObj,
(AEEHANDLER)CS_Dust2_HandleEvent,(PFNFREEAPPDATA)CS_Dust2_UnloadResources)
== TRUE)
{
return (AEE_SUCCESS);
}
}
return (EFAILED);
}
static boolean CS_Dust2_HandleEvent(IApplet * pi, AEEEvent eCode, uint16 wParam, uint32 dwParam)
{
Data* pMe=(Data*)pi;
switch (eCode)
{
case EVT_APP_START:
CS_Dust2_Init(pMe);
if (CS_Dust2_LoadResources(pMe) != SUCCESS) return FALSE;
CS_Dust2_Display(pMe);
CS_Dust2_KeyEvent(pMe);
CS_Dust2_Help(pMe);
return(TRUE);
case EVT_KEY:
switch (wParam)
{
case AVK_LEFT:
case AVK_4:
pMe->Key |= KEY_LEFT;
return(TRUE);
case AVK_RIGHT:
case AVK_6:
pMe->Key |= KEY_RIGHT;
return(TRUE);
case AVK_UP:
case AVK_8:
pMe->Key |= KEY_UP;
return(TRUE);
case AVK_DOWN:
case AVK_2:
pMe->Key |= KEY_DOWN;
return(TRUE);
case AVK_3:
pMe->Key |= KEY_HIGH;
return(TRUE);
case AVK_1:
pMe->Key |= KEY_LOW;
return(TRUE);
}
return FALSE;
case EVT_KEY_RELEASE:
switch (wParam)
{
case AVK_LEFT:
case AVK_4:
pMe->Key &= ~KEY_LEFT;
return(TRUE);
case AVK_RIGHT:
case AVK_6:
pMe->Key &= ~KEY_RIGHT;
return(TRUE);
case AVK_UP:
case AVK_8:
pMe->Key &= ~KEY_UP;
return(TRUE);
case AVK_DOWN:
case AVK_2:
pMe->Key &= ~KEY_DOWN;
return(TRUE);
case AVK_3:
pMe->Key &= ~KEY_HIGH;
return(TRUE);
case AVK_1:
pMe->Key &= ~KEY_LOW;
return(TRUE);
}
return FALSE;
case EVT_APP_NO_SLEEP:
return TRUE;
case EVT_APP_STOP:
CS_Dust2_UnloadResources(pMe);
return TRUE;
default:
break;
}
return FALSE;
}
//=====================================================
//CS_Dust2_Init
//=====================================================
static void CS_Dust2_Init(Data *pMe)
{
AEEDeviceInfo di;
int i,j,k=0;
//((x0,y0),(x1,y1),(x2,y2),贴图材质sprite序列)
short pos[]={
2,0,8,4,0,8,2,0,13, 3,//远地面
4,0,8,6,0,8,4,0,13, 3,
6,0,8,8,0,8,6,0,13, 3,
2,0,4,4,0,4,2,0,8, 3,
4,0,4,6,0,4,4,0,8, 3,
6,0,4,8,0,4,6,0,8, 3,
2,2,8,2,2,11,2,0,8, 6,//左边墙y
2,4,8,2,4,11,2,2,8, 7,
2,5,8,2,5,11,2,4,8, 8,
2,2,11,2,2,14,2,0,11, 7,
2,4,11,2,4,14,2,2,11, 6,
2,5,11,2,5,14,2,4,11, 8,
-2,2,7,1,2,7,-2,0,7, 6,//左边墙x
-2,4,7,1,4,7,-2,2,7, 7,
-2,5,7,1,5,7,-2,4,7, 8,
-5,2,7,-2,2,7,-5,0,7, 7,
-5,4,7,-2,4,7,-5,2,7, 6,
-5,5,7,-2,5,7,-5,4,7, 8,
2,2,6,2,2,8,2,0,6, 7,//左转角边墙
2,4,6,2,4,8,2,2,6, 6,
2,5,6,2,5,8,2,4,6, 9,
0,2,6,2,2,6,0,0,6, 7,
0,4,6,2,4,6,0,2,6, 6,
0,5,6,2,5,6,0,4,6, 9,
8,2,9,8,2,7,8,0,9, 7,//右边远墙
8,4,9,8,4,7,8,2,9, 6,
8,5,9,8,5,7,8,4,9, 9,
8,2,11,8,2,9,8,0,11, 6,
8,4,11,8,4,9,8,2,11, 7,
8,5,11,8,5,9,8,4,11, 6,
8,2,13,8,2,11,8,0,13, 7,
8,4,13,8,4,11,8,2,13, 6,
8,5,13,8,5,11,8,4,13, 9,
8,2,7,9,2,6,8,0,7, 6,//转角斜面
8,4,7,9,4,6,8,2,7, 7,
8,5,7,9,5,6,8,4,7, 6,
9,2,6,10,2,6,9,1,6, 6,//右边x墙
9,3,6,10,3,6,9,2,6, 7,
10,3,6,11,3,6,10,2,6, 6,
9,4,6,10,4,6,9,3,6, 6,
10,4,6,11,4,6,10,3,6, 7,
9,5,6,10,5,6,9,4,6, 7,
10,5,6,11,5,6,10,4,6, 6,
11,5,6,12,5,6,11,4,6, 7,//超越墙的面
11,4,6,11,4,4,11,2,6, 9,//右边近墙
11,2,5,11,2,4,11,1,5, 6,
11,3,4,11,3,2,11,1,4, 6,
11,3,2,11,3,0,11,1,2, 2,
11,5,4,11,5,2,11,3,4, 8,
11,5,2,11,5,0,11,3,2, 8,
9,1,6,11,1,6,9,1,4, 5,//台子地面
9,1,4,11,1,4,9,1,2, 5,
9,1,2,11,1,2,9,1,0, 5,
10,2,6,10,2,5,10,1,6, 1,//箱子
10,2,6,11,2,6,10,2,5, 0,
10,2,5,11,2,5,10,1,5, 1,
7,0,4,8,0,4,7,-2,0, 4,//坡
3,0,4,2,0,4,3,-2,0, 4,
3,0,4,7,0,4,3,-1,2, 3,
3,-2,0,7,-2,0,3,-1,2, 3,
};
//场景初始化
for(i=0;i<PLANE;i++)
{
for(j=0;j<9;j++) pMe->d3dPos[i][j]=pos[k++]*32;
pMe->d3dPos[i][9]=pos[k++];
}
pMe->userPos[0]=150;pMe->userPos[1]=90;pMe->userPos[2]=-220;//user位置
//获取设备尺寸
ISHELL_GetDeviceInfo(pMe->a.m_pIShell, &di);
pMe->hW = di.cxScreen >> 1; pMe->hH = di.cyScreen >> 1;
//每次draw 2个sprite的命令数组初始化
for(i=0;i<2;i++)
{
pMe->pCmds[i].unTransform = SPRITE_MATRIX_TRANSFORM;
pMe->pCmds[i].unMatrixTransform = i;
pMe->pCmds[i].unSpriteSize = SPRITE_SIZE_32X32;
pMe->pCmds[i].unComposite = 0;
pMe->pCmds[i].unLayer = 0;
}
pMe->pCmds[2].unSpriteSize = SPRITE_SIZE_END;//sptite结束
//辅助显示信息
pMe->fps[4]=' ';
pMe->fps[5]='f';
pMe->fps[6]='p';
pMe->fps[7]='s';
pMe->fps[8]='\0';
pMe->sysclock[0]='t';
pMe->sysclock[1]='i';
pMe->sysclock[2]='m';
pMe->sysclock[3]='e';
pMe->sysclock[9]='\0';
}
//=====================================================
//CS_Dust2_LoadResources
//=====================================================
#define CHECK_ERROR(e) if((e) != SUCCESS) { nErr = (e); goto Error; }//出错处理
#define CHECK_NULL(e) if((e) == NULL) { nErr = EFAILED; goto Error; }//非空
static int CS_Dust2_LoadResources(Data *pMe)
{
IBitmap *pbmScreen = NULL,*pbmDib = NULL,*pbmDdb = NULL,*pbmDhb = NULL;
AEEBitmapInfo bi;
int nErr;
uint16 cx,cy,cy2,y;
CHECK_ERROR(ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_SPRITE, (void**)&pMe->pISprite));//创建sprite实例
//设置pbmScreen
CHECK_NULL(pbmScreen = IDISPLAY_GetDestination(pMe->a.m_pIDisplay));
//设置pbmDib
CHECK_NULL(pbmDib = ISHELL_LoadBitmap(pMe->a.m_pIShell, "new.bmp"));//加载res.bmp 设备无关
CHECK_ERROR(IBITMAP_GetInfo(pbmDib, &bi, sizeof(bi)));//获取信息
cx=(uint16)bi.cx;
cy=(uint16)bi.cy;
cy2=cy+cy;
pMe->planes=cy/cx;
//图片切割示例
/*BMP
_______
| / |
|a /b |
|_/___|
*/
//加载
CHECK_ERROR(IBITMAP_CreateCompatibleBitmap(pbmScreen, &pbmDdb, cx, cy2));//建立兼容位图pbmDdb 设备相关
CHECK_ERROR(IBITMAP_BltIn(pbmDdb, 0, 0, cx, cy, pbmDib, 0, 0, AEE_RO_COPY));//拷贝a
CHECK_ERROR(IBITMAP_BltIn(pbmDdb, 0, cy, cx, cy, pbmDib, 0, 0, AEE_RO_COPY));//拷贝b
//剪切a
CHECK_ERROR(IBITMAP_CreateCompatibleBitmap(pbmScreen, &pbmDhb, cx, cx));//建立兼容位图pbmDhb
for(y=1;y<cx;y++) CHECK_ERROR(IBITMAP_DrawHScanline(pbmDhb,y, cx-y+2, cx, 227, AEE_RO_COPY));//绘制紫红右下三角
CHECK_ERROR(IBITMAP_SetTransparencyColor(pbmDhb, 0));//设置辅助位图黑色透明色
for(y=0;y<cy;y+=cx)CHECK_ERROR(IBITMAP_BltIn(pbmDdb, 0, y, cx, cx, pbmDhb, 0, 0, AEE_RO_TRANSPARENT));//透明拷贝
IBITMAP_Release(pbmDhb);//释放辅助位图
pbmDhb=NULL;
//剪切b
CHECK_ERROR(IBITMAP_CreateCompatibleBitmap(pbmScreen, &pbmDhb, cx, cx));//建立兼容位图pbmDhb
for(y=0;y<cx-1;y++) CHECK_ERROR(IBITMAP_DrawHScanline(pbmDhb,y, 0, cx-y-2, 227, AEE_RO_COPY));//绘制紫红左上三角
CHECK_ERROR(IBITMAP_SetTransparencyColor(pbmDhb, 0));//设置辅助位图黑色为透明色
for(y=cy;y<cy2;y+=cx)CHECK_ERROR(IBITMAP_BltIn(pbmDdb, 0, y, cx, cx, pbmDhb, 0, 0, AEE_RO_TRANSPARENT));//透明拷贝
IBITMAP_Release(pbmDhb);//释放辅助位图
pbmDhb=NULL;
CHECK_ERROR(IBITMAP_SetTransparencyColor(pbmDdb, 227));//设置紫红为透明色
//告知sprite 引擎sprite 图像的位置及大小
CHECK_ERROR(ISPRITE_SetSpriteBuffer(pMe->pISprite, SPRITE_SIZE_32X32, pbmDdb));
//告知sprite 引擎 去渲染sprite 和tile 的位置
ISPRITE_SetDestination(pMe->pISprite, pbmScreen);
//告知sprite 引擎查找设置SPRITE_MATRIX_TRANSFORM 属性的sprite 变换的位置。
ISPRITE_SetTransformTable(pMe->pISprite, pMe->pTransform);
//释放位图
IBITMAP_Release(pbmDdb);
IBITMAP_Release(pbmDib);
IBITMAP_Release(pbmScreen);
return SUCCESS;
Error:
if (pbmScreen) IBITMAP_Release(pbmScreen);
if (pbmDib) IBITMAP_Release(pbmDib);
if (pbmDdb) IBITMAP_Release(pbmDdb);
CS_Dust2_UnloadResources(pMe);
return nErr;
}
//=====================================================
//CS_Dust2_UnloadResources
//=====================================================
static void CS_Dust2_UnloadResources(Data *pMe)
{
ISHELL_CancelTimer(pMe->a.m_pIShell, 0, pMe);
if (pMe->pISprite != NULL)
{
ISPRITE_Release(pMe->pISprite);
pMe->pISprite = NULL;
}
}
//=====================================================
//CS_Dust2_Display
//=====================================================
static void CS_Dust2_Display(Data *pMe)
{
int16 scrPos[8];//屏幕投影坐标 4点 (2D)
int16 curPos[12];//当前相对user空间位置 4点 (3D)
byte i;
IDISPLAY_ClearScreen(pMe->a.m_pIDisplay);//清屏
for(i=0;i<PLANE;i++)//绘制所有平面 (共PLANE个)
{
//计算当前相对user空间位置
//前三个点
curPos[0]=pMe->d3dPos[i][0]-pMe->userPos[0];
curPos[1]=pMe->d3dPos[i][1]-pMe->userPos[1];
curPos[2]=pMe->d3dPos[i][2]-pMe->userPos[2];
curPos[3]=pMe->d3dPos[i][3]-pMe->userPos[0];
curPos[4]=pMe->d3dPos[i][4]-pMe->userPos[1];
curPos[5]=pMe->d3dPos[i][5]-pMe->userPos[2];
curPos[6]=pMe->d3dPos[i][6]-pMe->userPos[0];
curPos[7]=pMe->d3dPos[i][7]-pMe->userPos[1];
curPos[8]=pMe->d3dPos[i][8]-pMe->userPos[2];
if(curPos[5]+curPos[8]<-23) continue;
//第四个点
curPos[9]=curPos[3]+curPos[6]-curPos[0];
curPos[10]=curPos[4]+curPos[7]-curPos[1];
curPos[11]=curPos[5]+curPos[8]-curPos[2];
//四点在屏幕投影坐标
if(curPos[2]==0) continue;
if(curPos[5]==0) continue;
if(curPos[8]==0) continue;
if(curPos[11]==0) continue;
scrPos[0]=pMe->hW*curPos[0]/curPos[2];
scrPos[1]=-pMe->hW*curPos[1]/curPos[2];
scrPos[2]=pMe->hW*curPos[3]/curPos[5];
scrPos[3]=-pMe->hW*curPos[4]/curPos[5];
scrPos[4]=pMe->hW*curPos[6]/curPos[8];
scrPos[5]=-pMe->hW*curPos[7]/curPos[8];
scrPos[6]=pMe->hW*curPos[9]/curPos[11];
scrPos[7]=-pMe->hW*curPos[10]/curPos[11];
//运算参数可能只适合32X32 sprite
//两片三角形贴图
//左上
pMe->pCmds[0].x = (scrPos[2]+scrPos[4])-16+pMe->hW;
pMe->pCmds[0].y = (scrPos[3]+scrPos[5])-16+pMe->hH;
pMe->pCmds[0].unSpriteIndex = pMe->d3dPos[i][9];//材质
pMe->pTransform[0].A = (scrPos[2]-scrPos[0]) << 4;
pMe->pTransform[0].B = (scrPos[4]-scrPos[0]) << 4;
pMe->pTransform[0].C = (scrPos[3]-scrPos[1]) << 4;
pMe->pTransform[0].D = (scrPos[5]-scrPos[1]) << 4;
//右下
pMe->pCmds[1].x = pMe->pCmds[0].x;
pMe->pCmds[1].y = pMe->pCmds[0].y;
pMe->pCmds[1].unSpriteIndex = pMe->pCmds[0].unSpriteIndex+pMe->planes;//材质
pMe->pTransform[1].A = (scrPos[6]-scrPos[4]) << 4;
pMe->pTransform[1].B = (scrPos[6]-scrPos[2]) << 4;
pMe->pTransform[1].C = (scrPos[7]-scrPos[5]) << 4;
pMe->pTransform[1].D = (scrPos[7]-scrPos[3]) << 4;
//draw
ISPRITE_DrawSprites(pMe->pISprite, pMe->pCmds);
}
//help info
IDISPLAY_DrawText(pMe->a.m_pIDisplay,AEE_FONT_BOLD,L"NT3D 1.1 (60 units)",-1,0,0,0,IDF_TEXT_TRANSPARENT|IDF_ALIGN_CENTER);
IDISPLAY_DrawText(pMe->a.m_pIDisplay,AEE_FONT_BOLD,pMe->fps,-1,0,132,0,IDF_TEXT_TRANSPARENT|IDF_ALIGN_RIGHT);
IDISPLAY_DrawText(pMe->a.m_pIDisplay,AEE_FONT_BOLD,pMe->sysclock,-1,0,118,0,IDF_TEXT_TRANSPARENT|IDF_ALIGN_RIGHT);
IDISPLAY_Update(pMe->a.m_pIDisplay);
pMe->frames++;
ISHELL_SetTimer(pMe->a.m_pIShell, 0, CS_Dust2_Display, (void*)pMe);
}
//KeyEvent
static void CS_Dust2_KeyEvent(Data *pMe)
{
ISHELL_SetTimer(pMe->a.m_pIShell, 20, CS_Dust2_KeyEvent, (void*)pMe);
if(pMe->Key & KEY_LEFT) pMe->userPos[0]-=3;
if(pMe->Key & KEY_RIGHT) pMe->userPos[0]+=3;
if((pMe->Key & KEY_UP)&&(pMe->userPos[2]<-10)) pMe->userPos[2]+=3;
if(pMe->Key & KEY_DOWN) pMe->userPos[2]-=3;
if(pMe->Key & KEY_HIGH) pMe->userPos[1]+=3;
if(pMe->Key & KEY_LOW) pMe->userPos[1]-=3;
}
//fps
static void CS_Dust2_Help(Data *pMe)
{
ISHELL_SetTimer(pMe->a.m_pIShell, 1000, CS_Dust2_Help, (void*)pMe);
FLOATTOWSTR(pMe->frames, pMe->buf, 32);
pMe->frames=0;
pMe->fps[0]=pMe->buf[8];
pMe->fps[1]=pMe->buf[9];
pMe->fps[2]=pMe->buf[10];
pMe->fps[3]=pMe->buf[11];
pMe->clocksec++;
if(pMe->clocksec>59) {pMe->clocksec=0;pMe->clockmin++;}
FLOATTOWSTR(pMe->clockmin, pMe->buf, 32);
pMe->sysclock[4]=pMe->buf[10];
pMe->sysclock[5]=pMe->buf[11];
pMe->sysclock[6]=':';
FLOATTOWSTR(pMe->clocksec, pMe->buf, 32);
pMe->sysclock[7]=pMe->buf[10];
pMe->sysclock[8]=pMe->buf[11];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -