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

📄 ship.cpp

📁 是3D游戏一书中所讲的游戏引擎fly3D 包括fly3D引擎的源码及应用此引擎开发出来的游戏实例 有fly3D引擎的教程,易于step by step跟学
💻 CPP
字号:
#include "game.h"

ship::ship() 
{ 
	type=TYPE_SHIP;
	lasthitfrom=-1;
	lasthittime=0;
	flag=0;
	flag2=0;
	flag3=0;
	points=0; 
	player=0;
	abtime=0;
	rotvel.null(); 
	rotforce.null(); 
	mouserot.null(); 
	dynlight.null();
	firesel=0;
}

int ship::message(vector& p,float rad,int msg,int param,void *data)
{
	if (msg==FLYOBJM_DAMAGE)
	{
		if (directx->mpmode!=FLYMP_CLIENT && (flag3&0x20000)==0)
			{
			float len;
			mp_data2 msg;

			msg.v=pos-p;
			len=msg.v.length();
			if (len>rad || len<SMALL)
				return 0;

			flyengine->excludecollision=this;
			if(flyengine->collision_test(flyengine->bsp, p, pos))
				{
				flyengine->excludecollision=0;
				return 0;
				}
			flyengine->excludecollision=0;

			lasthittime=flyengine->cur_time;
			lasthitfrom=param;

			msg.f=*((float *)data);
			msg.v*=msg.f/(len*100.0f);
//			msg.f=*((float *)data)*(1-len/rad);
//			msg.v*=msg.f/(len*100.0f);
			force+=msg.v;
			shield-=msg.f;
			msg.type=FLYMP_MSG_DAMAGE;
			msg.from=directx->players[player].dpid;

			directx->send_message((mp_msg *)&msg,sizeof(mp_data2));

			if (directx->mpmode==FLYMP_NOMP)
				flyengine->filter.x+=msg.f>1.0f?1.0f:msg.f;
			}
	}
	else
	if (msg==FLYOBJM_ILLUM)
	{
		float fac=(p-pos).length()/rad;
		if (fac<1.0f)
			dynlight+=*((vector *)data)*(1.0f-fac);
	}

	return 1;
}

int ship::step(int dt)
{
	float len;

	switch( directx->mpmode )
	{
	case FLYMP_SERVER:
		{
		if (player==0)
			{
			life=-1;
			flyengine->cam=source;
			flyengine->player=source;
			directx->players[0].data=0;
			return 0;
			}

		if (shield<0 && flag2==0)
			{
			flag2=exptime;
			mp_send_pos(
				FLYMP_MSG_KILL,
				(lasthitfrom>=0)?directx->players[lasthitfrom].dpid:-1);
			}

		if (flag2==0 || flag2==exptime)
			{
			len=vel.length();
			if (len>0)
				{
				vel/=len;
				if (flag2==0)
					{
					len-=dt*veldamp;
					if (len<0) len=0;

					if (len>maxvel+speedboost)
						len=maxvel+speedboost;
					}
				vel*=len;
				}

			if (shield<0 && flag2==exptime)
				force.z-=0.0005f;

			flyengine->excludecollision=this;
			particle::step(dt);
			flyengine->excludecollision=0;
			}

		if (flag2)
			if (flag2==exptime)
				if (flyengine->hitobj)
					{
					flag2-=dt;
					mp_send_pos(
						FLYMP_MSG_EXPLODE,
						(lasthitfrom>=0)?directx->players[lasthitfrom].dpid:-1);
					remove_from_bsp();
					}
				else { ; }
			else 
				if (flag2>dt)
					flag2-=dt;
				else
					{
					pos=source->pos;
					add_to_bsp();
					vel.null();
					align_z(vector(0,0,1));
					rotate(rot);
					shield=((ship *)source)->shield;
					flag2=0;
					flag3=0;
					}

		if (flag3)
			{
			int i=flag3&0xffff;
			if (i<dt)
				flag3=0;
			else 
				flag3=(flag3&0xffff0000)|(i-dt);
			}

		force.null();
		life=1;
		}
		break;
	case FLYMP_NOMP:
		if (shield<0 && flag2==0)
			{
			flag2=exptime;
			expcam.pos=pos;
			expcam.node=node;
			*((local_system *)&expcam)=*((local_system *)this);
			}
	case FLYMP_CLIENT:
		{
		if (flag2==0 || flag2==exptime)
			{
			if (player==0)
				{
				if (flag2==0)
					check_keys(dt);

				rotvel+=rotforce;
				rotforce.x=rotforce.y=rotforce.z=0;
				rotate(mouserot);
				mouserot.x=mouserot.y=0;

				len=rotvel.length();
				if (len>0)
					{
					rotvel/=len;
					len-=dt*angulardamp;
					if (len<0) len=0;
					if (len>angularmaxvel) len=angularmaxvel;
					rotvel*=len;
					rotate(rotvel*(float)dt);
					}
				}

			len=vel.length();
			if (len>0)
				{
				vel/=len;
				if (flag2==0)
					{
					len-=dt*veldamp;
					if (len<0) len=0;

					if (len>maxvel+speedboost)
						len=maxvel+speedboost;
					}
				vel*=len;
				}

			if (shield<0 && flag2==exptime)
				force.z-=0.0005f;

			flyengine->excludecollision=this;
			particle::step(dt);
			flyengine->excludecollision=0;
			}

		if (flag2)
			if (flag2==exptime)
				if (directx->mpmode==FLYMP_NOMP && flyengine->hitobj)
					{
					if (exp) 
						exp->do_explode(pos,Z,player);
					flag2-=dt;
					remove_from_bsp();
					}
				else { ; }
			else 
				if (flag2>dt)
					flag2-=dt;
				else
					{
					pos=source->pos;
					add_to_bsp();
					vel.null();
					align_z(vector(0,0,1));
					rotate(rot);
					shield=((ship *)source)->shield;
					flag2=0;
					flag3=0;
					}

		if (flag3)
			{
			int i=flag3&0xffff;
			if (i<dt)
				flag3=0;
			else 
				flag3=(flag3&0xffff0000)|(i-dt);
			}

		force.null();
		life=1;

		if (flag&0x10 && englight)
			{
			englight->pos=pos+Z*engpos;
			flyengine->stepobj=englight;
			englight->step(dt);
			}
		
		if (spot && (flag&0x100))
			spot->reposition(this);
		}
		break;
	}
	
	if (player==0)
		directx->set_listener(&pos.x,0,&Y.x,&Z.x);

	return 1;
}

void ship::draw()
{
	if (objmesh==0) 
		return;
	if (player==0 && flag2!=exptime)
		return;
	if (flag2 && flag2!=exptime)
		return;
	
	// init dynamic light
	if (flyengine->hwlights)
		{
		objmesh->color.vec(1,1,1,1);
		dynlights.init_draw(this);
		}
	else if (node)
		{
		objmesh->color=node->color+dynlight;
		dynlight.null();
		}

	// draw ship and shield
	glPushMatrix();
	glTranslatef(pos.x,pos.y,pos.z);
	glMultMatrixf((float *)&mat);
	if (flag3&SHIP_FLAG3_INVISIBLE)
		objmesh->color.w=invistransp;
	else objmesh->color.w=1.0;
	objmesh->draw();
	if (shieldmesh)
		if ((flag3&SHIP_FLAG3_INVENSIBLE) || flyengine->cur_time-lasthittime<500 || (flag2==exptime))
		{
		glDepthMask(GL_FALSE);
		glBlendFunc(GL_ONE, GL_ONE);
		if (flag2==exptime)
			{
			shieldmesh->color=killcolor;
			shieldmesh->color.w=1.0f;
			}
		else
		if (flag3&SHIP_FLAG3_INVENSIBLE)
			{
			shieldmesh->color=invencolor;
			shieldmesh->color.w=1.0f;
			}
		else 
			{
			float t=1.0f-(flyengine->cur_time-lasthittime)/500.0f;
			shieldmesh->color=hitcolor*t;
			shieldmesh->color.w=t;
			}
		shieldmesh->scrollu=shieldmesh->scrollv=(flyengine->cur_time%750)/750.0f;
		shieldmesh->draw();
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glDepthMask(GL_TRUE);
		}
	glPopMatrix();

	// end dynamic lights
	if (flyengine->hwlights)
		dynlights.end_draw();

	// draw ship engine light
	if (flag&0x10 && englight)
		{
		englight->pos=pos+Z*engpos;
		englight->draw();
		}

	// draw ship engine halo
	if (enghalo && (flag3&SHIP_FLAG3_INVISIBLE)==0)
		{
		enghalo->pos=pos+Z*engpos;
		enghalo->color.w=vel.length()/maxvel*0.6f+0.2f;
		if (enghalo->color.w>0.6f) 
			enghalo->color.w=0.6f;
		enghalo->draw();
		}
}

int ship::get_custom_param_desc(int i,param_desc *pd)
{
	if (pd==0)
		return 33;
	else 
	switch(i)
	{
		case 0:
			pd->type='p';
			pd->data=&display;
			strcpy(pd->name,"display");
			break;
		case 1:
			pd->type='f';
			pd->data=&speedboost0;
			strcpy(pd->name,"speedboost");
			break;
		case 2:
			pd->type='f';
			pd->data=&shield;
			strcpy(pd->name,"shield");
			break;
		case 3:
			pd->type='f';
			pd->data=&maxshield;
			strcpy(pd->name,"maxshield");
			break;
		case 4:
			pd->type='f';
			pd->data=&maxvel;
			strcpy(pd->name,"maxvel");
			break;
		case 5:
			pd->type='f';
			pd->data=&veldamp;
			strcpy(pd->name,"veldamp");
			break;
		case 6:
			pd->type='f';
			pd->data=&angularmaxvel;
			strcpy(pd->name,"angularmaxvel");
			break;
		case 7:
			pd->type='f';
			pd->data=&angulardamp;
			strcpy(pd->name,"angulardamp");
			break;
		case 8:
			pd->type='3';
			pd->data=&objmesh;
			strcpy(pd->name,"objmesh");
			break;
		case 9:
			pd->type='3';
			pd->data=&shieldmesh;
			strcpy(pd->name,"shieldmesh");
			break;
		case 10:
			pd->type=TYPE_EXPLODE;
			pd->data=&exp;
			strcpy(pd->name,"explode");
			break;
		case 11:
			pd->type='i';
			pd->data=&exptime;
			strcpy(pd->name,"exptime");
			break;
		case 12:
			pd->type='i';
			pd->data=&maxabtime;
			strcpy(pd->name,"maxabtime");
			break;
		case 13:
			pd->type=TYPE_LIGHT;
			pd->data=&englight;
			strcpy(pd->name,"englight");
			break;
		case 14:
			pd->type=TYPE_SPRITE_LIGHT;
			pd->data=&enghalo;
			strcpy(pd->name,"enghalo");
			break;
		case 15:
			pd->type='f';
			pd->data=&engpos;
			strcpy(pd->name,"engpos");
			break;
		case 16:
			pd->type=TYPE_SPOT_LIGHT;
			pd->data=&spot;
			strcpy(pd->name,"spot");
			break;
		case 17:
			pd->type='f';
			pd->data=&mousespeed;
			strcpy(pd->name,"mousespeed");
			break;
		case 18:
			pd->type='f';
			pd->data=&forcefactor;
			strcpy(pd->name,"forcefactor");
			break;
		case 19:
			pd->type='c';
			pd->data=&hitcolor;
			strcpy(pd->name,"hitcolor");
			break;
		case 20:
			pd->type='c';
			pd->data=&invencolor;
			strcpy(pd->name,"invencolor");
			break;
		case 21:
			pd->type='c';
			pd->data=&killcolor;
			strcpy(pd->name,"killcolor");
			break;
		case 22:
			pd->type='f';
			pd->data=&invistransp;
			strcpy(pd->name,"invistransp");
			break;
		case 23:
			pd->type='i';
			pd->data=&ng;
			strcpy(pd->name,"nguns");
			break;
		case 24:
			pd->type=TYPE_GUN;
			pd->data=&g[0];
			strcpy(pd->name,"gun1");
			break;
		case 25:
			pd->type=TYPE_GUN;
			pd->data=&g[1];
			strcpy(pd->name,"gun2");
			break;
		case 26:
			pd->type=TYPE_GUN;
			pd->data=&g[2];
			strcpy(pd->name,"gun3");
			break;
		case 27:
			pd->type=TYPE_GUN;
			pd->data=&g[3];
			strcpy(pd->name,"gun4");
			break;
		case 28:
			pd->type=TYPE_GUN;
			pd->data=&g[4];
			strcpy(pd->name,"gun5");
			break;
		case 29:
			pd->type=TYPE_GUN;
			pd->data=&g[5];
			strcpy(pd->name,"gun6");
			break;
		case 30:
			pd->type=TYPE_GUN;
			pd->data=&g[6];
			strcpy(pd->name,"gun7");
			break;
		case 31:
			pd->type=TYPE_GUN;
			pd->data=&g[7];
			strcpy(pd->name,"gun8");
			break;
		case 32:
			pd->type=TYPE_GUN;
			pd->data=&g[8];
			strcpy(pd->name,"gun9");
			break;
	}
	return 0;
}

void ship::check_keys(int time_step)
{
	static int lastmouse[2][2]={ { 0,0 },{ 0,0 } },lm=0;
	float mousedx=(directx->dims.lX+lastmouse[0][0]+lastmouse[1][0])/3.0f;
	float mousedy=(directx->dims.lY+lastmouse[0][1]+lastmouse[1][1])/3.0f;
	lastmouse[lm][0]=directx->dims.lX;
	lastmouse[lm][1]=directx->dims.lY;
	lm=!lm;

	unsigned char *diks=directx->diks;
		
	if (diks[0x38])
		{
		if (diks[0xcb])
			force-=X/forcefactor;
		if (diks[0xcd])
			force+=X/forcefactor;
		if (diks[0xc8])
			force+=Y/forcefactor;
		if (diks[0xd0])
			force-=Y/forcefactor;
		}
	else
		{
		if (diks[0xcb])
			rotforce.y+=1;
		if (diks[0xcd])
			rotforce.y-=1;
		if (diks[0xc8])
			rotforce.x-=1;
		if (diks[0xd0])
			rotforce.x+=1;
		}

	if (diks[0x1e])
		rotforce.z+=1;
	if (diks[0x20])
		rotforce.z-=1;

	if (diks[0x11])
		if ((flag&0x1000)==0)
			flag^=0x1100;
		else ;
	else if (flag&0x1000)
			flag^=0x1000;

	if (diks[0x10])
		force-=X/forcefactor;
	if (diks[0x12])
		force+=X/forcefactor;

	if (diks[0x1f] || diks[0x3A])
		force-=Z/forcefactor;
	if (diks[0x2d])
		force+=Z/forcefactor;

	if (diks[0x3A])
		{
		if (abtime>0)
			{
			speedboost=speedboost0;
			abtime-=time_step;
			flag|=0x10;
			}
		else 
			{
			abtime=0;
			speedboost=0.0f;
			flag&=0xff0f;
			}
		}
	else 
		{
		abtime+=time_step/4;
		if (abtime>maxabtime)
			abtime=maxabtime;
		speedboost=0.0f;
		flag&=0xff0f;
		}

	if (diks[0x38])
		{
		if (mousedx>4)
			force+=X/forcefactor;
		else if (mousedx<-4)
			force-=X/forcefactor;

		if (mousedy>4)
			force-=Y/forcefactor;
		else if(mousedy<-4)
			force+=Y/forcefactor;
		}
	else
		{
		mouserot.y=-mousedx/mousespeed;
		mouserot.x=mousedy/mousespeed;
		}

	int i;
	for( i=0;i<9;i++ )
		if (directx->diks[2+i])
			{
			firesel=i;
			break;
			}
	if (g[firesel])
	if (directx->diks[0x9d] || directx->diks[0x39] || 
		directx->dims.rgbButtons[0])
		if (g[firesel]->fire_status())
			if (directx->mpmode==FLYMP_NOMP)
				g[firesel]->fire(this,player);
			else mp_send_pos(FLYMP_MSG_POS,flag|firesel|(points<<16));
}

void ship::draw_game_status()
{
	static char str[256];
	int i,j,k;

	tc->use(display);
	glBegin(GL_QUADS);
		glTexCoord2f(0,1);
		glVertex2i(0,0);
		glTexCoord2f(0.375f,1);
		glVertex2i(48,0);
		glTexCoord2f(0.375f,0);
		glVertex2i(48,128);
		glTexCoord2f(0,0);
		glVertex2i(0,128);
	glEnd();

	tc->use(-1);
	glBegin(GL_QUADS);
		glColor4ub(153,255,178,255);
		j=18+(int)(104.0f*abtime/maxabtime);
		glVertex2i(5,18);
		glVertex2i(16,18);
		glVertex2i(16,j);
		glVertex2i(5,j);
	
		glColor4ub(40,40,255,255);
		j=18+(int)(104*shield/maxshield);
		glVertex2i(31,18);
		glVertex2i(42,18);
		glVertex2i(42,j);
		glVertex2i(31,j);
	glEnd();
	
	for( i=0;i<directx->nplayers;i++)
		{
		sprintf(str,"%s (%i)",directx->players[i].name,((ship *)directx->players[i].data)->points);
		flyengine->draw_text( 0, i*16, str );
		}
	k=screen_sy-16;
	j=screen_sx/2;
	for( i=0;i<ng;i++,j+=32 )
		{
		if (g[i])
			if (firesel==i)
				sprintf(str,"[%i]",g[i]->firecount);
			else sprintf(str,"%i",g[i]->firecount);
		flyengine->draw_text( j, k, str );
		}
	static DWORD t=timeGetTime();
	static int frame_rate=0,frame_count=0;
	frame_count++;
	if (flyengine->cur_time-t>1000)
		{
		frame_rate=frame_count*1000/(flyengine->cur_time-t);
		t=flyengine->cur_time;
		frame_count=0;
		}
	if (flyengine->cur_time - flyengine->status_msg_time > 2000)
		{
		sprintf(str,"FPS:%i N:%i",frame_rate,flyengine->nodedrawcount);
		flyengine->draw_text( screen_sx-96, 0, str );
		}
}

void ship::mp_send_pos(int msgtype,int msgflag)
{
	static struct mp_data data;
	
	data.type=msgtype;
	data.dpid=directx->players[player].dpid;
	data.flag=msgflag;
	data.pos=pos;
	data.vel=vel;
	data.Y=Y;
	data.Z=Z;

	directx->send_message((mp_msg *)&data,sizeof(struct mp_data));
}

mesh *ship::ray_intersect(vector& ro,vector& rd,vector& ip,float& dist,int &facenum,float rad)
{
	if (shieldmesh)
	{
		static float d1,d2;
		vector 
			ro_local=(ro-pos)*mat_t,
			rd_local=rd*mat_t;
		if (shieldmesh->bbox.ray_intersect(ro_local,rd_local,d1,d2))
		{
		facenum=shieldmesh->ray_intersect(ro_local,rd_local,ip,dist,rad);
		if (facenum>-1)
			{
			if (directx->mpmode!=FLYMP_CLIENT && (flag3&0x20000)==0 && flyengine->stepobj 
				&& (flyengine->stepobj->type==TYPE_LASER || flyengine->stepobj->type==TYPE_MISSILE) 
				&& dist<1.0f && ((gun_projectile *)flyengine->stepobj)->damage>0.0f)
					{
					shield-=((gun_projectile *)flyengine->stepobj)->damage;
					lasthittime=flyengine->cur_time;
					if (directx->mpmode==FLYMP_SERVER)
						{
						mp_data2 msg;
						msg.f=((gun_projectile *)flyengine->stepobj)->damage;
						msg.v=vel;
						msg.type=FLYMP_MSG_DAMAGE;
						msg.from=directx->players[player].dpid;
						directx->send_message((mp_msg *)&msg,sizeof(mp_data2));
						}
					}
			ip=ip*mat+pos;
			return shieldmesh;
			}
		}
	}
	return 0;
}

⌨️ 快捷键说明

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