[转载]Silverlight C# 游戏开发:L6 3D摄像机

[转载]Silverlight C# 游戏开发:L6 3D摄像机 – Silvery Night – 博客园.

听闻Silverlight5将会支持3D的调用甚至控件,非常兴奋,以后Silverlight就可以开发3D游戏了,但是我这个系列的文章才刚 刚进行到一半,看来要加快速度,这篇主要介绍关于摄像机的相关开发,游戏离不开摄像机(Camera),Camera相当于眼睛,有了眼睛才看到世界,可 是眼睛也有相应的参数,在Balder 3D中创建摄像机相当的简单,在前几篇的代码中就能很容易的看出来,但是如何去控制摄像机达到我们的目的呢,先让我们了解一下3D世界的摄像机。

上图是一个3D世界摄像机的基本属性,它和其他的3D物体一致的部分在于空间坐标表示,但是为了看到世界,它需要一些其他的参数来描述功能,比如 Far\Near Clip(近远景裁切)、Target(目标点) 、Perspective field of view(视角)等等,这些属性为我们渲染3D游戏世界提供了基础参照。打开Balder 中Camera类就能看到这些属性,下面是简要说明:

Camera.Far:远景裁切,即最远看到的距离

Camera.Near:近景裁切,即最近看到的距离

Camera.FieldOfView:视角,所看范围,例如人类的视角就是60度

Camera.Target:目标点,即所看的目标位置,两点成一向量嘛

而其他的我们如果不做深层的开发一般用不上,例如Forward、Up、DepthDivisor、DepthZero

下面开发一个小程序来控制摄像机的这些属性,预览图如下:

这个只是一个简单的控件控制属性刷新的小小程序,首先要设计和制作一个界面:

但是这一次,我写了一个Mesh的组来方便管理,就如我们前面提到的一样,即便是复杂的人物模型,也可以通过这样的方式组合起来:

代码

/// <summary>
/// 自定义的模型组,即便是复杂的人物模型,也可以通过这样的方式组合出来
/// </summary>
public class MeshGroup : Balder.Objects.Geometries.Geometry
{
//计时器
DispatcherTimer _dispatchertimer = new DispatcherTimer();
public MeshGroup()
{
Name
= MeshGroup;
Game_Axis axis_x
= new Game_Axis(new Vertex(300, 0, 0), new Vertex(300, 0, 0), Colors.Red);
Game_Axis axis_y
= new Game_Axis(new Vertex(0, 300, 0), new Vertex(0, 300, 0), Colors.Blue);
Game_Axis axis_z
= new Game_Axis(new Vertex(0, 0, 300), new Vertex(0, 0, 300), Colors.Green);
Children.Add(axis_x);
Children.Add(axis_y);
Children.Add(axis_z);
Mesh Teapot
= new Mesh();
Teapot.Position
= new Coordinate(0, 0, 0);
Teapot.AssetName
= new Uri(/Balder_Studio;component/Res/teapot.ase, UriKind.Relative);
Children.Add(Teapot);
Children.Add(_box);
Children.Add(
new Box() { Dimension = new Coordinate(10, 30, 10), Position = new Coordinate(10, 10, 75) });
MainPage.MainThis.ToShow.Click
+= new System.Windows.RoutedEventHandler(ToShow_Click);
_dispatchertimer.Tick
+= new EventHandler(_dispatchertimer_Tick);
_dispatchertimer.Interval
= TimeSpan.FromMilliseconds(30);
}
void ToShow_Click(object sender, System.Windows.RoutedEventArgs e)
{
_dispatchertimer.Start();
}
Balder.Objects.Geometries.Box _box
= new Box() { Dimension = new Coordinate(10, 20, 30), Position = new Coordinate(75, 10, 0), Name = MyBox };
//旋转角度计数
float angle = 0;
float speed = 2;
void _dispatchertimer_Tick(object sender, EventArgs e)
{
World
= Balder.Math.Matrix.CreateRotationY(angle++);
_box.Position.Y
+= speed;
if (_box.Position.Y >= 50 || _box.Position.Y <= 0)
speed
= speed;

}
}

在这个组里面,在内部实现了一个动画,一块砖头在飘忽,动画参见 L4 模型组和简单的动画
我们在Lesson06.xmal.cs文件中加入如下代码:

Lesson06

public partial class Lesson06 : UserControl
{
public Camera _myCamera = new Camera();
public Lesson06()
{
InitializeComponent();

slider_axis_x.ValueChanged += new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_axis_ValueChanged);
slider_axis_y.ValueChanged
+= new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_axis_ValueChanged);
slider_axis_z.ValueChanged
+= new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_axis_ValueChanged);

slider_axis_x1.ValueChanged += new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_Target_ValueChanged);
slider_axis_y1.ValueChanged
+= new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_Target_ValueChanged);
slider_axis_z1.ValueChanged
+= new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_Target_ValueChanged);

slider_perspective.ValueChanged += new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_Target_ValueChanged);
slider_near_clip.ValueChanged
+= new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_Target_ValueChanged);
slider_far_clip.ValueChanged
+= new System.Windows.RoutedPropertyChangedEventHandler<double>(slider_Target_ValueChanged);

//L3
Game game = new Game() { Width = 600, Height = 400 };
game.Camera
= _myCamera;
game.Camera.Position
= new Coordinate(100, 120, 150);
game.Camera.Target
= new Coordinate(0, 0, 0);

game.Children.Add(new OmniLight() { Position = new Coordinate(0, 0, 0) });
game.Children.Add(
new MeshGroup());
LayoutRoot.Children.Add(game);
}

void slider_axis_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<double> e)
{
axis_z.Text
= ((int)slider_axis_z.Value).ToString();
_myCamera.Position.Z
= slider_axis_z.Value;
axis_y.Text
= ((int)slider_axis_y.Value).ToString();
_myCamera.Position.Y
= slider_axis_y.Value;
axis_x.Text
= ((int)slider_axis_x.Value).ToString();
_myCamera.Position.X
= slider_axis_x.Value;
}
void slider_Target_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<double> e)
{
axis_z1.Text
= ((int)slider_axis_z1.Value).ToString();
axis_y1.Text
= ((int)slider_axis_y1.Value).ToString();
axis_x1.Text
= ((int)slider_axis_x1.Value).ToString();
_myCamera.Target.Z
= slider_axis_z1.Value;
_myCamera.Target.Y
= slider_axis_y1.Value;
_myCamera.Target.X
= slider_axis_x1.Value;

text_perspective.Text = ((int)slider_perspective.Value).ToString();
text_near_clip.Text
= ((int)slider_near_clip.Value).ToString();
text_far_clip.Text
= ((int)slider_far_clip.Value).ToString();
_myCamera.Far
= (float)slider_far_clip.Value;
_myCamera.Near
= (float)slider_near_clip.Value;
_myCamera.FieldOfView
= slider_perspective.Value;

}
}

我尽量简单描写,建议不是太明白的朋友参看之前的文章,主要是用Slider控件控制属性达到效果。

那么最后我们运行一下看看效果吧:

获取 Microsoft Silverlight

源代码下载地址:点击这里下载工程

工程中如果缺少Balder.dll请在这里快速下载:SL4_Balder.rar

推荐Silverlight游戏开发博客:深蓝色右手

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏