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

📄 cs_dust2.c

📁 一个用纯c写的模拟3d程序,利用了些扩大缩小来模拟浮点数
💻 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 + -