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

📄 track.h

📁 演示一个火车头沿着轨道运行的动画。轨道可自定义(用鼠标绘制)
💻 H
字号:
#ifndef MY_TRACK_H
#define MY_TRACK_H
/* file: track.h
*/

#include "mouse.h"
#include "point.h"

static const float minangle=M_PI*2/3;/* 最小转折点角度 */
static const float minseglen=24.0;/* 最小轨道段长度 */

/* structures */
typedef struct
{
	long	size;/* number of points in the array */
	POINT*	point;/* point array */
}TRACK;

static int nWidth;
static int nHeight;
static int nMidWid;
static int nMidHei;

/* 从轨道的转折点列表中加入一个点 */
static POINT* PushPoint(TRACK* pTrack, POINT* pPoint)
{
	/* 将点加在末尾 */
	pTrack->point[pTrack->size].x=pPoint->x;
	pTrack->point[pTrack->size].y=pPoint->y;

	/* 容量加一,并返回末尾元素地址 */
	return &pTrack->point[(pTrack->size)++];
}/*end PushPoint*/

/* 从轨道的转折点列表中删除一个点 */
static POINT* PopPoint(TRACK* pTrack)
{
	if( pTrack->size > 0 )
		{
		/* 容量减一 */
		--(pTrack->size);
		if( pTrack->size > 0 )
			{
			/* 返回末尾元素地址 */
			return &pTrack->point[pTrack->size-1];
			}/*end if*/
		}/*end if*/

	return NULL;
}/*end PopPoint*/

/* 绘制整个轨道 */
static void DrawTrack(const TRACK* pTrack, BOOL bClose)
{
	POINT* pLast=&pTrack->point[pTrack->size-1];
	POINT* pPoint;

	for( pPoint=&pTrack->point[1]; pPoint<=pLast; ++pPoint )
		{
		line(pPoint->x,pPoint->y,(pPoint-1)->x,(pPoint-1)->y);
		}/*end for*/

	if( bClose )/* 首尾连接 */
		{
		line(pLast->x,pLast->y,pTrack->point[0].x,pTrack->point[0].y);
		}/*end if*/
}/*end DrawTrack*/

/* 选择一个已有轨道 */
static TRACK* Select(const TRACK* pTrack,int num)
{
	int i;

	cleardevice();
	setbkcolor(BLACK);
	settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
	setcolor(YELLOW);
	outtextxy(20,80,"Select a track");
	setcolor(LIGHTRED);
	outtextxy(10,130,"<- : Last Track");
	outtextxy(10,170,"-> : Mext Track");
	setcolor(LIGHTCYAN);
	outtextxy(10,210,"Enter : Select");
	outtextxy(10,250,"ESC   : Quit");

	setcolor(RED);
	DrawTrack(pTrack,TRUE);
	for( i=0; ; )
	{
	switch( (char)(getch()) )
		{
		case 75:/* <- : Last */
			{
			if( --i < 0 )
				{
				i=num-1;
				}/*end if*/

			/* 涂掉原有轨道 */
			setfillstyle(SOLID_FILL,BLACK);
			bar(nWidth-nHeight+36,36,nWidth-37,nHeight-37);

			/* 绘制新轨道 */
			setcolor(RED);
			DrawTrack(pTrack+i,TRUE);
			}break;

		case 77:/* -> : Next */
			{
			if( ++i >= num )
				{
				i=0;
				}/*end if*/

			/* 涂掉原有轨道 */
			setfillstyle(SOLID_FILL,BLACK);
			bar(nWidth-nHeight+36,36,nWidth-37,nHeight-37);

			/* 绘制新轨道 */
			setcolor(RED);
			DrawTrack(pTrack+i,TRUE);
			}break;

		case '\r':/* Enter */
			{
			/* 返回选定的轨道元素地址 */
			return pTrack+i;
			}break;

		case 27:/* Esc */
			{
			return NULL;
			}break;

		default:{
			}break;
		}/*end switch*/
	}/*end for*/
	return NULL;
}/*end Select*/

/* 绘制自定义轨道 */
static TRACK* Customize(TRACK* pTrack)
{
	POINT MousePos;/* 当前鼠标坐标 */
	POINT LastMPos;/* 上次鼠标坐标 */
	POINT* pLast=NULL;/* 最后一次确定的转折点 */
	BOOL bMouseMove;/* 鼠标是否移动 */
	BOOL bActive;/* 是否有绘图动作 */
	BOOL bValid;/* 当前这段轨道是否有效 */
	int nState;/* 鼠标按键状态 */
	BOOL bLastRButton=FALSE;
	float th;
	char s[32];

	cleardevice();
	setbkcolor(BLACK);

	InitMouse();/* 初始化鼠标 */
	/* 设置鼠标移动范围 */
	SetCursorRange(nWidth-nHeight+36,nWidth-37,36,nHeight-37);

	settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
	setcolor(YELLOW);
	outtextxy(20,40,"Use Mouse to");
	outtextxy(20,60,"draw your track");
	setcolor(LIGHTRED);
	outtextxy(10,100,"Left  Button :");
	outtextxy(10,140,"Right Button :");
	setcolor(WHITE);
	outtextxy(10,115,"Confirm current point");
	outtextxy(10,155,"Delete last point");
	setcolor(LIGHTCYAN);
	outtextxy(10,190,"Drag the mouse to");
	outtextxy(10,205,"draw a curve");
	setcolor(BROWN);
	outtextxy(10,240,"C : Clear the track");
	outtextxy(10,270,"R : Redraw the track");
	outtextxy(10,300,"Enter : Finish");
	outtextxy(10,330,"ESC   : Quit");
	setcolor(LIGHTGREEN);
	outtextxy(20,380,"Mouse Position");

	GetMouseState(&LastMPos);
	MousePos=LastMPos;
	ShowCursor(&MousePos);
	sprintf(s,"%d, %d",MousePos.x,MousePos.y);
	setcolor(LIGHTGREEN);
	outtextxy(44,395,s);
	setvisualpage(0);

	for( ; ; delay(1000) )
		{
		LastMPos=MousePos;

		/* 获取鼠标位置及按键状态 */
		nState=GetMouseState(&MousePos);

		/* 判断鼠标是否移动 */
		bActive=bMouseMove=( LastMPos.x != MousePos.x ) || ( LastMPos.y != MousePos.y );

		if( pLast != NULL )
			{
			/* 当前这段轨道长度大于 最小长度,则有效 */
			bValid=( Distance(pLast,&MousePos) > minseglen );
			if( bValid )
				{
				if( pTrack->size > 1 )
					{
					th=Angle(pLast-1,pLast,&MousePos);
					/* 轨道转折点的角度足够大(>2pi/3),则有效 */
					bValid=bValid&&( th>minangle || th<-minangle );
					}/*end if*/
				}/*end if*/
			}/*end if*/

		if( bMouseMove )
			{
			/* 显示鼠标坐标 */
			sprintf(s,"%d , %d",MousePos.x,MousePos.y);
			setfillstyle(SOLID_FILL,BLACK);
			bar(44,395,115,402);
			setcolor(LIGHTGREEN);
			outtextxy(44,395,s);

			ShowCursor(&LastMPos);/* 清除上次绘制的鼠标 */

			if( pLast != NULL )
				{
				/* 清除上次绘制的一段轨道 */
				setcolor(BLACK);
				line(pLast->x,pLast->y,LastMPos.x,LastMPos.y);

				/* 绘制当前这段轨道,无效为灰色,有效为红色 */
				setcolor((bValid)?RED:LIGHTGRAY);
				line(pLast->x,pLast->y,MousePos.x,MousePos.y);
				}/*end if*/
			}/*end if*/

		if( nState&2 )/* 鼠标右键按下 */
			{
			if( !bLastRButton )
				{
				bLastRButton=TRUE;

				/* 删除上次确定的转折点 */
				if( pTrack->size > 1 )/* 当前轨道有两个以上的转折点 */
					{
					setcolor(BLACK);

					/* bActive==TRUE说明有绘图动作,需重绘鼠标 */
					if( !bActive )
						{
						bActive=TRUE;
						ShowCursor(&LastMPos);/* 清除上次绘制的鼠标 */
						}/*end if*/

					/* 清除上次绘制的一段轨道 */
					line(pLast->x,pLast->y,MousePos.x,MousePos.y);
					/* 清除上上次绘制的一段轨道 */
					line(pLast->x,pLast->y,(pLast-1)->x,(pLast-1)->y);
					/* 删除末尾的点 */
					pLast=PopPoint(pTrack);

					/* 判断当前欲绘制的新轨道是否有效 */
					bValid=( Distance(pLast,&MousePos) > minseglen );
					if( bValid )
						{
						if( pTrack->size > 1 )
							{
							th=Angle(pLast-1,pLast,&MousePos);
							bValid=bValid&&( th>minangle || th<-minangle );
							}/*end if*/
						}/*end if*/

					/* 绘制当前这段轨道,无效为灰色,有效为红色 */
					setcolor((bValid)?RED:LIGHTGRAY);
					line(pLast->x,pLast->y,MousePos.x,MousePos.y);
					}
				else if( pTrack->size == 1 )/* 当前轨道只有一个转折点 */
					{
					setcolor(BLACK);
					if( !bActive )
						{
						bActive=TRUE;
						ShowCursor(&LastMPos);/* 清除上次绘制的鼠标 */
						}/*end if*/

					/* 清除上次绘制的一段轨道 */
					line(pLast->x,pLast->y,MousePos.x,MousePos.y);
					/* 删除末尾的点 */
					pLast=PopPoint(pTrack);
					}/*end if*/
				}/*end if*/
			}
		else	{
			bLastRButton=FALSE;

			if( nState&1 )/* 鼠标左键按下 */
				{
				/* 如果当前没有转折点 或 转折点有效,则确定当前点为转折点 */
				if( ( pLast == NULL ) || bValid )
					{
					if( pTrack->size < 1024 )
						{
						pLast=PushPoint(pTrack,&MousePos);
						}
					else	{
						goto finish;
						}/*end if*/
					}/*end if*/
				}/*end if*/
			}/*end if*/

		if( bioskey(1) )/* 有键按下 */
			{
			switch( (char)(getch()) )
				{
				case 'c':
				case 'C':/* Clear the track */
					{
					if( !bActive )
						{
						bActive=TRUE;
						ShowCursor(&LastMPos);/* 清除上次绘制的鼠标 */
						}/*end if*/

					/* 涂掉原有轨道 */
					setfillstyle(SOLID_FILL,BLACK);
					bar(nWidth-nHeight+36,36,nWidth-37,nHeight-37);

					/* 清除轨道所有转折点 */
					pTrack->size=0;
					pLast=NULL;
					}break;

				case 'r':
				case 'R':/* Redraw the track */
					{
					if( !bActive )
						{
						bActive=TRUE;
						ShowCursor(&LastMPos);/* 清除上次绘制的鼠标 */
						}/*end if*/

					/* 重绘原有轨道 */
					setcolor(RED);
					DrawTrack(pTrack,FALSE);

					/* 重绘当前这段轨道 */
					if( !bValid )
						{
						setcolor(LIGHTGRAY);
						line(pLast->x,pLast->y,MousePos.x,MousePos.y);
						}/*end if*/
					}break;

				case '\r':/* Enter */
					{
					if( pTrack->size >= 3 )
						{
finish:						if( ( pTrack->point[0].x == pLast->x ) && ( pTrack->point[0].y == pLast->y ) )
							{
							pLast=PopPoint(pTrack);
							if( pTrack->size < 3 )
								{
								break;
								}/*end if*/
							}/*end if*/

						if( !bActive )
							{
							ShowCursor(&MousePos);/* 清除上次绘制的鼠标 */
							}/*end if*/

						/* 清除上次绘制的一段轨道 */
						setcolor(BLACK);
						line(pLast->x,pLast->y,MousePos.x,MousePos.y);

						/* 重绘轨道,首尾连接 */
						setcolor(RED);
						DrawTrack(pTrack,TRUE);

						setfillstyle(SOLID_FILL,BLUE);
						bar(nMidWid-120,nMidHei-20,nMidWid+120,nMidHei+20);
						setcolor(YELLOW);
						outtextxy(nMidWid-80,nMidHei-4,"Press Any Key to Run");
						getch();
						return pTrack;
						}/*end if*/
					}break;

				case 27:/* Esc */
					{
					return NULL;
					}break;

				default:{
					}break;
				}/*end switch*/
			}/*end if*/

		if( bActive )
			{
			ShowCursor(&MousePos);/* 在新位置绘制鼠标 */
			}/*end if*/
		}/*end for*/

	return pTrack;
}/*end Customize*/

#endif /*define MY_TRACK_H*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -