游戏数学(22)

 

首先需要一个简单的Input类来记录鼠标输入。

public class Input

{

public Point MousePosition { get; set; }

}

Input类将在窗体中初始化和更新。想知道鼠标位置的GameStates需要把Input对象放到自己的构造函数中。现在在窗体类中添加一个Input对象。

public partial class Form1 : Form

{

Input _input = new Input();

在窗体中需要创建一个新函数来更新输入类,该函数将在每一帧中调用。

private void UpdateInput()

{

System.Drawing.Point mousePos = Cursor.Position;

mousePos = _openGLControl.PointToClient(mousePos);

// Now use our point definition,

Point adjustedMousePoint = new Point();

adjustedMousePoint.X = (float)mousePos.X - ((float)ClientSize.Width

/ 2);

adjustedMousePoint.Y = ((float)ClientSize.Height / 2)-(float)mouse-

Pos.Y;

_input.MousePosition = adjustedMousePoint;

}

private void GameLoop(double elapsedTime)

{

UpdateInput();

UpdateInput使用PointToClient函数将光标的位置从窗体的坐标系转换到控件的坐标系。然后将基于OpenGL控件的中心,把光标位置转换到OpenGL坐标系中。这是将控件的X坐标和Y坐标减半实现的。现在,最终的坐标正确地将光标的位置从窗体坐标映射到OpenGL坐标。如果把光标放到OpenGL控件的中心,Input类将报告位置(0,0)。

在结束对窗体代码的讨论之前,还需要编写最后一项功能:必须把新的输入对象添加到圆的状态的构造函数中。

_system.AddState("circle_state", new CircleIntersectionState(_input));

还必须修改状态的构造函数。

Input _input;

public CircleIntersectionState(Input input)

{

_input = input;

将输入传递给状态以后,就可以使用光标的位置了。有必要确认代码都在正确工作。最简单的方法是,使用OpenGL在光标所在的位置绘点。

public void Render()

{

Gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);

_circle.Draw();

// Draw the mouse cursor as a point

Gl.glPointSize(5);

Gl.glBegin(Gl.GL_POINTS);

{

Gl.glVertex2f(_input.MousePosition.X,

_input.MousePosition.Y);

}

Gl.glEnd();

}

运行程序,光标总是会带着一个小方块。注意代码中添加了一个glClear命令。试着删除glClear命令,看看会发生什么事情。

现在鼠标指针已经可以工作,接下来返回到相交性代码。状态的更新循环将执行相交性测试。

public void Update(double elapsedTime)

{

if (_circle.Intersects(_input.MousePosition))

{

_circle.Color = new Color(1, 0, 0, 1);

}

else

{

// If the circle's not intersected turn it back to white.

_circle.Color = new Color(1, 1, 1, 1);

}

}

这是intersect函数的用法,接下来就实际编写该函数。这个测试需要使用大量向量操作,所以把指针对象转换成了一个向量。

public bool Intersects(Point point)

{

// Change point to a vector

Vector vPoint = new Vector(point.X, point.Y, 0);

Vector vFromCircleToPoint = Position - vPoint;

double distance = vFromCircleToPoint.Length();

if (distance > Radius)

{

return false;

}

return true;

}

运行程序,观察光标移入和移出圆时会发生什么情况。

读书导航