鼠标移动:单击精灵“行走”以点击点击

时间:2011-02-17 05:14:46

标签: c# mouse user-input game-physics

我对C#和XNA非常陌生并且编程很好(比如我可以按照教程进行操作,但是大多数我自己创建它仍然非常困难)。现在,我正在四处寻找如何做这个“简单”的事情。

这是一个想法,它将成为塔防游戏;现在我正在研究裸骨基础知识。我有我的小精灵家伙,他会用键盘输入来移动,现在我想点击屏幕上的某个地方并让他“走”到那一点。只有我迷失在逻辑上。我可以点击,他会用

跳到那里
if (aMouse.LeftButton == ButtonState.Pressed)
{
  Position.X = aMouse.X;
  Position.Y = aMouse.Y;
} 

从我读过的其他鼠标输入中,我想我会需要某种循环(bool可能?),它会将精灵移动到一个方向,并且必须运行检查,看看他是否是到了那一点。但是在鼠标点击并创建该循环后得到这一点,运行检查......我很无能为力。

4 个答案:

答案 0 :(得分:2)

您需要添加一些实例变量:

Point2D targetPos;

还有一些常数:

const Point2D speed;

当您运行Update()循环时,通过向其添加速度向量(当然是正确的方向)来更新当前位置,直到您处于距目标位置的预定义阈值内(通常阈值是根据速度矢量 - 如果从当前位置到目标位置的距离小于速度矢量的长度,那么你就在你的位置。在这种情况下使用bool会很好用。当您单击鼠标时,将另一个实例变量(移动)设置为true,一旦到达目标位置,请将移动设置为false。

答案 1 :(得分:2)

人们正在以非常低的水平回答你的问题。有时它有助于在更高层次上考虑问题。

您需要的是一种状态管理。花哨的计算机科学术语是有限状态机。但是现在不要再费心了。起初相当干燥和混乱:)

你的角色目前有一个状态 - “站着”。您需要添加并处理“步行到目的地”状态。

  

从我读过的其他鼠标输入中,我认为我需要某种循环

你需要一个循环,称为游戏循环。如果您正在使用XNA,那么您已经拥有了XNA。但是你走在正确的轨道上。

每次通过游戏循环,您都应该处理当前状态,并检查所谓的状态转换。那是你将世界上的某些东西从一个州改变到另一个州的时候。例如,当您单击鼠标时,您希望该人开始移动。

在你的游戏循环中,你检查是否发生了鼠标点击。如果确实如此,那么设置一些数据(在哪里移动),并通过将他的状态设置为“步行到目的地”来告诉他开始行走。下一次更新,您将处理该状态。

当你的角色处于“走向desintation”状态时,你需要根据自上次游戏更新后经过的时间更新他们的位置。在XNA中,这是为您计算的。如果你不使用XNA,那么你必须自己检查一下。您可以使用类似Stopwatch类的内容,并查看Elapsed字段。

如果角色在目的地,您需要将它们切换回“站立”状态。

如果您再次点击鼠标,如果您希望“步行到目的地”状态注意与否,则取决于您。如果你注意它,你可以设置与从“站立”状态转换时相同的数据。

所以,你需要这些变量:

  • 计时器,找出自上次游戏循环后经过的时间(XNA给你)
  • 当前玩家状态(可能是enum
  • 当前玩家位置(向量)
  • 玩家的步行速度(可能是浮动),以每秒(或毫秒)为单位测量
  • “步行到目的地”状态的数据 - 目标位置(另一个向量)
  • 与用户输入相关的数据(自上次更新以来发生的鼠标事件,这些点击的位置等)

游戏中每个角色的角色特定数据会有所不同,因此您需要为每个角色创建一个新副本。你可能想把它放在课堂上。其余部分更全球化,因此您可以将其分开,或将其作为游戏,游戏循环,输入类等的一部分(但您选择组织它)。

我不会介绍如何实际计算部分运动内容的矢量数学,因为其他人已经涵盖了这一点。没有意义重复这些答案。它基本上归结为在当前位置和目标位置之间制作一个向量,并将其乘以/除以您的步行速度(将其切换到单次更新中移动的距离)。

答案 2 :(得分:1)

我假设你有三件事:

  1. 当前位置
  2. 期望的位置
  3. 快速移动每个'游戏标记'//不知道游戏标记是什么?找出来!
  4. 你正在考虑这样做

    enter image description here

    // dx, dy are delta x and delta y. It's how far in each direction
    // the player must travel
    // note, I fixed a typo where they were desired - desired... should be
    // desired - current, as they are now
    float dx = desiredX - currentX;
    float dy = desiredY - currentY;
    
    // d uses the pythagorean theorum to find the distance between current and desired
    float d = sqrt(dx*dx + dy*dy);
    // fac is how far along that line between desired and current will you move
    float fac = d / speed;
    
    // mx is the component of the dx line proportional to the size of fac : d
    // which means it's how far in the x direction you'll move
    float mx = dx * fac;
    float my = dy * fac;
    
    // the new postition is the old position plus the move value
    float newPositionX = dx + mx;
    float newPositionY = dy + my;
    

答案 3 :(得分:0)

我发现这段代码最有用......另外我添加了额外的几行以防止出现某些情况。例如,有时候方向是0.83,速度可能已经被地形/天气等等游戏因素修改过......如果速度低于1,精灵可能根本不会移动甚至向错误的方向移动!

 if (Vector2.Distance(Position, TargetPosition) > 2.0f)
 {
    velocity = Vector2.Subtract(TargetPosition, Position);
    velocity.Normalize();
    /// Now no matter which direction we are going we are always moving @ sprite.Speed
    /// at velocity or speed below 1 - problems occur where the unit may not move at all!!
    if(current_Speed < 1)
    {
       Vector2 temp = (velocity * 10) * (current_Speed * 10);
       Position += temp / 10;
    }
    else
    { 
       Vector2 temp = velocity * current_Speed;
       Position += temp;
    }
    //convert to int to render sprite to pixel perfect..
    Position = new Vector2((int)Position.X, (int)Position.Y);
 }