搞了一个这么个插件 Mesh tounity3d terrainn 怎么用

Axiom3D写游戏:第一个窗口 - 天天不在 - 推酷
Axiom3D写游戏:第一个窗口 - 天天不在
Axiom主要的代码大致翻看了下,就想到了自己来模拟一下游戏开发.
这章主要包括创建窗口及3D渲染的一些基本元素,并添加一个第三人称的骨骼动画作主角,加上前文中修改过后的地形组件,能用鼠标和键盘进行漫游.如下图所示.
在Axiom上给出的例子中,可以选择是用OpenGL或是DirectX渲染,现在有问题的地方是如果用OpenGL渲染,而Axiom鼠标与键盘输入采用的是SharpInputSystem,这个在DirectX渲染下是没有问题的,但是在OpenGL渲染的窗口下得不到正确的鼠标位置.而DixectX渲染下,运行一会后,骨骼动画在进行骨骼变化时,调用SoftwareVertexBlend会引起程序挂起,这个问题没找到解决方法,以后在来调.
在上面的情况下,在加上前面我主要学的是OpenGL,我决定在我接下来采用OpenGL渲染以及OpenTK里提供的鼠标与键盘输入接口.
接下来,通过Axiom里提供的例子,结合Samples.Brower.Win32与mon来看Axiom的渲染流程,结合上面的流程自己写了一半,才发现有现存的,在Axiom.Framework里的Game抽象类里,提供对应流程,因为原始采用SharpInputSystem来处理键盘与鼠标反馈,经过修改,下面是代码.
public abstract class Game : IDisposable, IWindowEventListener
protected Root E
protected IConfigurationManager ConfigurationM
protected ResourceGroupManager C
protected SceneManager SceneM
protected Camera C
protected Viewport V
protected RenderWindow W
protected Axiom.Graphics.RenderSystem RenderS
public virtual void Run()
PreInitialize();
LoadConfiguration();
Initialize();
CreateRenderSystem();
CreateRenderWindow();
LoadResource();
CreateSceneManager();
CreateCamera();
CreateViewports();
CreateInput();
CreateScene();
this.Engine.StartRendering();
private void PreInitialize()
this.ConfigurationManager = new DefaultConfigurationManager();
// instantiate the Root singleton
this.Engine = new Root(this.ConfigurationManager.LogFilename);
// add event handlers for frame events
this.Engine.FrameStarted += Engine_FrameRenderingQ
public virtual void LoadConfiguration()
this.ConfigurationManager.RestoreConfiguration(this.Engine);
private void Engine_FrameRenderingQueued(object source, FrameEventArgs e)
Update(e.TimeSinceLastFrame);
public virtual void Initialize()
public virtual void CreateRenderSystem()
if (this.Engine.RenderSystem == null)
this.RenderSystem = this.Engine.RenderSystem = this.Engine.RenderSystems.First().V
this.RenderSystem = this.Engine.RenderS
public virtual void CreateRenderWindow()
this.Window = Root.Instance.Initialize(true, &Xin Game&);
WindowEventMonitor.Instance.RegisterListener(this.Window, this);
public virtual void LoadResource()
ResourceGroupManager.Instance.InitializeAllResourceGroups();
public virtual void CreateSceneManager()
// Get the SceneManager, a generic one by default
this.SceneManager = this.Engine.CreateSceneManager(&DefaultSceneManager&, &GameSMInstance&);
this.SceneManager.ClearScene();
public virtual void CreateCamera()
// create a camera and initialize its position
this.Camera = this.SceneManager.CreateCamera(&MainCamera&);
this.Camera.Position = new Vector3(0, 0, 0);
this.Camera.LookAt(new Vector3(0, 0, -300));
public virtual void CreateViewports()
// create a new viewport and set it's background color
this.Viewport = this.Window.AddViewport(this.Camera, 0, 0, 1.0f, 1.0f, 100);
this.Viewport.BackgroundColor = ColorEx.SteelB
public virtual void CreateInput()
//var window = this.Window[&nativewindow&];
public abstract void CreateScene();
public virtual void Update(float timeSinceLastFrame)
#region IDisposable Implementation
#region IsDisposed Property
/// &summary&
/// Determines if this instance has been disposed of already.
/// &/summary&
public bool IsDisposed { get; set; }
#endregion IsDisposed Property
/// &summary&
/// Class level dispose method
/// &/summary&
/// &remarks&
/// When implementing this method in an inherited class the following tem
/// protected override void dispose( bool disposeManagedResources )
if ( !IsDisposed )
if ( disposeManagedResources )
// Dispose managed resources.
// If there are unmanaged resources to release,
// they need to be released here.
// If it is available, make the call to the
// base class's Dispose(Boolean) method
base.dispose( disposeManagedResources );
/// &/remarks&
/// &param name=&disposeManagedResources&&True if Unmanaged resources should be released.&/param&
protected virtual void dispose(bool disposeManagedResources)
if (!IsDisposed)
if (disposeManagedResources)
if (this.Engine != null)
// remove event handlers
this.Engine.FrameStarted -= Engine_FrameRenderingQ
if (this.SceneManager != null)
this.SceneManager.RemoveAllCameras();
this.Camera = null;
if (Root.Instance != null)
Root.Instance.RenderSystem.DetachRenderTarget(this.Window);
if (this.Window != null)
WindowEventMonitor.Instance.UnregisterWindow(this.Window);
this.Window.Dispose();
if (this.Engine != null)
this.Engine.Dispose();
// There are no unmanaged resources to release, but
// if we add them, they need to be released here.
IsDisposed = true;
/// &summary&
/// Call to when class is no longer needed
/// &/summary&
public void Dispose()
dispose(true);
GC.SuppressFinalize(this);
dispose(false);
#endregion IDisposable Implementation
#region IWindowEventListener Implementation
/// &summary&
/// Window has moved position
/// &/summary&
/// &param name=&rw&&The RenderWindow which created this event&/param&
public void WindowMoved(RenderWindow rw)
/// &summary&
/// Window has resized
/// &/summary&
/// &param name=&rw&&The RenderWindow which created this event&/param&
public void WindowResized(RenderWindow rw)
/// &summary&
/// Window has closed
/// &/summary&
/// &param name=&rw&&The RenderWindow which created this event&/param&
public void WindowClosed(RenderWindow rw)
// Only do this for the Main Window
if (rw == this.Window)
Root.Instance.QueueEndRendering();
/// &summary&
/// Window lost/regained the focus
/// &/summary&
/// &param name=&rw&&The RenderWindow which created this event&/param&
public void WindowFocusChange(RenderWindow rw)
#endregion
在原来的基础上去掉相关SharpInputSystem的代码,相关初始化过程都在Run这个方法内,主要过程生成Root对象,此过程会预先调用大部分Manager类,以达到相关静态构造函数能按顺序进行,不然可能会引发一些问题,插件的加载也在这个方法内。在加载插件时,会查找是否包含OpenGL与DirectX渲染插件,在这里我们只选择添加了RenderSystems.OpenGL的插件,那么在接下创建RenderSystem时,选择这个渲染插件作为Root对象的渲染系统。根据对应的RenderSystem我们创建对应的窗口,跟踪相关代码,我们知道我们创建的是RenderWindow的子类OpenTKWindow.在创建窗口之后。我们会选择加载资源进来。然后是创建场景管理SceneManager,场景管理具体可以查看
,Ogre本身给我们提供了二个场景管理插件,分别是BSP与Octree,这二个方案主要区别是针对物体怎么确定是否需要渲染的逻辑有所不同,最新Axiom因为直接用的是Ogre1.7之后的地形插件,所以不需要固定使用Octree的场景管理方案。在已经创建管理基础上,我们创建摄像机,已经对应窗口的Viewport对象。方法Update就是Root对象的消息循环,我们每桢的逻辑都可以放入这个方法内,当我们调用Root的StartRendering方法后,正常情况下就不断更新Update方法。
在原来的Game里我们放弃了原来的SharpInputSystem,我们需要一个能正常接收对应OpenTKWindow里键盘与鼠标的输入,并且还有前面所说的一个骨骼动画加上地形组件所产生的地形,以及一些基本的UI组件显示。
public class OpenTKGame : Game
public OpenTKGame()
#region property
public KeyboardState KeyboardState
return Keyboard.GetState();
public MouseState MouseState
return Mouse.GetState();
#endregion
protected SinbadCharacterC
protected CameraManager cameraM
protected UIManager uiM
protected TerrainManager terrainM
private bool bLoadTerrain = true;
private bool bDown = false;
public override void CreateRenderWindow()
base.CreateRenderWindow();
public override void LoadResource()
//ResourceGroupManager.Instance.InitializeResourceGroup(&Popular&);
ResourceGroupManager.Instance.InitializeResourceGroup(&Essential&);
uiManager = new UIManager(this.Window);
public override void CreateCamera()
//uiManager.ShowBackdrop(&SdkTrays/Bands&);
base.CreateCamera();
this.cameraManager = new CameraManager(this.Camera);
this.terrainManager = new TerrainManager(this.SceneManager);
public override void CreateInput()
base.CreateInput();
var window = this.Window[&nativewindow&] as OpenTK.NativeW
if (window == null)
throw new NotImplementedException();
var mouse = window.InputDriver.Mouse[0];
var keyboard = window.InputDriver.Keyboard[0];
mouse.ButtonDown += mouse_ButtonD
mouse.ButtonUp += mouse_ButtonUp;
mouse.Move += mouse_M
keyboard.KeyDown += keyboard_KeyD
keyboard.KeyUp += keyboard_KeyUp;
public override void CreateScene()
// set background and some fog
Viewport.BackgroundColor = new ColorEx(1.0f, 1.0f, 0.8f);
SceneManager.SetFog(FogMode.Linear, new ColorEx(1.0f, 1.0f, 1.0f), 0, 15, 100);
// set shadow properties
//SceneManager.ShadowTechnique = ShadowTechnique.TextureM
SceneManager.ShadowColor = new ColorEx(0.5f, 0.5f, 0.5f);
SceneManager.ShadowTextureSize = 1024;
SceneManager.ShadowTextureCount = 1;
// disable default camera control so the character can do its own
cameraManager.setStyle(CameraStyle.Manual);
// use a small amount of ambient lighting
SceneManager.AmbientLight = new ColorEx(0.3f, 0.3f, 0.3f);
// add a bright light above the scene
Light light = SceneManager.CreateLight(&CharacterLight&);
light.Type = LightType.P
light.Position = new Vector3(-10, 40, 20);
light.Specular = ColorEx.W
this.uiManager.ShowBackdrop(&SdkTrays/Bands&);
this.uiManager.ShowLoadingBar(6, 1, 0.7f);
ResourceGroupManager.Instance.InitializeResourceGroup(&Popular&);
if (this.bLoadTerrain)
terrainManager.SetupContent();
this.uiManager.HideLoadingBar();
this.uiManager.HideBackdrop();
ShowCursor(0);
uiManager.ShowCursor();
MeshManager.Instance.CreatePlane(&floor&, ResourceGroupManager.DefaultResourceGroupName,
new Plane(Vector3.UnitY, 0), 100, 100, 10, 10, true, 1, 10, 10, Vector3.UnitZ);
// create a floor entity, give it a material, and place it at the origin
Entity floor = SceneManager.CreateEntity(&Floor&, &floor&);
floor.MaterialName = &Examples/Rockwall&;
floor.CastShadows = false;
SceneManager.RootSceneNode.AttachObject(floor);
// create our character controller
this.chara = new SinbadCharacterController(Camera);
this.chara.bodyNode.Position = new Vector3(1900, 5, 2000);
public override void Update(float timeSinceLastFrame)
base.Update(timeSinceLastFrame);
this.cameraManager.frameRenderingQueued(timeSinceLastFrame);
this.chara.AddTime(timeSinceLastFrame);
if (bLoadTerrain)
var position = this.chara.bodyNode.P
terrainManager.GetTerrainReyHighter(ref position, timeSinceLastFrame);
this.chara.bodyNode.Position =
[DllImport(&user32.dll&, EntryPoint = &ShowCursor&, CharSet = CharSet.Auto)]
public extern static void ShowCursor(int status);
#region event
void keyboard_KeyUp(object sender, KeyboardKeyEventArgs e)
this.cameraManager.injectKeyUp(e);
this.chara.InjectKeyUp(e);
void keyboard_KeyDown(object sender, KeyboardKeyEventArgs e)
switch (e.Key)
case Key.R:
switch (this.Camera.PolygonMode)
case PolygonMode.Points:
this.Viewport.Camera.PolygonMode = PolygonMode.S
case PolygonMode.Solid:
this.Viewport.Camera.PolygonMode = PolygonMode.W
case PolygonMode.Wireframe:
this.Viewport.Camera.PolygonMode = PolygonMode.P
this.cameraManager.injectKeyDown(e);
this.chara.InjectKeyDown(e);
void mouse_Move(object sender, MouseMoveEventArgs e)
this.cameraManager.injectMouseMove(e);
if (bDown)
this.chara.InjectMouseMove(e);
uiManager.RefreshCursor(e.X, e.Y);
void mouse_ButtonUp(object sender, MouseButtonEventArgs e)
this.cameraManager.injectMouseUp(e);
bDown = false;
void mouse_ButtonDown(object sender, MouseButtonEventArgs e)
this.cameraManager.injectMouseDown(e);
this.chara.InjectMouseDown(e);
bDown = true;
#endregion
OpenTKGame
OpenTKGame继续Game,有一些方法做了相关改动,在LoadResource里,并没有全部加载所有资源,只是加载了UI所需要的资源。在CreateInput里,我们获取OpenTKWindow里的nativewindow,以此对象来检测鼠标与键盘的输入。然后在CreateScene就是我们相关元素的初始化的一些过程,场景管理的一些基本定义,一个点光源,界面上的一些UI元素,这里有二个位置,一个是加载游戏资源对应的进度条,一个是光标。然后是地形加载,最后就是主角,骨骼动画的加载。
关于地形,我在上文
大致分析了下,原Axiom里的地形组件有些问题还没修正,需要自己修改相关位置的BUG才能得到正确的地形,这里就不仔细说了,需要注意的一点就是,我们的角色要正确的与地面交互.下面是主要源代码。
public class TerrainManager
private const string TerrainFilePrefix = &TestTerrain&;
private const string TerrainFileSuffix = &dat&;
private const float TerrainWorldSize = 5120;
private const int TerrainSize = 513;
private const int TerrainPageMinX = 0;
private const int TerrainPageMinY = 0;
private const int TerrainPageMaxX = 0;
private const int TerrainPageMaxY = 0;
protected bool terrainsImported = false;
protected Real fallV
protected Real heightUpdateCountD
protected Real heightUpdateR
protected Vector3 terrainPos = new Vector3(0, 0, 0);
protected Real brushSizeTerrainSpace = 0.02f;
protected TerrainGlobalOptions terrainG
protected TerrainGroup terrainG
protected List&Entity& houseList = new List&Entity&();
private SceneManager SceneM
public TerrainManager(SceneManager sceneManager)
this.heightUpdateRate = 1.0f / 2.0f;
this.SceneManager = sceneM
private ImportData _configureTerrainDefaults(Light l)
// Configure global
TerrainGlobalOptions.MaxPixelError = 8;
// testing composite map
positeMapDistance = 3000;
TerrainGlobalOptions.LightMapDirection = l.DerivedD
//positeMapAmbient = SceneManager.AmbientL
positeMapDiffuse = l.D
// Configure default import settings for if we use imported image
var defaultImp = this.terrainGroup.DefaultImportS
defaultImp.TerrainSize = TerrainS
defaultImp.WorldSize = TerrainWorldS
defaultImp.InputScale = 600.0f;// 600.0f;
defaultImp.MinBatchSize = 33;
defaultImp.MaxBatchSize = 65;
// textures
defaultImp.LayerList = new List&LayerInstance&();
var inst = new LayerInstance();
inst.WorldSize = 30;// 100;
inst.TextureNames = new List&string&();
inst.TextureNames.Add(&dirt_grayrocky_diffusespecular.dds&);
inst.TextureNames.Add(&dirt_grayrocky_normalheight.dds&);
defaultImp.LayerList.Add(inst);
inst = new LayerInstance();
inst.WorldSize = 30;//30;
inst.TextureNames = new List&string&();
inst.TextureNames.Add(&grass_green-01_diffusespecular.dds&);
inst.TextureNames.Add(&grass_green-01_normalheight.dds&);
defaultImp.LayerList.Add(inst);
inst = new LayerInstance();
inst.WorldSize = 30;// 200;
inst.TextureNames = new List&string&();
inst.TextureNames.Add(&growth_weirdfungus-03_diffusespecular.dds&);
inst.TextureNames.Add(&growth_weirdfungus-03_normalheight.dds&);
defaultImp.LayerList.Add(inst);
return defaultI
public void SetupContent()
var blankTerrain = false;
MaterialManager.Instance.SetDefaultTextureFiltering(TextureFiltering.Anisotropic);
MaterialManager.Instance.DefaultAnisotropy = 7;
SceneManager.SetFog(FogMode.Linear, new ColorEx(0.07f, 0.07f, 0.08f), 0, 10000, 25000);
var lightDir = new Vector3(0.55f, 0.3f, 0.75f);
lightDir.Normalize();
var l = SceneManager.CreateLight(&tsLight&);
l.Type = LightType.D
l.Direction = lightD
l.Diffuse = ColorEx.W
l.Specular = new ColorEx(0.8f, 0.8f, 0.8f);
SceneManager.AmbientLight = new ColorEx(0.2f, 0.2f, 0.2f);
this.terrainGroup = new TerrainGroup(SceneManager, Alignment.Align_X_Z, (ushort)TerrainSize, TerrainWorldSize);
this.terrainGroup.SetFilenameConvention(TerrainFilePrefix, TerrainFileSuffix);
this.terrainGroup.Origin = this.terrainP
_configureTerrainDefaults(l);
for (long x = TerrainPageMinX; x &= TerrainPageMaxX; ++x)
for (long y = TerrainPageMinY; y &= TerrainPageMaxY; ++y)
_defineTerrain(x, y, blankTerrain);
// sync load since we want everything in place when we start
this.terrainGroup.LoadAllTerrains(true);
if (this.terrainsImported)
foreach (var ts in this.terrainGroup.TerrainSlots)
_initBlendMaps(ts.Instance);
this.terrainGroup.FreeTemporaryResources();
var e = SceneManager.CreateEntity(&TudoMesh&, &tudorhouse.mesh&);
var entPos = new Vector3(this.terrainPos.x + 2043, 0, this.terrainPos.z + 1715);
var rot = new Quaternion();
entPos.y = this.terrainGroup.GetHeightAtWorldPosition(entPos) + 65.5 + this.terrainPos.y;
rot = Quaternion.FromAngleAxis(Utility.RangeRandom(-180, 180), Vector3.UnitY);
var sn = SceneManager.RootSceneNode.CreateChildSceneNode(entPos, rot);
sn.Scale = new Vector3(0.12, 0.12, 0.12);
sn.AttachObject(e);
this.houseList.Add(e);
e = SceneManager.CreateEntity(&TudoMesh1&, &tudorhouse.mesh&);
entPos = new Vector3(this.terrainPos.x + 1850, 0, this.terrainPos.z + 1478);
entPos.y = this.terrainGroup.GetHeightAtWorldPosition(entPos) + 65.5 + this.terrainPos.y;
rot = Quaternion.FromAngleAxis(Utility.RangeRandom(-180, 180), Vector3.UnitY);
sn = SceneManager.RootSceneNode.CreateChildSceneNode(entPos, rot);
sn.Scale = new Vector3(0.12, 0.12, 0.12);
sn.AttachObject(e);
this.houseList.Add(e);
e = SceneManager.CreateEntity(&TudoMesh2&, &tudorhouse.mesh&);
entPos = new Vector3(this.terrainPos.x + 1970, 0, this.terrainPos.z + 2180);
entPos.y = this.terrainGroup.GetHeightAtWorldPosition(entPos) + 65.5 + this.terrainPos.y;
rot = Quaternion.FromAngleAxis(Utility.RangeRandom(-180, 180), Vector3.UnitY);
sn = SceneManager.RootSceneNode.CreateChildSceneNode(entPos, rot);
sn.Scale = new Vector3(0.12, 0.12, 0.12);
sn.AttachObject(e);
this.houseList.Add(e);
private void _defineTerrain(long x, long y, bool flat)
this.terrainGroup.DefineTerrain(x, y, 0);
var filename = this.terrainGroup.GenerateFilename(x, y);
if (ResourceGroupManager.Instance.ResourceExists(this.terrainGroup.ResourceGroup, filename))
this.terrainGroup.DefineTerrain(x, y);
var img = _getTerrainImage(x % 2 != 0, y % 2 != 0);
this.terrainGroup.DefineTerrain(x, y, img);
this.terrainsImported = true;
private Image _getTerrainImage(bool flipX, bool flipY)
var img = Image.FromFile(&terrain.png&, ResourceGroupManager.DefaultResourceGroupName);
if (flipX)
img.FlipAroundY();
if (flipY)
img.FlipAroundX();
private void _ponents.Terrain.Terrain terrain)
var blendMap0 = terrain.GetLayerBlendMap(1);
var blendMap1 = terrain.GetLayerBlendMap(2);
Real minHeight0 = 70;
Real fadeDist0 = 40;
Real minHeight1 = 70;
Real fadeDist1 = 15;
var pBlend1 = blendMap1.BlendP
var blendIdx = 0;
for (var y = 0; y & terrain.LayerBlendMapS y++)
for (var x = 0; x & terrain.LayerBlendMapS x++)
Real tx = 0;
Real ty = 0;
blendMap0.ConvertImageToTerrainSpace(x, y, ref tx, ref ty);
Real height = terrain.GetHeightAtTerrainPosition(tx, ty);
Real val = (height - minHeight0) / fadeDist0;
val = Utility.Clamp(val, 0, 1);
val = (height - minHeight1) / fadeDist1;
val = Utility.Clamp(val, 0, 1);
pBlend1[blendIdx++] =
blendMap0.Dirty();
blendMap1.Dirty();
blendMap0.Update();
blendMap1.Update();
public void GetTerrainReyHighter(ref Vector3 chaPos, float timeSinceLastFrame)
var ray = new Ray(new Vector3(chaPos.x, this.terrainPos.y + 10000, chaPos.z), Vector3.NegativeUnitY);
TerrainGroup.RayResult rayResult = this.terrainGroup.RayIntersects(ray);
Real distanceAboveTerrain = 5;
Real fallSpeed = 300;
Real newy = chaPos.y;
if (rayResult.Hit)
if (chaPos.y & rayResult.Position.y + distanceAboveTerrain)
this.fallVelocity += timeSinceLastFrame * 20;
this.fallVelocity = Utility.Min(this.fallVelocity, fallSpeed);
newy = chaPos.y - this.fallVelocity * timeSinceLastF
newy = Utility.Max(rayResult.Position.y + distanceAboveTerrain, newy);
// Camera.Position = new Vector3(chaPos.x, newy, chaPos.z);
chaPos = new Vector3(chaPos.x, newy, chaPos.z);
if (this.heightUpdateCountDown & 0)
this.heightUpdateCountDown -= timeSinceLastF
if (this.heightUpdateCountDown &= 0)
this.terrainGroup.Update();
this.heightUpdateCountDown = 0;
TerrainManager
在方法GetTerrainReyHighter里,我们在角色上面取一点与角色下面取一点组成Ray,然后计算与地形的交互点,得到正确的高度,这个具体过程有点像我原来用PyOpengl里的相关过程
。地形的LOD等级主要与二方面有关,一个是当前块与摄像机位置,一个是当前块的高度。一般来说,与摄像机与近,当前块越高,lod数值越低,精度越高。
关于角色的控制SinbadCharacterController用的就是例子程序的,只做了一点小变动,就不说了。
UI我主要用到一个进度条与光标,提取例子里这些位置组合成下面这个。
public class UIManager : IResourceGroupListener
private string mName = &xinGame&;
protected RenderWindow mW
protected ProgressBar LoadB
protected Real groupInitP // proportion of load job assigned to initialising one resource group
protected Real groupLoadP // proportion of load job assigned to loading one resource group
protected Real loadI
protected Overlay backdropL // backdrop layer
protected OverlayElementC // backdrop
protected Overlay cursorL // cursor layer
protected OverlayElementC // cursor
protected Overlay mPriorityL // top priority layer
protected OverlayElementContainer mDialogS // top priority dialog shade
public Overlay BackdropLayer
return this.backdropL
protected set
this.backdropLayer =
public OverlayElement CursorImage
return this.cursor.Children[this.cursor.Name + &/CursorImage&];
public UIManager(RenderWindow window)
this.mWindow =
OverlayManager om = OverlayManager.I
String nameBase = this.mName + &/&;
nameBase.Replace(' ', '_');
BackdropLayer = om.Create(nameBase + &BackdropLayer&);
BackdropLayer.ZOrder = 100;
this.backdrop = (OverlayElementContainer)om.Elements.CreateElement(&Panel&, nameBase + &Backdrop&);
BackdropLayer.AddElement(this.backdrop);
this.cursorLayer = om.Create(nameBase + &CursorLayer&);
this.cursorLayer.ZOrder = 400;
this.cursor = (OverlayElementContainer)om.Elements.CreateElementFromTemplate(&SdkTrays/Cursor&, &Panel&, nameBase + &Cursor&);
this.cursorLayer.AddElement(this.cursor);
this.mPriorityLayer = om.Create(nameBase + &PriorityLayer&);
this.mPriorityLayer.ZOrder = 300;
this.mDialogShade = (OverlayElementContainer)om.Elements.CreateElement(&Panel&, nameBase + &DialogShade&);
this.mDialogShade.MaterialName = &SdkTrays/Shade&;
this.mDialogShade.Hide();
this.mPriorityLayer.AddElement(this.mDialogShade);
this.mPriorityLayer.Show();
public void ShowBackdrop(String materialName)
if (materialName != String.Empty)
this.backdrop.MaterialName = materialN
BackdropLayer.Show();
public void HideBackdrop()
BackdropLayer.Hide();
public void ShowLoadingBar(int numGroupsInit, int numGroupsLoad, Real initProportion)
if (this.LoadBar != null)
HideLoadingBar();
this.LoadBar = new ProgressBar(this.mName + &/LoadingBar&, &Loading...&, 400, 308);
OverlayElement e = this.LoadBar.OverlayE
this.mDialogShade.AddChild(e);
e.VerticalAlignment = VerticalAlignment.C
e.Left = (-(e.Width / 2));
e.Top = (-(e.Height / 2));
ResourceGroupManager.Instance.AddResourceGroupListener(this);
this.mDialogShade.Show();
if (numGroupsInit == 0 && numGroupsLoad != 0)
this.groupInitProportion = 0;
this.groupLoadProportion = 1;
else if (numGroupsLoad == 0 && numGroupsInit != 0)
this.groupLoadProportion = 0;
if (numGroupsInit != 0)
this.groupInitProportion = 1;
else if (numGroupsInit == 0 && numGroupsLoad == 0)
this.groupInitProportion = 0;
this.groupLoadProportion = 0;
this.groupInitProportion = initProportion / numGroupsI
this.groupLoadProportion = (1 - initProportion) / numGroupsL
public void HideLoadingBar()
if (this.LoadBar != null)
this.LoadBar.Cleanup();
this.LoadBar = null;
ResourceGroupManager.Instance.RemoveResourceGroupListener(this);
this.mDialogShade.Hide();
public void ShowCursor()
ShowCursor(String.Empty);
public void ShowCursor(String materialName)
if (materialName != String.Empty)
CursorImage.MaterialName = materialN
if (!this.cursorLayer.IsVisible)
this.cursorLayer.Show();
RefreshCursor();
public void HideCursor()
this.cursorLayer.Hide();
public void RefreshCursor()
var mouseStatus = Mouse.GetState();
this.cursor.SetPosition(mouseStatus.X, mouseStatus.Y);
public void RefreshCursor(int x, int y)
this.cursor.SetPosition(x, y);
#region IResourceGroupListener
public void ResourceGroupScriptingStarted(string groupName, int scriptCount)
this.loadInc = this.groupInitProportion / scriptC
this.LoadBar.Caption = &Parsing...&;
this.mWindow.Update();
public void ScriptParseStarted(string scriptName, ref bool skipThisScript)
this.ment = System.IO.Path.GetFileName(scriptName);
this.mWindow.Update();
public void ScriptParseEnded(string scriptName, bool skipped)
this.LoadBar.Progress = this.LoadBar.Progress + this.loadI
this.mWindow.Update();
public void ResourceGroupScriptingEnded(string groupName)
public void ResourceGroupPrepareStarted(string groupName, int resourceCount)
public void ResourcePrepareStarted(Resource resource)
public void ResourcePrepareEnded()
public void ResourceGroupPrepareEnded(string groupName)
public void ResourceGroupLoadStarted(string groupName, int resourceCount)
this.loadInc = this.groupLoadProportion / resourceC
this.LoadBar.Caption = &Loading...&;
this.mWindow.Update();
public void ResourceLoadStarted(Resource resource)
this.ment = resource.N
this.mWindow.Update();
public void ResourceLoadEnded()
this.LoadBar.Progress = this.LoadBar.Progress + this.loadI
this.mWindow.Update();
public void WorldGeometryStageStarted(string description)
this.ment =
this.mWindow.Update();
public void WorldGeometryStageEnded()
this.LoadBar.Progress = this.LoadBar.Progress + this.loadI
this.mWindow.Update();
public void ResourceGroupLoadEnded(string groupName)
#endregion
效果和例子里的一样。
UIManager这个主要是熟悉下相应的Overlay里相关类的用法,相关label,button,checkbox等这些控件都可以由Overlay,OverlayElementContainer,OverlayElement这些元素组成,这些元素相关属性都可以从对应的overlay文本文件反序列化得到,这样我们可以直接修改相关属性产生不同的效果,不需要改动代码,后面应该会详细介绍Overlay相关元素的代码与方法。需要说明的是,这个项目是控制台应用程序,建winform项目在这没用,上下文环境不一样,相关窗口,UI是不能混用的。
CameraManager这个类在这列出来,这里没怎么用,相关的鼠标与键盘处理都在TerrainManager中,在这也不列出来了。
附件XinGame.zip.需要大家自己下载Axiom项目,相关bin目录里引用的DLL有些多,上传限制就不发了。里面因地图比较大,我移动速度调的很快,大家可以自己修改。wsad方向,鼠标按下移动调整方向。
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见

我要回帖

更多关于 terrain 的文章

 

随机推荐