骑着大鱼吃小鱼游戏3D版源码

9日,醒来有点早,继续热水饺。

这是个3D版的大鱼吃小鱼游戏,可以骑着一条大鱼去吃比自己小的鱼,还是相同的小游戏架构,可以嵌入RPG中做为任务。游戏场景同样是随机生成的,鱼群的游动有flocking的效果。. 

  如果碰到比自己大的鱼会被吃掉

 这次场景的随机生成使用的是marching cube算法,不像普通高度地形的单层效果,marching cube可以做出溶洞的效果。先生成随机的高度图来挖出溶洞的主体,再配合迷宫算法挖出细小的通道。溶洞山石的纹理展开是先使用大致的map,然后再使用类似布料的弹簧质点做拉伸。

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/FishEat/MiniGameFish.h
//  @Brief:     MiniGameFish
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================
 

#ifndef  __MiniGameFish__H__
#define  __MiniGameFish__H__

#include "Rpg/MiniGame.h"
enum  FishSize;
class FishEntity;
class FishFlock;
class FishRole; 

enum MiniFishCmd
{
	CMD_PlayerMove,   
	CMD_FishMove  ,
	CMD_EatFish   , 
	CMD_GameOver  ,
	CMD_Restart   ,
};
const char* FishCmdToString(int enumeration);
//随机生成地图
class MarchingCubeSys;
namespace RendSys
{
	class Mesh;
};
class FishScene
{
public:
	FishScene();
	~FishScene();
	void Free();
	//倒置溶洞的室内场景
	void GenRacingRoad2();
	//穿山隧道的室外场景
	void GenRacingRoad3();
	void Render();

	void SaveToCollide(RendSys::Mesh* mesh);
	//
	TexturePtr m_texture;	
	MarchingCubeSys* m_marchingCubeSys;
};

//水下 雾比较大 有光线刻蚀  有气泡和扭曲  岩壁碰撞
class MiniGameFish:public MiniGame
{
public:
	MiniGameFish();
	virtual~MiniGameFish();
	virtual bool Start();
	virtual bool Stop();
	virtual bool Render();
	virtual void RenderUI();
	virtual bool Update();
	virtual bool Free();
	virtual bool KeepResource(bool once,int& circle,String& nextTip);
	//三种类型结构
	virtual MiniPlayer*  CreatePlayer();
	virtual MiniPlayer*  CreateRobot ();
	virtual MiniPlayer*  CreateRole  ();

	//处理游戏网络命令包
	virtual int  ProcessPacketCmd(PacketBase* packet);
	//virtual const char* CmdToString(const char* stream,int len);

	RectF    m_groundRect;
	//todo fish flock
	static const int AIFISHNUM = 15;
	FishEntity*  m_fishEntitys[AIFISHNUM];
	
	FishRole*    m_myRolePlayer;

#define MaxFlocks  32
	FishFlock*   m_fishFlocks[MaxFlocks];

};
extern MiniGameFish* G_FishGame;

#endif

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/FishEat/MiniGameFish.cpp
//  @Brief:     MiniGameFish
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================
 
#include "General/Pch.h"
#include "General/General.h"
#include "General/StringUtil.h"
#include "General/Timer.h"
#include "General/Window.h"
#include "AI/Navigation/SteeringSystem.h"
#include "Gui/GuiMgr.h"
#include "Gui/RpgGuis.h"
#include "MiniGameFish.h"
#include "Render/Camera.h"
#include "Render/Font.h"
#include "Render/RendDriver.h"
#include "Render/SceneMgr.h"
#include "Render/Water.h"
#include "Rpg/SyncGameInfo.h"
#include "Rpg/RpgGame.h"
#include "Sound/SoundListener.h"
#include "Sound/SoundManager.h"
#include "FishEat/FishEntity.h"
#include "FishEat/FishCharacter.h"
#include "FishEat/MiFishEat_PlayGui.h"
#include "Render/FishFlock.h"
#include "FishCharacter.h"
#include "Net/PacketList.h"
#include "Render/Shader.h"
#include "Render/Terrain.h"
#include "Render/Maze.h"
#include "Math/MarchingCubes.h"
#include "Render/MC_Misc.h"
#include "General/Pce.h"

#define InWaterDis 1

#define UndeadTime 4

MiniGameFish* G_FishGame;

//关于镜头://摄像机tarpos 1驾驶员 
class CameraCtrlerFishing: public CameraCtrlerTarget
{
public:
	CameraCtrlerFishing();
	virtual void  Update();
	Mode mode;
};

CameraCtrlerFishing::CameraCtrlerFishing()
:mode(ThirdPerson)
{
	m_distToTar = 70;
}

void CameraCtrlerFishing::Update()
{
	if(G_Keyboard->IsKeyPressed(DIK_LCONTROL))
	{
		if(G_Keyboard->IsKeyUping(DIK_V))
		{
			mode = (mode==FirstPerson)?ThirdPerson:FirstPerson;
		}
	}

	if (G_FishGame==NULL)
	{
		m_toBeRemove = true;
		return;
	}

	FishCharacter* role = G_FishGame->m_myRolePlayer;
	if (role)
	{
		Camera* camera = G_Camera;

		//if (mode==FirstPerson)
		//{
		//	vec3  tarPos = role->GetPos();

		//	vec3  head = role->m_rot*vec3(0,0,1);//car->GetHeading();
		//	float DisWheelH = role->GetStyle()->DisWheelH;
		//	camera->SetTarPos(tarPos+head*(DisWheelH*0.5f));

		//	vec3  right = role->m_rot*vec3(-1,0,0);//car->GetHeadingRight();
		//	camera->SetDir(head,Cross(right,head));

		//	m_distToTar = 0.1f;//car->GetStyle()->DisWheelH*0.5f;

		//	camera->SetEyePos(tarPos - head*m_distToTar);
		//}
		//else
		{ 
			//CheckMouseRot(MOUSE_RIGHT, 10, -HALFPI * 0.2f, HALFPI * 0.2f);
			CheckWheelDis(50,500); 

			vec3 head = role->GetHeading();
			head.y = -0.5f;
			head.Normalize();

			vec3 up = head.Cross(vec3(0,1,0)).Cross(head);
			up.Normalize(); 
			camera->SetDir(head,up);

			vec3 tarPos = role->GetPos();
			SetTarPos(tarPos);
			camera->SetEyePos(tarPos - camera->GetHeadDir()*m_distToTar);
		}

		CheckSceneCollide(G_FishGame->m_movieCollide);
		//CheckSceneCollide(G_RpgMap->GetCollideMovie());
	}
}

//==================^_^==================^_^==================^_^==================^_^

const char* FishCmdToString(int enumeration)
{
	switch(enumeration)
	{
	case CMD_PlayerMove:return "CMD_PlayerMove";		
	case CMD_FishMove  :return "CMD_FishMove  ";	
	case CMD_EatFish   :return "CMD_EatFish   ";		
	case CMD_GameOver  :return "CMD_GameOver  ";	
	case CMD_Restart   :return "CMD_Restart   ";		
	default             :return "CMD_unknow";
	}
	return "CMD_unknow";
}


FishScene G_FishScene;

MiniGameFish::MiniGameFish()
{
	G_FishGame = this;
	CmdEnumToString = FishCmdToString;
	for (int i=0;i<AIFISHNUM;i++)
	{
		m_fishEntitys[i] = NULL;
	}
}
MiniGameFish::~MiniGameFish()
{
	MiniGameFish::Free();
	G_FishGame = NULL;
}

bool MiniGameFish::Start()
{
	m_myRolePlayer = NULL;
	if(!MiniGame::Start())
		return false;

	if (m_movieScene == NULL)
	{
		LoadConfig loader(LoadConfig::GenDonotReShrinkBound,true,true);
		m_movieScene = new RendSys::MovieClip;
		m_movieScene->LoadFromFile("data/minigame/fisheat/scene.movie",&loader);

		Frame frame;
		frame.SetPos(m_startPos);
		m_movieScene->SetProgramFrame(&frame);
		m_movieScene->Advance();
	}

	if (m_movieCollide == NULL)
	{
		m_movieCollide = new RendSys::MovieClip;
	}
	Frame frame;
	frame.SetPos(m_startPos);

	if (0)
	{
		LoadConfig loader(LoadConfig::GenReShrinkBound,false,false);
		m_movieCollide = new RendSys::MovieClip;
		m_movieCollide->LoadFromFile("data/minigame/fisheat/scene_collide.movie",&loader);

		m_movieCollide->SetProgramFrame(&frame);
		m_movieCollide->Advance();
	}
	else
	{
		//随机生成
		G_FishScene.GenRacingRoad2();
		//rand Collide
		LoadConfig loader(LoadConfig::GenDonotReShrinkBound,false,false);
		m_movieCollide->LoadFromFile("data/MiniGame/Racing/collide.movie",&loader);
		MovieClip* movie = m_movieCollide->GetMovieClip("scene");
		if (movie)
		{
			Mesh* mesh = movie->GetMesh();
			G_FishScene.SaveToCollide(mesh);
		}
		frame.SetPos(vec3(m_startPos.x,m_startPos.y - 70,m_startPos.z));
		m_movieCollide->SetProgramFrame(&frame);
		m_movieCollide->Advance();
	}

	m_deadAccumeTime = 0;

	float width__  = G_Window->m_iWidth; 
	float height_  = G_Window->m_iHeight; 
	SetBoardRect(RectF((G_Window->m_iWidth-width__)/2,(G_Window->m_iHeight-height_)/2,width__,height_), 
		RectF(m_startPos.x-50,m_startPos.z-50,100,100),
		m_startPos.y+0.1f);

	FishStyle* fishStyle = G_StyleMgr->GetStyle<FishStyle>(20001);

	//FISH 1~9
	int level = G_MyRole->m_fishLevel;
	if (level>6)
	{
		level = 6;
	}
	bool bBigFish = false;
	for (int i=0;i<AIFISHNUM;i++)
	{
		if (m_fishEntitys[i]==NULL)
		{
			m_fishEntitys[i] = new FishEntity;
		}
		m_fishEntitys[i]->m_hideAccumeTime = RandRange(1.0f,3.0f);
		m_fishEntitys[i]->m_fishSize = (FishSize)((RandRange(1,100)%3)+1);
		switch(m_fishEntitys[i]->m_fishSize)
		{
		case FS_SMALL:
			fishStyle = G_StyleMgr->GetStyle<FishStyle>(20001+level);
			m_fishEntitys[i]->SetStyle(fishStyle);
			m_fishEntitys[i]->GetRenderCharacter()->SetScale(vec3(fishStyle->scale,fishStyle->scale,fishStyle->scale)*0.7f);
			break;
		case FS_MIDDLE:
			fishStyle = G_StyleMgr->GetStyle<FishStyle>(20001+level+1);
			m_fishEntitys[i]->SetStyle(fishStyle);
			m_fishEntitys[i]->GetRenderCharacter()->SetScale(vec3(fishStyle->scale,fishStyle->scale,fishStyle->scale)*1.2f);
			break;
		case FS_BIG:
			fishStyle = G_StyleMgr->GetStyle<FishStyle>(20001+level+2);
			m_fishEntitys[i]->SetStyle(fishStyle);
			m_fishEntitys[i]->GetRenderCharacter()->SetScale(vec3(fishStyle->scale,fishStyle->scale,fishStyle->scale)*2.0f);
			break;
		}
	}
	vec3 pos;
	float groundSize = BoardRect3D.width;
	for (int i=0;i<AIFISHNUM;i++)
	{
		pos = m_startPos+vec3(RandRange(-groundSize,groundSize),5,RandRange(-groundSize,groundSize));
		m_fishEntitys[i]->SetPos(pos);
		m_fishEntitys[i]->m_homePos = pos;
		//m_fishEntitys[i]->SetHeading(head);
	}
	//
	for (int i = 0; i < MaxFlocks; i++) 
	{
		m_fishFlocks[i] = new FishFlock();
		m_fishFlocks[i]->Init(RandRange(8,30),10,
			m_startPos+vec3(RandRange(-300,300),5,RandRange(-300,300)),
			vec3(300,50,300));
	}

	for (int i = 0; i < MaxFlocks; i++) 
	{
		m_fishFlocks[i]->m_enemyFlock = m_fishFlocks[(i+1)%MaxFlocks];
	}
	//==================^_^

	for (int i=0;i<m_allPlayerNum;i++)
	{
		FishCharacter* thePlayer = (FishCharacter*)m_miniPlayer[i];

		//SetStyle
		FishStyle* style = G_StyleMgr->GetStyle<FishStyle>(20001);//90001+i);
		if (style==NULL)
		{
			return false;
		}
		thePlayer->SetStyle(style);

		//InitPos
		FishRobot* theRobot = dynamic_cast<FishRobot*>(thePlayer);
		FishRole* theRole = dynamic_cast<FishRole*>(thePlayer);
		vec3 pos = m_startPos+0.5f*vec3(RandRange(-groundSize,groundSize),5,RandRange(-groundSize,groundSize));
		thePlayer->SetPos(pos);
		if (theRole)
		{
			theRole->SetWorkingWithAI(false);
			theRole->m_homePos = pos;
		}
		else if (theRobot)
		{
			theRobot->SetWorkingWithAI(true);
			theRobot->m_homePos = pos;
		}

		
		{
			thePlayer->m_driver = new FishDriver;
			Style* style = G_StyleMgr->GetStyle(thePlayer->GetPlayerInfo()->style);
			thePlayer->m_driver->SetStyle(style);
			thePlayer->m_driver->GetRenderCharacter()->SetScale(vec3(1.2f,1.2f,1.2f));
			thePlayer->m_driver->GetRenderCharacter()->PlayAnim("drive");
		}
	}

	//进入miniplaygui,(选人、选关卡都已在房间里进行完毕)。
	if(GetStyle()) G_GuiMgr->PushGui(GetStyle()->playGUI.c_str(),GL_DIALOG);

	//
	for(int i = 0; i < m_allPlayerNum; i++)
	{
		if(m_miniPlayer[i])
			m_miniPlayer[i]->Start();
	}

	//设置摄像机
	CameraCtrlerFishing* ctrler = new CameraCtrlerFishing;
	ctrler->SetDistToTar(300);
	ctrler->SetTarPos(m_startPos);
	G_Camera->PushCtrler(ctrler);
	G_Camera->SetEuler(0, -30, 0);
	//片头摄像机
	PushIntroCamera();

	G_MyRole->SetExternState(new CharacterState);

	return true;
}
MiniPlayer* MiniGameFish::CreatePlayer()
{
	return new FishCharacter;
}

MiniPlayer* MiniGameFish::CreateRobot()
{
	return new FishRobot;
}

MiniPlayer* MiniGameFish::CreateRole()
{
	m_myRolePlayer = new FishRole;
	return m_myRolePlayer;
}
bool MiniGameFish::Stop()
{

	G_MyRole->SetExternState(NULL);
	G_MyRole->GetRenderCharacter()->SetScale(vec3(2.0f,2.0f,2.0f));

	G_GuiMgr->PopGui("MiFishEat_PlayGui");
	
	{
		if (m_myPlayer && m_myPlayer->m_liveNum>0)
		{
			G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(true);
		}
		else
		{
			G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(false);
		}
		G_GuiMgr->PushGui("Rpg_ResultDialog",GL_DIALOGBOTTOM);
	}
	MiniGame::Stop();
	return true;
}

bool MiniGameFish::Render()
{
	PROFILEFUN("MiniGameFish::Render();",0.0f,ALWAYSHIDE);
	G_RendDriver->SetFogParms(Color(0.2f,0.9f,0.3f,1),50,500);

	if (G_ShaderMgr&& G_ShaderMgr->m_curEffect)
	{
		G_ShaderMgr->MapChangeParm();
	}

	G_RendDriver->EnableRendState(RS_LIGHTING);
	G_RendDriver->PushMatrix();
	G_RendDriver->Translatef(m_startPos.x,m_startPos.y - 70,m_startPos.z);
	G_FishScene.Render();
	G_RendDriver->PopMatrix();


	for (int i = 0; i < MaxFlocks; i++) 
	{
		m_fishFlocks[i]->Render();
	}
	
	for (int i=0;i<AIFISHNUM;i++) 
	{
		m_fishEntitys[i]->Render();
	}

	for (int i=0;i<m_allPlayerNum;i++)
	{
		FishCharacter* fish = dynamic_cast<FishCharacter*>(m_miniPlayer[i]);
		fish->Render();
		if(fish->m_driver)
			fish->m_driver->Render();
	}

	if (m_movieScene)
	{
		m_movieScene->RendClip();
	}
	return true;
}

void MiniGameFish::RenderUI()
{
	MiniGame::RenderUI();
	/
	
	G_RendDriver->BeginUI();
	G_FontMgr->GetFontDesc().backStyle = FB_RECT;
	G_FontMgr->GetFontDesc().backColor = Color(0.2f,0.3f,1.0f,0.6f);
	char buf[256];
	//得分:%d 
	sprintf(buf,TextData::GetText("T_PVB_TIP_04" ),m_myPlayer->m_score);
	G_FontMgr->TextAtPos(vec2(200, 200),buf);

	//剩余生命:%d
	sprintf(buf,TextData::GetText("T_RACING_TIP_03" ),m_myPlayer->m_liveNum);
	G_FontMgr->TextAtPos(vec2(200, 230),buf);
	G_FontMgr->GetFontDesc().backStyle = FB_NULL;

}

bool MiniGameFish::Update()
{
	PROFILEFUN("MiniGameFish::Update();",0.0f,ALWAYSHIDE);
	MiniGame::Update();

	for (int i = 0; i < MaxFlocks; i++) 
	{
		m_fishFlocks[i]->Update();
	}

	for (int i=0;i<AIFISHNUM;i++)
	{
		m_fishEntitys[i]->Update();
	}

	for (int i=0;i<m_allPlayerNum;i++)
	{
		FishCharacter* fish = dynamic_cast<FishCharacter*>(m_miniPlayer[i]);
		fish->Update();
	}
	return true;
}

bool MiniGameFish::Free()
{
	MiniGame::Free();
	for (int i = 0; i < MaxFlocks; i++) 
	{
		delete m_fishFlocks[i];
	}

	for (int i=0;i<AIFISHNUM;i++)
	{
		SafeDelete(m_fishEntitys[i]);
	}
	return true;
}

bool MiniGameFish::KeepResource(bool once,int& circle,String& nextTip)
{
	static bool LoadedStyles = false;
	if (LoadedStyles==false)
	{
		/*  fish20001~
			*/
		LoadedStyles = true;
		G_StyleMgr->LoadStyles<FishStyle>("data/Logic/Style/Fish.style",Enum_Style(FishStyle));
	}

	//keep fish
	{
		PROFILEFUN("MiniGameFish::KeepResource(bool once,int& circle,String& nextTip);",0.0f,ALWAYSHIDE);
		StyleGroupRef styles(Enum_Style(FishStyle));
		FishStyle* it = (FishStyle*)styles.GetFirst();
		while (it)
		{
			//Log::LogStr((*it).modelName);
			G_MovieClipMgr->KeepMovie((*it).modelName);
			G_RpgMap->KeepBoneStyle((*it).boneStyle);
			it = (FishStyle*)styles.GetNext();
		}
	}
	return true;
}

int  MiniGameFish::ProcessPacketCmd(PacketBase* packet)
{
	int cmd;
	packet->ReadValue(cmd);
	switch(cmd)
	{
	case CMD_PlayerMove:
		{
			int  slot = 0;
			vec3 pos;
			vec3 speed;
			packet->ReadValue(slot);
			packet->ReadValue(pos);
			packet->ReadValue(speed);
			FishCharacter* thePlayer = (FishCharacter*)GetPlayerFromSlot(slot);
			thePlayer->SetPos(pos);
			thePlayer->SetSpeed(speed);
		}
		break;	
	case CMD_FishMove:
		{
			int  slot = 0;
			vec3 pos;
			vec3 speed;
			packet->ReadValue(slot);
			packet->ReadValue(pos);
			packet->ReadValue(speed);
			FishCharacter* thePlayer = (FishCharacter*)GetPlayerFromSlot(slot);
			thePlayer->SetPos(pos);
			thePlayer->SetSpeed(speed);
		}
		break;
	case CMD_EatFish:
		{
			int  slot = 0;
			int  bEaten;
			int  fishID;
			packet->ReadValue(slot);
			packet->ReadValue(bEaten);
			packet->ReadValue(fishID);
			FishCharacter* thePlayer = (FishCharacter*)GetPlayerFromSlot(slot);
			if (bEaten)
			{
				//			thePlayer->SetSpeed(speed);
			}
			else
			{
				//thePlayer->SetSpeed(speed);
			}
		}
		break;
	case CMD_GameOver:
		break;
	case CMD_Restart:
		break;
	}
	return 0;
}

FishScene::FishScene()
:m_marchingCubeSys(NULL)
{
}
FishScene::~FishScene()
{
	Free();
}
void FishScene::Free()
{
	SafeDelete(m_marchingCubeSys);
}
void FishScene::GenRacingRoad2()
{
	Free();
	G_TextureMgr->AddTexture(m_texture,"data/environment/terrain/w_rock0.png");


#define  CubeWALL  RandRange(0.6f,1.0f) //1
#define  CubeEmpty RandRange(0.1f,0.4f) //0

	//地形
	TerrainData terrain;
	terrain.New(257,257,10,10);
	terrain.FillFractSurface(0,0,500,0.5f,false,0);

	//生成迷宫 宽墙窄路
	Maze maze;

	//maze.GeneratePrimTrunkMaze(11,11);
	//maze.AdjustSpace(3,3,1,1);
	//maze.RandEnterExit();
	//maze.OutputMaze();

	maze.GeneratePrimNatureMaze(20,20);
	maze.AdjustSpace(3,3,1,1);
	maze.MakeBigRoad();
	maze.RandEnterExit();
	maze.OutputMaze();

	//拓宽假路 假路可以撑开墙壁 假路上可以摆放建筑
	//todo 。。。

	//将地形上抬 截断顶部  靠底部挖洞  即形成倒置溶洞的室内场景

	//MarchingCubeSys 地形
	m_marchingCubeSys = new MarchingCubeSys;
	//vec3I voxelSize(64,64,64);
	vec3I voxelSize(32,32,32);
	float extendScale = 10;//5; 改变extendScale的同时marchingCube整个上下范围变了, 注意 terrain的高度也要跟着调整 否则室内室外风格就变了 
	m_marchingCubeSys->Init(voxelSize,vec3(voxelSize.x*extendScale*2,voxelSize.y*extendScale,voxelSize.z*extendScale*2));
	m_marchingCubeSys->SetGroundPos(vec3(0,m_marchingCubeSys->m_halfGroundExtend.y/3,0));   // 1/6 在地下
	m_marchingCubeSys->ClearEnergys();
	int maxX = m_marchingCubeSys->EnergyGridSize.x;//-1;
	int maxY = m_marchingCubeSys->EnergyGridSize.y;//-1;
	int maxZ = m_marchingCubeSys->EnergyGridSize.z;//-1;
	//遍历 
	float* energy  = m_marchingCubeSys->m_gridEnergys;
	float* energyZ = m_marchingCubeSys->m_gridEnergys;
	vec3 pos;
	const float extendX = m_marchingCubeSys->VoxelGridExtend.x;
	const float extendY = m_marchingCubeSys->VoxelGridExtend.y;
	const float extendZ = m_marchingCubeSys->VoxelGridExtend.z;
	pos.z = 0;//m_marchingCubeSys->m_groundMin.z;
	const float ScaleL2T = terrain.m_iWidth/(m_marchingCubeSys->m_halfGroundExtend.x*2.0f);//marching局部坐标变为terrain坐标
	for( int z = 0; z < maxZ; z++, energyZ += m_marchingCubeSys->EnergyGridSizeXY)
	{
		pos.z += extendZ;
		pos.x = 0;//m_marchingCubeSys->m_groundMin.x;
		energy = energyZ;
		for(int x = 0; x < maxX; x++ )
		{
			pos.x += extendX;
			//pos.y = 0;//m_marchingCubeSys->m_groundMin.y;
			float height = terrain.GetHeightf(pos.x*ScaleL2T,pos.z*ScaleL2T);
			int   heightI = (height-m_marchingCubeSys->m_groundMin.y)/extendY;

			energy = energyZ + x;
			int y = 0;
			for( ; y < heightI && y < maxY; y++)
			{
				//pos.y += extendY;
				*energy = CubeEmpty;  //地上为实 地下为空
				energy += m_marchingCubeSys->EnergyGridSize.x;
			}
			for( ; y < maxY; y++)
			{
				//pos.y += extendY;
				*energy = CubeWALL;  
				energy += m_marchingCubeSys->EnergyGridSize.x;
			}
		}
	}

	//室内场景 一般要筑一到两面墙+天花板
	{
		energyZ = m_marchingCubeSys->m_gridEnergys;
		{
			int z = 0;
			//int z = m_marchingCubeSys->EnergyGridSize.z-1;
			energy = energyZ +z*m_marchingCubeSys->EnergyGridSizeXY;
			for(int x = 0; x < maxX; x++ )
			{
				energy = energyZ + x;
				for( int y = 0; y < maxY; y++)
				{
					*energy = CubeWALL;
					energy += m_marchingCubeSys->EnergyGridSize.x;
				}
			}
		}

		energyZ = m_marchingCubeSys->m_gridEnergys;
		for( int z = 0; z < maxZ; z++, energyZ += m_marchingCubeSys->EnergyGridSizeXY)
		{
			energy = energyZ;
			int x = 0;
			{
				energy = energyZ + x;
				for( int y = 0; y < maxY; y++)
				{
					*energy = CubeWALL;
					energy += m_marchingCubeSys->EnergyGridSize.x;
				}
			}
		}


		//筑天花板
		energyZ = m_marchingCubeSys->m_gridEnergys;
		for( int z = 0; z < maxZ; z++, energyZ += m_marchingCubeSys->EnergyGridSizeXY)
		{
			energy = energyZ;
			for(int x = 0; x < maxX; x++ )
			{
				energy = energyZ + x;
				int y = maxY-1;
				{
					energy += m_marchingCubeSys->EnergyGridSize.x*y;
					*energy = CubeWALL;
				}
			}
		}
	}

	//地道
	int by = m_marchingCubeSys->EnergyGridSize.y/2; 
	const int Radius = Max(m_marchingCubeSys->EnergyGridSize.x/maze.m_mazeWidth,1);
	const float ScaleM2M = ((float)m_marchingCubeSys->EnergyGridSize.x)/maze.m_mazeWidth;//maze坐标变为marching坐标
	for (int y = 0; y < maze.m_mazeHeight; y++)
	{
		for (int x = 0; x < maze.m_mazeWidth; x++)
		{
			if (maze.mazeBlockType(x,y)==Maze::Road)
			{
				int bx = x*ScaleM2M;
				//int by = 32;  // 64/6
				int bz = y*ScaleM2M;
				//m_marchingCubeSys->m_gridEnergys[(bx) +(by)*(m_marchingCubeSys->EnergyGridSize.x) +(bz)*m_marchingCubeSys->EnergyGridSizeXY] = CubeWALL;
				for(int i=-Radius;i<Radius;i++)
				{
					int cz = bz+i;
					if (cz>=0 && cz<m_marchingCubeSys->EnergyGridSize.z)
					{
						for(int j=-Radius;j<Radius;j++)
						{
							int cy = by+j;
							if (cy>=0 && cy<m_marchingCubeSys->EnergyGridSize.y)
							{
								for(int k=-Radius;k<Radius;k++)
								{			
									int cx = bx+k;
									if (cx>=0 && cx<m_marchingCubeSys->EnergyGridSize.x)
									{
										m_marchingCubeSys->m_gridEnergys[(cx) +(cy)*(m_marchingCubeSys->EnergyGridSize.x) +(cz)*m_marchingCubeSys->EnergyGridSizeXY] = CubeWALL;
									}
								}
							}
						}
					}
				}
			}
		}
	}

	m_marchingCubeSys->Update();
}

void FishScene::GenRacingRoad3()
{
	Free();
	G_TextureMgr->AddTexture(m_texture,"data/environment/terrain/w_rock0.png");

	//地形
	TerrainData terrain;
	terrain.New(257,257,10,10);
	terrain.FillFractSurface(0,0,500,0.5f,false,0);

	//生成迷宫 宽墙窄路
	Maze maze;

	//maze.GeneratePrimTrunkMaze(11,11);
	//maze.AdjustSpace(3,3,1,1);
	//maze.RandEnterExit();
	//maze.OutputMaze();

	maze.GeneratePrimNatureMaze(20,20);
	maze.AdjustSpace(3,3,1,1);
	maze.MakeBigRoad();
	maze.RandEnterExit();
	maze.OutputMaze();

	//拓宽假路 假路可以撑开墙壁 假路上可以摆放建筑
	//todo 。。。

	//将地形下移 截断底部  靠中部挖洞  即形成穿山隧道的室外场景

	//MarchingCubeSys 地形
	m_marchingCubeSys = new MarchingCubeSys;
	//vec3I voxelSize(64,64,64);
	vec3I voxelSize(32,32,32);
	float extendScale = 10;//5; 改变extendScale的同时marchingCube整个上下范围变了, 注意 terrain的高度也要跟着调整 否则室内室外风格就变了 
	m_marchingCubeSys->Init(voxelSize,vec3(voxelSize.x*extendScale*2,voxelSize.y*extendScale,voxelSize.z*extendScale*2));
	m_marchingCubeSys->SetGroundPos(vec3(0,m_marchingCubeSys->m_halfGroundExtend.y/3,0));   // 1/6 在地下
	m_marchingCubeSys->ClearEnergys();
	int maxX = m_marchingCubeSys->EnergyGridSize.x;//-1;
	int maxY = m_marchingCubeSys->EnergyGridSize.y;//-1;
	int maxZ = m_marchingCubeSys->EnergyGridSize.z;//-1;
	//遍历 
	float* energy  = m_marchingCubeSys->m_gridEnergys;
	float* energyZ = m_marchingCubeSys->m_gridEnergys;
	vec3 pos;
	const float extendX = m_marchingCubeSys->VoxelGridExtend.x;
	const float extendY = m_marchingCubeSys->VoxelGridExtend.y;
	const float extendZ = m_marchingCubeSys->VoxelGridExtend.z;
	pos.z = 0;//m_marchingCubeSys->m_groundMin.z;
	const float ScaleL2T = terrain.m_iWidth/(m_marchingCubeSys->m_halfGroundExtend.x*2.0f);//marching局部坐标变为terrain坐标
	for( int z = 0; z < maxZ; z++, energyZ += m_marchingCubeSys->EnergyGridSizeXY)
	{
		pos.z += extendZ;
		pos.x = 0;//m_marchingCubeSys->m_groundMin.x;
		energy = energyZ;
		for(int x = 0; x < maxX; x++ )
		{
			pos.x += extendX;
			//pos.y = 0;//m_marchingCubeSys->m_groundMin.y;
			float height = terrain.GetHeightf(pos.x*ScaleL2T,pos.z*ScaleL2T);
			height -= 200;//地形下移
			int   heightI = (height-m_marchingCubeSys->m_groundMin.y)/extendY;

			energy = energyZ + x;
			int y = 0;
			for( ; y < heightI && y < maxY; y++)
			{
				//pos.y += extendY;
				*energy = CubeWALL;  //地下为实 地上为空
				energy += m_marchingCubeSys->EnergyGridSize.x;
			}
			for( ; y < maxY; y++)
			{
				//pos.y += extendY;
				*energy = CubeEmpty;
				energy += m_marchingCubeSys->EnergyGridSize.x;
			}
		}
	}

	{
		//筑天花板 山顶非空
		energyZ = m_marchingCubeSys->m_gridEnergys;
		for( int z = 0; z < maxZ; z++, energyZ += m_marchingCubeSys->EnergyGridSizeXY)
		{
			energy = energyZ;
			for(int x = 0; x < maxX; x++ )
			{
				energy = energyZ + x;
				int y = maxY-1;
				{
					energy += m_marchingCubeSys->EnergyGridSize.x*y;
					*energy = CubeEmpty;
				}
			}
		}
	}

	//挖隧道
	int by = m_marchingCubeSys->EnergyGridSize.y/3; 
	int Radius = Max(m_marchingCubeSys->EnergyGridSize.x/maze.m_mazeWidth,1);
	int RadiusY;
	const float ScaleM2M = ((float)m_marchingCubeSys->EnergyGridSize.x)/maze.m_mazeWidth;//maze坐标变为marching坐标
	for (int y = 0; y < maze.m_mazeHeight; y++)
	{
		for (int x = 0; x < maze.m_mazeWidth; x++)
		{
			if (maze.mazeBlockType(x,y)==Maze::Road)
			{
				//靠近路中间挖的高度更大
				RadiusY = Radius + maze.GetSurroundingBlocks(x, y, 2,Maze::Road)*0.2f;

				int bx = x*ScaleM2M;
				//int by = 32;  // 64/6
				int bz = y*ScaleM2M;
				//m_marchingCubeSys->m_gridEnergys[(bx) +(by)*(m_marchingCubeSys->EnergyGridSize.x) +(bz)*m_marchingCubeSys->EnergyGridSizeXY] = 0;
				for(int i=-Radius;i<Radius;i++)
				{
					int cz = bz+i;
					if (cz>=0 && cz<m_marchingCubeSys->EnergyGridSize.z)
					{
						//上半圆挖隧道
						for(int j=-RadiusY;j<0;j++)
						{
							int cy = by+j;
							if (cy>=0 && cy<m_marchingCubeSys->EnergyGridSize.y)
							{
								for(int k=-Radius;k<Radius;k++)
								{			
									int cx = bx+k;
									if (cx>=0 && cx<m_marchingCubeSys->EnergyGridSize.x)
									{
										m_marchingCubeSys->m_gridEnergys[(cx) +(cy)*(m_marchingCubeSys->EnergyGridSize.x) +(cz)*m_marchingCubeSys->EnergyGridSizeXY] = CubeWALL;
									}
								}
							}
						}

						//下半圆筑路
						for(int j=0;j<RadiusY;j++)
						{
							int cy = by+j;
							if (cy>=0 && cy<m_marchingCubeSys->EnergyGridSize.y)
							{
								for(int k=-Radius;k<Radius;k++)
								{			
									int cx = bx+k;
									if (cx>=0 && cx<m_marchingCubeSys->EnergyGridSize.x)
									{
										m_marchingCubeSys->m_gridEnergys[(cx) +(cy)*(m_marchingCubeSys->EnergyGridSize.x) +(cz)*m_marchingCubeSys->EnergyGridSizeXY] = CubeEmpty;
									}
								}
							}
						}
					}
				}
			}
		}
	}

	m_marchingCubeSys->RemoveChip();
	m_marchingCubeSys->Update();
}

void FishScene::Render()
{
	if (m_marchingCubeSys)
	{
		m_texture->Bind();
		m_marchingCubeSys->Render();
	}
}

void FishScene::SaveToCollide(RendSys::Mesh* mesh)
{
	if (mesh==NULL)
		return;

	mesh->Free();

	int vVertexNum = m_marchingCubeSys->m_vertexNum;
	int tVertexNum = m_marchingCubeSys->m_vertexNum;
	int trigonNum  = m_marchingCubeSys->m_indexNum/3;
	mesh->Resize(vVertexNum, tVertexNum, trigonNum);


	Mesh::Vertex*  v = mesh->m_vVertexs;
	Mesh::TVertex* t = mesh->m_tVertexs;
	Mesh::Trigon*  tri = mesh->m_trigons;

	{
		MarchingCubeSys::SVertex* vb = m_marchingCubeSys->m_vertexs;
		for (int j=0;j<vVertexNum;++j)
		{
			v->x  = vb->pos[0] ;
			v->y  = vb->pos[1] ;
			v->z  = vb->pos[2] ;
			v->nx = vb->normal[0] ;
			v->ny = vb->normal[1] ;
			v->nz = vb->normal[2] ;

			t->u  = vb->uvw[0] ;
			t->v  = vb->uvw[1] ;
			t->w  = vb->uvw[2] ;

			v++;
			vb++;
			t++;
		}

		MarchingCubeSys::IndexInt* trib = m_marchingCubeSys->m_indexs;
		for (int j=0;j<trigonNum;++j)
		{
			tri->vIndex[0]  = trib[0] ;
			tri->vIndex[1]  = trib[1] ;
			tri->vIndex[2]  = trib[2] ;

			tri+=1;
			trib+=3;
		}

	}
	//mesh->CreateBuff();//test
	mesh->BuildTree();
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值