Skip to content

geek

Mouse Clicks and LFS

Wrote a little program that launches LFS, clicks the appropriate buttons and sends strings to connect to a server defined by IP (it's called local in LFS for some reason), puts the player in the game and starts the game.

All works nicely, but man, is it ever an ugly hack. Hard-coding screen coordinates, putting in Thread.Sleep(n) so the UI can catch up, etc. But at least there is a way to automate the client.

Back to coding: Click this

Having run into a number of things I cannot accomplish with InSim in LFS, I've decided to venture down the ugly route of simulating the mouse. Not that horrible. InSim was never really designed for client automation.

I haven't tested this on LFS yet, just Calc.exe, but I finally found a way to do mouse clicks in another application from .NET.

The first route i went down was the SendMessage from user32.dll. Tried many different ways of getting the windowhandle and all that stuff, but no click ever materialized. Also found this method weird. Why do i have to tell it what window i'm clicking when i give it the cursor position. It's likely i just never figured out the proper syntax, but the docs i found certainly didn't aid me much.

Then i found mouse_event also from user32.dll. This one just sent a click event for the current location of the mouse. Just the way i would have expected. And it works!

Here's the sample code:

const int WM_LBUTTONDOWN = 0x0201;
const int WM_LBUTTONUP = 0x0202;
const int SC_MAXIMIZE = 0xF030;
const UInt32 MouseEventLeftDown = 0x0002;
const UInt32 MouseEventLeftUp = 0x0004;

[DllImport("user32.dll", EntryPoint="SendMessage", CharSet=CharSet.Auto)]
public static extern void SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, UIntPtr dwExtraInfo);

public static void Test()
{
    Process myProc = new Process();
    myProc.StartInfo.FileName = @"calc.exe";
    myProc.Start();

    // maximizing so we know where the button is (cheap ass hack for testing)
    SendMessage(myProc.MainWindowHandle,WM_SYSCOMMAND,SC_MAXIMIZE,0);

    Point p = new Point(150,150); // the 6 button
    Cursor.Position = p;
    Thread.Sleep(1000);

    if (myProc.WaitForInputIdle(3000))
    {
        // This one works !!!
        mouse_event(MouseEventLeftDown,0,0,0,new System.UIntPtr());
        mouse_event(MouseEventLeftUp,0,0,0,new System.UIntPtr());

        // This one doesn't do anything :(
        SendMessage(myProc.MainWindowHandle,WM_LBUTTONDOWN, Cursor.Position.X, Cursor.Position.Y);
        SendMessage(myProc.MainWindowHandle,WM_LBUTTONDOWN, Cursor.Position.X, Cursor.Position.Y);
    }
}

Track your Head

Ok, more geek, than programming.

Been spending a lot of time with LFS S2 lately. The new Alpha is out and with my tweaked setup for the GTT is finally drivable. I can even drift it a fair amount. Fantastic game!

Well, i took advantage of the discount that LFS offered on the TrackIR Pro. It looks like a camera, and it is one, but for the infrared spectrum. It tracks your heads movements and adjusts your POV in-game. It uses a progressive exageration of your head movement, so only a couple of degrees left of right and you are looking behind yourself.

Tried it out with LFS and the extra immersion is intense. It comes completely natural to you. You just move your head and you are looking in that direction and the exageration doesn't seem out of place. Makes driving a little funky, since you are no longer driving in the direction you are looking, necessarily. Physics feedback be nice, right about now :) Still, i think i'll adjust. Went for a lap with some AI opponents and being able to look left and right and see your opponents going into a turn was a tremendous help. This device kicks ass!

Live For Speed InSim API 0.01a

I've been playing Racing Simulations for a while. I have an Act Labs Force RS, a wheel I truly enjoy, even though Act Labs has decided to get out of that market. My true love was Need For Speed: Porsche Unleashed. I think it was the best NFS game of the series. A good balance between Arcade and Simulator. However it is also the one that did the worst commercially and now NFS is pretty much a Console arcade racing franchise. Oh well.

I've spent some time with TOCA: Race Driver 2, a beautiful engine, but i never liked the feel of the cars. Grand Prix Legends, is of course the reigning champion among Simulation junkies, so much so that the 10 year(?) old game has been lovingly kept up to date by a devoted fanbase. But talk about hard to drive, and I am really more of a GT racing kind of guy.

While I've known about Live For Speed for a while and played the demo, it wasn't until a couple of weeks ago that I finally broke down and bought the full game. And man, it's shaping up to be my favorite simulator. S1 is already incredible, and graphically good enough. The driving is fun and challenging and extend to which you can tweak your car setup is incredible. And what's been posted of S2 pretty much puts at the top of the genre, if you ask me.

And then there is InSim, a UDP protocol for communicating with either the individual game or a game server to control many aspects, or syphon racing statistics from it. Being a geek, I was drawn to this protocol almost as much as to the racing itself and so I've been busy building an Object/Event model to encapsulate the protocol in C#. Finally all the playing with binary serialization has paid off. The first version of the lib with a VS.NET winforms tester solution can be found here, the full NDoc generate docs are here. Right now this is a binary release of the Lib itself, but once i lock down the Model, i'll release the full source, most likely under the General Public License.

This initial release understands all InSim packets, but I have not built objects around them, so really the only capabilities exposed are:

  • Connect to an LFS instance, and if so configured, automatically respond to keep alive packets
  • Access the LFS version information
  • Send and receive messages
  • Request and subscribe to Status packets.

It'll probably take me a month to flesh out the rest, at my current pace.

IE compatibility

Quirksmode is a very useful site regarding javascript and css compatibility across browsers. Using the snippet regarding mouse coordinates, both of the pages mentioned in the last two posts now work in IE as well.

Trigonometry and Javascript

Had some fun this weekend playing with Javascript, trying draw dynamic lines. Since Javascript doesn't actually have any kind of Draw() or Paint() methods, it comes down to manipulating images. I originally started by scaling images of lines, but even after adding a bunch of variations of lines for different lengths and angles, it always looked damn ugly.

Finally I decided to go the traditional line drawing way: One pixel at a time. Well, almost.. i have tiny segments with lovely alpha blurred edges and created them in horizontal, vertical and the two diagonal variations. And i create dashed lines from them, calculating points along the line.

The current state of this experiment can be found here. (Note: This does not work in IE right now. Really only because i didn't put in the alternate code for finding the mouse coordinates, so i'll fix that in time).

Next, time to play with XmlHttp and generate finalized line segments on the fly and place them, as well as save the information so you can recall the paths drawn. Then, I'll look into emulating the google maps code for panning the background around and bringing in offscreen content on the fly.

Emacs, Nxml-Mode and Unicode

I've run into this too many times and fixed just as many.. grr. And i always forget.. Time to write it down.

I use James Clark's excellent nxml-mode to edit pretty much anything that's vaguely XML, i.e. i usually convert HTML i have to edit into XHTML so i can use this mode.

Problem is, if you just start writing XML in that mode, the resulting file will be Unicode encoded. There is a fix to this. Write proper XML :) Basically, first add this to your .emacs file:

(unify-8859-on-decoding-mode)

Next, make sure you got your proper XML header:

<?xml version="1.0" encoding="utf-8"?>

Tada! File is saved in proper form.

Just to be all proper and stuff, I use this header for my html/xhtmlL

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

Interop vs. Serialize

I was this close to just using ISerializable for by binary representation for networking. But then talking to n8, i decided that leaving the door open for java interop was important enough in Enterprise computing, that I couldn't ignore it.

So, I'm back to coming up with my packet structure in manner that i can easily serialize by hand. Right now the plan is something along the line of a fixed sized header followed by a variable sized gzip-Xml chunk and a variable sized raw data chunk. Both of the variable chunks can be 0 length. The header is used for expressing the purpose of the packet, and describing the offsets of the variable packets. The gzip-Xml is for data that the recipient is supposed to parse and act on, while the raw data packet will be just that, raw data that i sued to construct a complete file.

I need to dig up the test code i did for doing manual serialization in .NET. Really, just what would be done in C with a struct and memcpy, but of course, since in C# you don't have pointers and the memory is managed for you, it's a bit more of a hoop jumping exercise. The code is on another machine, so i'll leave that for another post.