## Crystal Quest like mouse moving

Moderator
Posts: 509
Joined: 2002.09
Post: #1
Anyone know how to do this in Carbon? I've tried to do this like the book Tricks of the... gurus but somehow it isn't Carbon compatible.

"When you dream, there are no rules..."
Unregistered

Post: #2
The way I would be inclined to do it would be to hide the mouse and either (a) constrain the mouse to a square region or (b) just drag the region around behind the mouse (mouse moves frrely within region, if it goes off the edge the region follows to keep it inside).

If the square's coordinate system has 0,0 in the centre, you can read the mouse position in those coordinates and simply make that your velocity for the frame.

As I recall, that was how cq's controls worked (or rather, it should produce the same behaviour).

If I don't make sense, it's because it's late, so post if you're interested and I'll expound more fully later.
Moderator
Posts: 509
Joined: 2002.09
Post: #3
I'm more than interested. I already have a rectangle as my mouse pointer, but I don't know how to do the velocity, I'm very bad at that.

"When you dream, there are no rules..."
Unregistered

Post: #4
First of all, caveat: we will want to be able to set the mouse position, and I don't know how to do this. All my ideas depend upon that idea at at least one point, so if anyone knows could they tell us?

Second caveat: long post. I'm downloading chunks of the devtools from the apple site, and 255MB total is not small beans for a 56k modem. I've spent a while writing this .

Moving on: of the thoughts I've had over a couple of days, I think the following is probably the best way of doing it, because it gives the same maximum speed in all directions. You'll want to store your position as a point - perhaps the centre point of the rectangle you mentioned, if the rectangle was your bounding box?

The key thing about crystal quest's controls was that your mouse position controlled velocity. If you moved the mouse left a bit and stopped, you started moving left, and if you then moved the mouse back to the middle you came to a halt. If you moved the mouse too far, there was a maximum speed.

Hide the cursor and set the mouse to the centre of the screen, and calculate the translation into some zero-centred coordinate system. Then let the user move the mouse freely (even though they can't see it). When the cursor crosses the edge of a specific circle centred on screen, we set the mouse position to the closest point on the edge of that circle.

The circle represents the maximum speed in all possible directions. So when the cursor is at the centre of the circle, it doesn't move at all, when it's at the very edge of the circle at the top, it's moving upwards as fast as it can, and when it's sort of in the middle on the left it'll be drifting slowly leftwards.

Each frame, you'll:

1) get mouse position

2) translate it into the zero-centred coordinate system:

translatedMouseX = mouseX - screenCentreX;
translatedMouseY = mouseY - screenCentreY;

3) add the squares of the translated x and y positions

speedSquared = translatedMouseX*translatedMouseX + translatedMouseY*translatedMouseY

, and see whether speedSquared is larger than the (precalculated) circle radius squared.
If so, go to 4); otherwise, go to 6).

4) multiply each translated mouse coordinate by (circleRadiusSquared/speedSquared), moving them back to the edge of the circle.

5) keep the translated mouse coordinates, you'll need them in a second, but do the inverse transform back into screen coordinates on a copy, and set the global mouse position to that value.

6) all you need worry about now is the translated mouse coordinates, which we know are within a certain circle. Your circle's radius will ideally be larger than your maximum speed, to offer finer control, and so will probably have a radius of at least 100, whereas you probably won't want your ship to be able to move faster than (say) 25 pixels per frame. Although you won't want to have it so large that the user takes too long to move the mouse from one side to the otherÖ
So:

scaleFactor = 25/100;

and then, joy of joys, finally do the movement:

shipPosX += translatedMouseX * scaleFactor;
shipPosY += translatedMouseY * scaleFactor;

You don't have to keep track of the ship's velocity at any stage in this process; all you need to do is remember the ship's position and keep the mouse position inside the circle. Oh, and reset the mouse position to the centre every so often (new life, beginning of levelÖ).

Let me know if this helps, or if it doesn't make sense, or if you find out how to set the mouse positionÖ