控制台应用程序鼠标单击 XY 坐标检测/比较
我正在 C# 控制台应用程序中开发一款游戏,纯粹是作为使用更好方法之前的练习。与使用诸如内置按钮功能的 Windows 窗体应用程序之类的东西相反,我努力抓住光标位置(我知道如何做)并将其与控制台应用程序内定义的多个区域进行比较也许是像素位置,但我也不知道除了像素之外是否还有某种内置的空间单位(最后一位是我无法计算的部分)。
PS我知道这是一般性的,没有提供任何代码,但我不觉得有必要,因为我所要求的只是简要解释如何在控制台应用程序中获取 XY 坐标,并将它们粘贴到 int 中变量。
非常感谢! :D
I have a game that I am working on in a C# console application, purely as practice before going on to better methods. As opposed to using something such as a Windows Forms App, which has button functionality built in, I am endeavoring to grab the cursor position (which I know how to do) and compare it to a number of area's inside a console application as defined by perhaps pixel location, but I also do not know if there is some sort of built in unit of space other than pixels (this last bit is the part I am unable to figure).
P.S. I know this is in general terms, with no code already provided, but I do not feel that it is needed as all I am asking for is a brief explanation of how to grab X Y coordinates inside a console application, and stick them in int variables.
Many Thanks in advance! :D
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
经过很长时间的搜索,我终于找到了这个例子。下载页面上的示例程序。除其他外,它还为您提供控制台窗口中的鼠标位置(基于字符)。
编辑:这是我的
ConsoleListener
类(包含我的NativeMethods
类的一部分)。您可以将处理程序附加到
MouseEvent
(调用Start()
方法之后)。为了使其正常工作,您可能需要首先执行此代码:
使用此文件头:
After searching for a long time I finally found this example. Download the example program on the page. It gives you, among other things, the mouse location in the console window (character-based).
EDIT: This is my
ConsoleListener
class (with part of myNativeMethods
class).You can attach a handler to the
MouseEvent
(after calling theStart()
method).To make it work properly, you probably want to execute this code first:
With this file header:
此外,控制台不仅仅用于文本处理。你可以为它编写相当不错的窗口管理器。你可以用它做任何事情。只是更难了。
不过速度比较慢。
我使用 C# 实现了一个虚拟机,使用用户界面的控制台。它不会逐行打印文本;而是逐行打印文本。它[界面]的作用很像GUI。
如果你想在控制台上使用鼠标输入,请尝试这个钩子:
链接
Also, the console isn't just for text processing. You can write pretty decent window managers for it. You can do anything with it. It's just harder.
It's slower, though.
I implemented a virtual machine in C# using the console for the user interface. It doesn't print lines of text one after the other; it [the interface] acts rather like a GUI.
If you want mouse input on the console, try this hook:
Link
当您在不使用事件的情况下编写游戏时……您实际上是在自己实现事件。这是有利的,因为与使用语言的内置事件相比,您可以使其更加高效。如果您知道自己在做什么,以这种方式编写的游戏就不太容易出错。
例如,当我试图教我的兄弟如何编写游戏时,我为他编写了一个简单的贪吃蛇游戏。我在一个线程中有主循环,移动蛇并将其绘制在循环中的新位置。我会同时运行一个线程,连续检查 4 件事:
如果蛇撞到了自己(游戏结束);如果游戏结束,则停止更新蛇主位置的主线程,将游戏打印到屏幕上,等待按键输入,然后重新启动游戏。
如果蛇吃了一个苹果;增加表示已经吃掉了多少个苹果的计数器变量,并在屏幕上打印这个新值,覆盖之前的值。
如果按下箭头键。如果向左,则将移动设置为 0,如果向右,则设置移动为 1,如果向下,则设置移动为 2,如果向上,则设置移动为 3。 存储的 int 是指向使蛇移动的 4 个委托的数组的指针朝正确的方向。
更新蛇位置的主循环将告诉线程检查这 4 件事蛇正在做什么。我这样做的方法是让蛇头移动的屏幕上的每个单元格都引用二维代表数组。关于这组代表:
游戏是在控制台模式下编写的,并使用控制台颜色。控制台设置为 80x50 字符。委托如下:“delegate void ptr()”;然后我使用以下命令创建数组:
“ptr[,] pos = 新 ptr[80,50]”。假设蛇的头部位于屏幕上的位置 (4,5),当它移动到那里后,主循环将执行“pos[4,5].Invoke();”。
其中之一:
当蛇移动到新位置时,主循环线程将获取蛇在屏幕上覆盖的每个单元格,并将该位置的委托设置为指向名为“void gameover()”的函数,该函数将设置 gameover_ 变量为真。因此,当检查游戏状态的循环线程检查游戏结束时,它会冻结游戏并在屏幕上打印游戏结束。
其他:
当在屏幕上绘制一个苹果时,它被绘制的委托位置(随机的)被设置为指向“voidincrement_apple()”,它会增加苹果计数器,从视图中删除当前的苹果,并绘制一个新的苹果在屏幕上,将旧苹果位置设置为指向“void nop()”,该位置不执行任何操作,并将新苹果位置指向“voidincrement_apple()”。
这基本上就是游戏的运作方式。正如您所看到的,蛇移动到屏幕上的这些位置,并且它没有执行任何显式检查,例如“if(snake_position == some_position)”,游戏会自动为游戏中发生的所有事情执行它应该执行的所有操作,就像当您单击表单上的按钮时,分配给该事件的操作会自动执行,而无需您自己检查该事件。
所以你看,我本可以使用 C# 提供的表单和默认事件,但我没有。我使用控制台界面,并实现了我自己的事件系统。
这就是它在幕后的工作原理:
表单应用程序的主循环将在一个线程中运行,该线程检查屏幕上所有按钮等的输入。这些项目中的每一个都会将它们使用的布尔变量设置为 true。当您单击此按钮时,另一个运行循环的线程会检查您按下的内容,并假设您按下了一个名为“button1”的按钮,该按钮将分配有一个委托;然后,该委托将执行它所指向的任何内容。
有点难以解释,但这对你来说有意义吗?
When you write a game without using events... all you are really doing it implementing events yourself. This is advantageous because you can make it much more efficient than by using your language's built-in events. Games written this way are less error-prone if you know what you are doing.
For example, when I was trying to teach my brother how games are written, I wrote a simple snake game for him. I had the main loop in a thread, move the snake and draw it at its new position in a cycle. I would have a thread running at the same time that continuously checks 4 things:
If the snake crashed into itself (game over); if game over occurs, halt the main thread that updates the main position of the snake, print game over onto the screen, await key input, then restart the game.
If the snake had eaten an apple; increment the counter variable that says how many apples have been eaten, and print this new value on the screen, over-writing what was previously there.
If the snake had eaten a number of apples divisible by 10 (snake grows by 1 cell, subtract from a wait variable that says how much time should pass between each movement the snake makes)
If an arrow key has been pressed. If left, set move to 0, if right set move to 1, if down set move to 2, if up set move to 3. The int that this is stored in is a pointer to an array of 4 delegates that make the snake move in the right direction.
The main loop that updates the position of the snake would tell the thread checking these 4 things what the snake is doing. The way I do this is I have every cell on the screen that the snake's head moves to refer to a 2-dimensional array of delegates. About this array of delegates:
The game is written in console mode, and uses console colours. The console is set to 80x50 characters. A delegate as follows: "delegate void ptr()"; then I create the array with:
"ptr[,] pos = new ptr[80,50]". Say the snake's head is at position (4,5) on the screen, after it has moved there the main loop would execute "pos[4,5].Invoke();".
One of them:
When the snake moves to a new position, the main loop thread would get each cell that the snake covers on the screen, and set the delegate at that position to point to a function called "void gameover()" which would set the gameover_ variable to true. So when the loop thread that checks the status of the game checks for gameover, it freezes the game and prints game over on the screen.
Another:
When an apple is drawn on the screen, the delegate position it gets drawn at (which is randomized) is set to point to "void increment_apple()" which increments the apple counter, removes the current apple from view, and draws a new apple on the screen, setting the old apple position to point to a "void nop()" which does nothing, and the new apple position to point to "void increment_apple()".
This is basically how the game works. As you can see, the snake moves to these positions on the screen, and it without performing any explicit checks like "if(snake_position == some_position)", the game automatically does everything it is supposed to for everything that happens in the game, much like how when you click a button on a form, an action assigned to that event is automatically executed, without you having to check for the event yourself.
So you see, I could have used a form and the default events that C# provides, but I didn't. I used the console interface, and implemented my own events system.
This is how it works behind the scenes:
the main loop for your form app will run in a thread that checks for input from all the buttons, etc on the screen. Each of these items will set a boolean variable they use to true. When you click this button, another thread running a loop checks what you have pressed, and say you pressed a button called "button1", that button would have had a delegate assigned to it; that delegate is then executed with whatever it points to.
Kind of hard to explain, but does this make sense to you?
我知道这是不久前的事,但在控制台中获取鼠标位置并不难。我只会向您展示我使用的代码,以防其他人想要答案:
享受!
编辑:
我刚刚想出了一种简单的方法来获得鼠标点击(这也适用于键盘按钮,只需参考 https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes?redirectedfrom=MSDN你需要什么
I know this is a while ago, but it's not super hard to get the mouse position in the Console. I'll just show you the code I use in case someone else wants an answer:
Enjoy!
Edit:
I just figured out a simple way to get mouse clicks as well (this also works with keyboard buttons, just refer to https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes?redirectedfrom=MSDN for what you need
@Frank Krueger 说的话。你真的想这样做吗? Windows 窗体旨在使此过程变得更加容易。
如果这样做,您将需要在低级 Windows API 中使用 PInvoke。尝试此作为起点 - 但请注意这比 Windows 窗体应用程序要复杂得多。
What @Frank Krueger said. Do you really want to do this? Windows Forms is designed to make this much easier.
If you do, you'll need to use PInvoke into the low level Windows API. Try this as a starting point - but be aware that this is considerably more complex than the Windows Forms application would be.
经过大量研究,我找到了解决方案。
使用 Button 类和我在下面创建的 GUI,可以制作一个按钮,并用鼠标单击它(它不能完美工作)。
并且您需要导入
System.Windows.Forms
和System.Drawing
。After much studying, I found a solution.
With the Button class and the GUI that I created below, it is possible to make a button, and it is clicked with or mouse (it does not work perfectly).
And you need to import
System.Windows.Forms
andSystem.Drawing
.