鼠标移动:点击精灵“行走”指向点击的

发布于 2024-10-17 13:25:27 字数 433 浏览 11 评论 0原文

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

想法是这样的,这将是一款塔防游戏;现在我正在研究基本的基础知识。我有一个可以通过键盘输入移动的小精灵,现在我想单击屏幕上的某个位置并让他“行走”到该点。只是我迷失了逻辑。我可以点击,他会跳到那里

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

根据我读到的其他鼠标输入,我想我需要某种循环(也许是布尔?),它将沿着一个方向移动精灵,并且必须检查一下他是否已经到了那一步。但是在单击鼠标并创建循环后得到该点,运行检查......我一无所知。

I'm pretty new to C# and XNA and well programing (like I can follow a tutorial but most of the creating it on my own is still really really hard). Right now I'm going round and round trying to figure out how to do this one "simple" thing.

Here's the idea, its going to be a tower defense game; right now I'm working on bare bone basics. I've got my little sprite guy who will move around with Keyboard input, now I want to click somewhere on the screen and have him "walk" to that point. Only I'm lost on the logic. I can click and he'll jump there with

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

From what I've read for other mousing input, I'm thinking I'll need some kind of loop (bool maybe?) that will move the sprite in a direction and will have to run a check to see if he's got to that point yet. But getting that point after the mouse click and creating that loop, running the check...I'm clueless.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

慈悲佛祖 2024-10-24 13:25:27

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

Point2D targetPos;

和一些常量:

const Point2D speed;

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

You need to add some instance variables:

Point2D targetPos;

And some constants:

const Point2D speed;

When you run through your Update() loop, update the current position by adding the speed vector to it (in the correct direction of course) until you are within a predefined threshold from the target position (usually the thresholds are calculated from the speed vector - if the distance from the current position to the target position is less than the length of the speed vector, then you're at your position). Using a bool in this case would work well. When you click your mouse set another instance variable (moving) to true, and once you've reached your target position, set moving to false.

那支青花 2024-10-24 13:25:27

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

您需要的是一种状态管理。一个奇特的计算机科学术语是有限状态机。但现在不用费心去查找。一开始相当干燥和混乱:)

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

根据我读到的其他鼠标输入,我想我需要某种循环

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

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

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

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

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

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

因此,您需要这些变量:

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

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

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

People are answering your question at a very low level. Sometimes it help to think of the problem at a higher level.

What you need is a type of state management. The fancy Computer Science term for that is a Finite State Machine. But don't bother looking that up right now. It's fairly dry and confusing at first :)

Your character currently has one state - "standing around". You need to add and process the "walking to destination" state.

From what I've read for other mousing input, I'm thinking I'll need some kind of loop

You need one loop, called the game loop. If you're using XNA, you've already got one. But you're on the right track.

Every time through the game loop, you should process the current state, and check for what are called State Transitions. That's when you change something in your world from one state to another state. For example, when you click the mouse, you want the guy to start moving.

In your game loop you check to see if a mouse click just happened. If it did, then set up some data (where to move to), and tell him to start walking by setting his state to "walking to destination". Next update, you'll process that state instead.

When your character is in the "walking to desintation" state, you need to update their position, based on the amount of time that passed since the last game update. In XNA, this is calculated for you. If you're not using XNA, then you'll have to check yourself. You might be able to use something like the Stopwatch class, and check the Elapsed field.

If the character is at the destination, you need to switch them back to the "standing around" state.

If you receive another mouse click, it is up to you if you want the "walking to destination" state to pay attention to it or not. If you do pay attention to it, you set up the same sort of data as when you transitioned from the "standing around" state.

So, you'll need these variables:

  • A timer, to find out the elapsed time since the last game loop (XNA gives it to you)
  • The current player state (maybe an enum)
  • The current player position (a vector)
  • The walking speed of the player (a float, probably), measured in units per second (or millisecond)
  • Data for the "walking to destination" state - target position (another vector)
  • Data related to user input (mouse events that occurred since the last update, the position of those clicks, etc)

The character specific data will be different for each character in your game, so you want a new copy of it for each. You'll probably want to put it in a class. The rest of it is more global, so you can keep it separate, or make it part of your game, game loop, input classes, etc (however you choose to organize it).

I won't cover the vector math for how to actually calculate the partial movement stuff, since other people have covered that. No sense in duplicating those answers. It basically boils down to making a vector between your current position and the target position, and multiplying/dividing it by your walking speed (to chop it up to the distance moved in a single update).

哭泣的笑容 2024-10-24 13:25:27

我假设您有三件事:

  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;

I'm assuming you have three things:

  1. Current position
  2. Desired position
  3. Speed to move each 'game tick' // don't know what a game tick is? find out!

You're looking at doing this

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;
如果没有 2024-10-24 13:25:27

我发现这段代码非常有用...此外,我还添加了几行来防止某些情况发生。例如,有时方向为 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);
 }

I have found this code to be most useful... additionally I have added an extra couple lines to prevent certain situations from occuring. For instance there will be times where direction is 0.83 and speed may have been modified by game factors like terrain/wheather/etc.... if speed is below 1, the sprite may not move at all or even move in the wrong direction!

 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);
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文