4

我对 C# 和 XNA 和编程非常陌生(就像我可以按照教程进行操作,但我自己创建它的大部分内容仍然非常困难)。现在我正在转来转去,试图弄清楚如何做这个“简单”的事情。

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

if (aMouse.LeftButton == ButtonState.Pressed)
{
  Position.X = aMouse.X;
  Position.Y = aMouse.Y;
} 

从我读到的其他鼠标输入来看,我想我需要某种循环(也许是布尔值?),它将向一个方向移动精灵,并且必须运行检查以查看他是否有那个点呢。但是在鼠标单击并创建该循环后得到这一点,运行检查......我一无所知。

4

4 回答 4

2

人们在非常低的水平上回答你的问题。有时在更高的层次上思考问题会有所帮助。

你需要的是一种状态管理。花哨的计算机科学术语是有限状态机。但现在不要费心去查。起初它相当干燥和令人困惑:)

你的角色目前有一种状态——“站在周围”。您需要添加和处理“步行到目的地”状态。

从我读到的其他鼠标输入来看,我想我需要某种循环

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

每次通过游戏循环时,您都应该处理当前状态,并检查所谓的状态转换。那是当您将世界中的某些事物从一种状态更改为另一种状态的时候。例如,当您单击鼠标时,您希望该人开始移动。

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

当您的角色处于“步行至目的地”状态时,您需要根据自上次游戏更新以来经过的时间来更新他们的位置。在 XNA 中,这是为您计算的。如果您不使用 XNA,那么您必须自己检查。您也许可以使用类之Stopwatch类的东西,并检查该Elapsed字段。

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

如果您再次收到鼠标点击,您是否希望“步行到目的地”状态注意它取决于您。如果您确实注意它,您会设置与从“站立”状态转换时相同类型的数据。

因此,您将需要这些变量:

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

游戏中每个角色的角色特定数据都会有所不同,因此您需要为每个角色创建一个新副本。你可能想把它放在一个类中。其余部分更具全局性,因此您可以将其分开,或使其成为游戏、游戏循环、输入类等的一部分(无论您选择如何组织它)。

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

于 2011-02-17T06:03:49.440 回答
2

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

Point2D targetPos;

还有一些常数:

const Point2D speed;

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

于 2011-02-17T05:26:53.150 回答
1

我假设你有三件事:

  1. 当前位置
  2. 所期望的职位
  3. 移动每个“游戏滴答”的速度//不知道什么是游戏滴答?查出!

你正在考虑这样做

在此处输入图像描述

// 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;
于 2011-02-17T05:28:53.780 回答
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);
 }
于 2013-12-17T23:45:46.223 回答