Developing A Game Engine with Perl : Part 2 - Mouse Input

Let me start by saying.... I DO NOT KNOW WHAT I AM DOING.

Literally, developing a game engine is not on my resume... yet! So any code or ways of doing anything you read here, is just what I've figured out and works for me, which by no means should suggest to you that it is the proper way to do what ever it may be. Please consult your local guru first.

OK, now that we have that established... Please consider the following as entertainment and should you learn along the way with me, that's wonderful!

Now, by the time of writing this article, I am several months into this undertaking. I'll describe in future posts what the engine is capable of, but for today, let me tell you about what happened over the last 2 weeks. I will likely break them up into separate posts for easier consumption.

Here's a quick list of the accomplishments, disasters and discoveries.

  • Mouse Input Support
  • Hardware Failure
  • Server Upgrade
  • UEFI vs OpenSuSE Installer
  • 32bit -> 64bit & Perl's Storable

Mouse Input Support

Yes, that's right, ANSI Game Engine games will be able to use a mouse. Seems like such a simple concept, that a game engine should have mouse support. And as it turns out, it is. I just hadn't gotten to it until now. You see, my mind-set up to now has been on the idea of BBS door games So keyboard only input was something I never questioned.... until I started developing the engine's Editor

At some point I realized the only way to have the capabilities I wanted in the engine, was to design a graphics & meta editor. Which so far turns out to be basically an MSPaint program that draws in ANSI and contains game meta information. Up until now, I have been relying on procedural code / command line utilities (jp2a, img2txt) to convert jpeg's, gif's & png's images into ANSI, or 3rd party ANSI drawing programs like Moebius ANSI Art Editor

These tools are great for what they can do, unfortunately, they were never intended for such uses as a game engine. So a purpose built ANSI graphics editor that can also store meta and game information was needed.

I very quickly realized that editing graphics and meta information by keyboard alone was slooooooooooooow!!! Not gonna work, I thought. I mean, yeah, it could be done, but even a single scene image is 132x57 "pixels". And to edit 7,524 cells with just arrow keys... nah son, that aint gonna happen. So time to start reading about mouse input via telnet/terminal.

As it turns out, it's quite a simple process. All you need to do is send/print one of a few ANSI Escape Codes to the telnet/terminal client and you can get varying levels of detailed mouse input information in return.

For my application, I needed the most detail, which includes mouse movement, button press, button release and X/Y coordinate information.

Sending/printing these ANSI escape codes to the telnet/terminal client enables/disables exactly (almost, see limitation on Mouse Button 3 below) what I need.

my $turn_mouse_on = "\033[?1003h";
my $turn_mouse_off = "\033[?1003l";

In Perl, \033 is the escape key. The return I started getting from enabling this was perfect.

It looked something like this:

input: ^[[M 5<
Mouse Button: 0, Line: 28, Column: 21

input: ^[[M!5<
Mouse Button: 1, Line: 28, Column: 21

input: ^[[M"5<
Mouse Button: 2, Line: 28, Column: 21

input: ^[[M#5<
Mouse Button: 3, Line: 28, Column: 21

input: ^[[M<80>5<
Mouse Button: 96, Line: 28, Column: 21

First character ^[ is escape (\033) followed by [M followed by the mouse button number and X/Y coordinates, all offset by +32.

What this offset +32 means is, if you take the first example:
input: ^[[M 5<
you see the first character after [M is a space. If we look up what space is in Dec from an ASCII chart we find space is Dec 32. If we adjust for offset, by subtracting 32, it is a 0. Mouse button 0 is the main left mouse button on my mouse.

Mouse Button 0: Left Mouse Click
Mouse Button 1: Middle Mouse Click
Mouse Button 2: Right Mouse Click
Mouse Button 3: Mouse button release
Mouse Button 96: Mouse Move

Not sure if you see the limitation, but Mouse Button 3 is all we get to let us know that a mouse button was let go. Not which mouse button was let go, just that one was. Unfortunately, this is the best I have been able to discover, and works good enough for now.

Here is a quick snip of code I use to extract the necessary information. Sometimes they come in a string with multiple mouse inputs back to back, especially on mouse movements when buffered over telnet. So I split the string on \033[M first to get an array of mouse inputs, then split each mouse input on every character to get the mouse button and coordinate information. I use ord() to get the Dec value of each ASCII character, then adjust for the offset:

input: ^[[M<80>3<^[[M<80>4<

my @mouse = split(/\033\[M/,$input);
foreach my $mouse_input (@mouse) {
    my @button_and_coords = split(//, $mouse_input);
    my $mouse_button = ord($button_and_coords[0]) - 32;
    my $column       = ord($button_and_coords[1]) - 32;
    my $line         = ord($button_and_coords[2]) - 32;
}

I've read somewhere in a man page that you shouldn't put terminal controls into code, and should opt for using a library, such as ncurses. I probably should as well, but I'm still learning and enjoy working directly with the codes today.

Let me know if you have had any experience coding for using mouse in a terminal and if you've used a library like Curses cpan module for Perl.

If you have any suggestions or comments please share constructively. Also please visit our social media pages for lots of fun videos and pictures showing the game engine in action.

ANSI Game Engine on Instagram
ANSI Game Engine on Facebook

Prev << Developing A Game Engine With Perl
Next >> Part 3 - Hardware Failure & Server Upgrade

Cheers!
Shawn

2 Comments

Leave a comment

About Shawn Holland

user-pic Sharing what I learn along the journey of developing ANSI Game Engine