2008年11月23日 星期日

XNA - 中文字(各國文字)

XNA - 中文字(各國文字)

使用方式很簡單…

// 取得 Graphics
Graphics g = Graphics.FromHwnd(this.Handle);
// 先取得一個字的大小
SizeF strSize1 = g.MeasureString("一", font);
// 接著取得兩個字的大小
SizeF strSize2 = g.MeasureString("一二", font);
// 相減得字元寬度
int charWidth = (int)(strSize1.Width - strSize2.Width);



將pupu大大的code整理一下:

public void DrawChar(SpriteBatch spriteBatch, char c, Vector2 position, Color color)
{
// 轉換成int
// 事實上還要扣除掉起始字元,目前為了方便一律從'\u0000'開始
int offset = (int)c;
// 計算出字元位在第幾張圖
int picIndex = offset / this.mGridPreTexture;
// 計算出在圖中的位移量
offset -= picIndex * this.mGridPreTexture;

// 取得字元的 rectangle
Rectangle rect = new Rectangle((offset % this.mTextureGrid.Width) * this.mFontSize.Width,
(offset / this.mTextureGrid.Height) * this.mFontSize.Height,
this.mFontSize.Width,
this.mFontSize.Height
);

// 繪製
spriteBatch.Draw(this.mFontTexture[picIndex], position, rect, color);
}



希望你也知道如何繪製紋理圖上的某個區塊。

public void DrawChar(SpriteBatch spriteBatch, char c, Vector2 position, Color color)
{
// 轉換成int
// 事實上還要扣除掉起始字元,目前為了方便一律從'\u0000'開始
int offset = (int)c;
// 計算出字元位在第幾張圖
int picIndex = offset / this.mGridPreTexture;
// 計算出在圖中的位移量
offset -= picIndex * this.mGridPreTexture;

// 取得字元的 rectangle
Rectangle rect = new Rectangle((offset % this.mTextureGrid.Width) * this.mFontSize.Width,
(offset / this.mTextureGrid.Height) * this.mFontSize.Height,
this.mFontSize.Width,
this.mFontSize.Height
);

// 繪製
spriteBatch.Draw(this.mFontTexture[picIndex], position, rect, color);
}

2008年11月1日 星期六

XNA - SpriteBatch 與 RenderState


SpriteBatch.Begin Method

GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace;
GraphicsDevice.RenderState.DepthBufferEnable = false;

GraphicsDevice.RenderState.AlphaBlendEnable = true;
GraphicsDevice.RenderState.AlphaBlendOperation = BlendFunction.Add;
GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
GraphicsDevice.RenderState.SeparateAlphaBlendEnabled = false;

GraphicsDevice.RenderState.AlphaTestEnable = true;
GraphicsDevice.RenderState.AlphaFunction = CompareFunction.Greater;
GraphicsDevice.RenderState.ReferenceAlpha = 0;

GraphicsDevice.SamplerStates[0].AddressU = TextureAddressMode.Clamp;
GraphicsDevice.SamplerStates[0].AddressV = TextureAddressMode.Clamp;

GraphicsDevice.SamplerStates[0].MagFilter = TextureFilter.Linear;
GraphicsDevice.SamplerStates[0].MinFilter = TextureFilter.Linear;
GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.Linear;

GraphicsDevice.SamplerStates[0].MipMapLevelOfDetailBias = 0.0f;
GraphicsDevice.SamplerStates[0].MaxMipLevel = 0;



RenderState的部分:

GraphicsDevice.RenderState.DepthBufferEnable = true;
GraphicsDevice.RenderState.AlphaBlendEnable = false;
GraphicsDevice.RenderState.AlphaTestEnable = false;
// 像是我會開雙面貼圖,就要加上去
GraphicsDevice.RenderState.CullMode = CullMode.None;


SamplerStates的部分:

GraphicsDevice.SamplerStates[0].AddressU = TextureAddressMode.Wrap;
GraphicsDevice.SamplerStates[0].AddressV = TextureAddressMode.Wrap;


對應的網誌

2008年10月26日 星期日

XNA - 3D模型的碰撞檢測 - Part 2

XNA - 3D模型的碰撞檢測 - Part 2

例如:

if (bulletBoundingSphere.Intersects(planeBoundingSphere))
{
//plane's been hit. cue smoke, flames, snakes in a panic, singing nuns, whatever...
}



這裡範例展示要如何取得Model的BoundingSphere…

//Load the model using my game's instance of a ContentManager.

Model myModel = MyGame.ContentManager.Load("ContentMeshesMyModel");

foreach (ModelMesh mesh in myModel.Meshes)
{
//Do stuff with mesh.BoundingSphere
}



接著來看看這些程式碼,它們可以在MyGame.cs裡面找到…

private void AnalyseModel()
{
// Take a copy of the Model's BoneTransforms (transforms to be applied to each part of the model)
GetBoneTransforms();

// Build BoundingParts for Collision Detection
BuildBoundingParts();
}

private void GetBoneTransforms()
{
_modelBoneTransforms = new Matrix[_model.Bones.Count];
_model.CopyAbsoluteBoneTransformsTo(_modelBoneTransforms);
}



是的,這一切聽起來令人興奮,所以來看看著個好東西。這些程式碼在MyGame.cs約頂部的地方,你可以看到以下有趣的程式碼…

//Blob mesh
private string[] _modelBoundingPartNames = new string[]
{
"Fuselage",
"Wing",
"Tail"
};

private Color[] _modelBoundingPartColours = new Color[]
{
Color.Blue,
Color.Red,
Color.GreenYellow
};

private Vector4[][] _modelBoundingPartSubdivisions = new Vector4[][]
{
//Fuselage
new Vector4[] { new Vector4(0.50f, 0.10f, 0.46f, 0.20f),
new Vector4(0.50f, 0.30f, 0.46f, 0.27f),
new Vector4(0.50f, 0.60f, 0.48f, 0.26f)
},
//Wing
new Vector4[] { new Vector4(0.07f, 0.51f, 0.50f, 0.20f),
new Vector4(0.30f, 0.515f, 0.50f, 0.25f),
new Vector4(0.50f, 0.515f, 0.50f, 0.27f),
new Vector4(0.70f, 0.515f, 0.50f, 0.25f),
new Vector4(0.93f, 0.51f, 0.50f, 0.20f)
},
//Tail
new Vector4[] { new Vector4(0.25f, 0.52f, 0.45f, 0.40f),
new Vector4(0.50f, 0.56f, 0.53f, 0.55f),
new Vector4(0.75f, 0.52f, 0.45f, 0.40f)
}
};



接下來看BuildBoundingParts()方法會做些甚麼事情!

///
/// Builds a collection of BoundingParts for each ModelMesh in the Model.
/// Each BoundingPart will contain one or many BoundingSphere as defined in the _modelBoundingPartSubdivisions array.
///

private void BuildBoundingParts()
{
_modelBoundingParts = new BoundingPartList();

BoundingPart boundingPart;

int meshIndex = 0;
foreach (ModelMesh mesh in _model.Meshes)
{
BoundingSphere[] pieces = new BoundingSphere[_modelBoundingPartSubdivisions[meshIndex].Length];
int pieceIndex = 0;

//Create, Scale and Position new BoundingSphere's according to the defined subdivisions for this part of the model.
foreach (Vector4 subdivision in _modelBoundingPartSubdivisions[meshIndex])
{
//Determine the new BoundingSphere's Radius
float radius = subdivision.W * mesh.BoundingSphere.Radius;

//Determine the new BoundingSphere's Center by interpolating.
//The subdivision's X, Y, Z represent percentages in each axis. They will used across the full diameter of XNA's "default" BoundingSphere.
float x = MathHelper.Lerp(mesh.BoundingSphere.Center.X - mesh.BoundingSphere.Radius, mesh.BoundingSphere.Center.X + mesh.BoundingSphere.Radius, subdivision.X);
float y = MathHelper.Lerp(mesh.BoundingSphere.Center.Y - mesh.BoundingSphere.Radius, mesh.BoundingSphere.Center.Y + mesh.BoundingSphere.Radius, subdivision.Y);
float z = MathHelper.Lerp(mesh.BoundingSphere.Center.Z - mesh.BoundingSphere.Radius, mesh.BoundingSphere.Center.Z + mesh.BoundingSphere.Radius, subdivision.Z);
Vector3 centre = new Vector3(x, y, z);

pieces[pieceIndex] = new BoundingSphere(centre, radius);

pieceIndex++;
}
boundingPart = new BoundingPart(mesh.BoundingSphere, pieces, _modelBoneTransforms[mesh.ParentBone.Index], _modelBoundingPartNames[meshIndex], _modelBoundingPartColours[meshIndex]);

_modelBoundingParts.Add(boundingPart);
meshIndex++;
}
}

2008年10月25日 星期六

XNA - CameraManager In Game Programming From Novice to Professional

XNA - CameraManager In Game Programming From Novice to Professional

但如果要用到索引值,而且後續會加入攝影機的狀況下,問題就會發生了。
解決的方式很多種,最小更動的方式就是在 Add 時更新索引值:

public void Add(String id, ICamera camera)
{
String activeCam = null;
if (this.activeCamera != null)
{
// 記錄原本活動中的攝影機名字
activeCam = this.cameras.Keys[this.activeCameraIndex];
}

this.cameras.Add(id, camera);

if (this.activeCamera == null)
{
this.activeCamera = camera;
this.activeCameraIndex = this.cameras.IndexOfKey(id);
}
else
{
// 重新設定攝影機
this.SetActiveCamera(activeCam);
}
}

藍字的部分是新加入的 code,笨笨的,但是簡單明瞭
其他像是阻止進行排序,或者乾脆別用 Sort 系列的集合等等…
嘛~

2008年10月24日 星期五

SyntaxHighlighter 測試


class nTestGameScene : nGameScene
{
nAnimateModel myAnimateModel;

int CurrentTakeIndex = 0;

Transformation myTargetTrans;

bool isLookTarget = false;

int test = 50;
if(test >= 100)
{...}


456


class nTestGameScene : nGameScene
{
nAnimateModel myAnimateModel;

int CurrentTakeIndex = 0;

Transformation myTargetTrans;

bool isLookTarget = false;