ID:1379560
 
Contents
Mouse Aiming
- Static Camera
- Player-Centric Camera
Relevant Vector Math
Mouse Movement Vector

Changelog

Original:
Easy! You just have to...
//  add the mouse-tracking events to /atom...
atom
// when the mouse enters an atom for the first time
// (MouseMove purposely is not called)
MouseEntered(location, control, params)
..()
usr.client.MousePosition(params)

// when the mouse moves around within an atom
// (and no mouse buttons are down)
MouseMove(location, control, params)
..()
usr.client.MousePosition(params)

// when the mouse moves around and at least
// one mouse button is down
MouseDrag(over_object, src_location, over_location, src_control, over_control, params)
..()
usr.client.MousePosition(params)

// to call an extremely simple proc
// to parse the screen-loc from the given params...
client
// this is the screen-loc passed by the mouse events.
var mouse_screen_loc

// (1, 1) is the bottom-left pixel in the screen.
var mouse_x
var mouse_y

proc/MousePosition(params)
var screen_loc = params2list(params)["screen-loc"]
if(!screen_loc) return

// Sometimes we get screen-loc in the form of
// "map:x:px,y:py"
// but we want to just be using the "x:px,y:py" part.
var position = 1
var colons = 0
var first_colon
for(var/_ in 1 to 3)
var colon = findtext(screen_loc, ":", position)
if(colon)
if(!first_colon) first_colon = colon
position = colon + 1
colons ++
else break
if(colons > 2) screen_loc = copytext(screen_loc, first_colon + 1)

// We split "x:px,y:py" into "x:px" and "y:py".
var comma = findtext(screen_loc, ",")
var screen_x = copytext(screen_loc, 1, comma)
var screen_y = copytext(screen_loc, comma + 1)

// Split "x:px" into x and px.
var colon_x = findtext(screen_x, ":")
var x = text2num(copytext(screen_x, 1, colon_x))
var px = text2num(copytext(screen_x, colon_x + 1))

// Split "y:py" into y and py.
var colon_y = findtext(screen_y, ":")
var y = text2num(copytext(screen_y, 1, colon_y))
var py = text2num(copytext(screen_y, colon_y + 1))

// Store them in the client's variables.
// tile_width() and tile_height() are just procs
// that return whatever world.icon_size says,
// because unfortunately it can be a number or text.
mouse_screen_loc = screen_loc
mouse_x = (x - 1) * tile_width() + px
mouse_y = (y - 1) * tile_height() + py

// Call an event that you can easily override.
MouseUpdate()

proc/MouseUpdate()

// But wait, there's more!
// Your mouse won't be tracked on the "void" areas on the map,
// found in the darkness behind opaque objects and past the map edges
// because there are no atoms there.
// To fix this, we add a mouse-catcher to the background.
New()
. = ..()
screen += new /atom/movable {
name = ""
layer = -1.#INF
mouse_opacity = 2
screen_loc = "SOUTHWEST to NORTHEAST"
}

And that's all you need to do! Simple, right?

The new MouseMove event isn't a disappointment, right?

It looks a lot better than the code in Forum_account's Mouse Position library, right?
Thank you!
Lummox, plz, why we need to do all that messy code to parse screen_loc?
Lol!

Wouldn't it be easier to just bury a mouse_x/mouse_y readonly value in the client?

Set it to relative to the main map component, and let us clamp it ourselves.
Kiao:

Slightly improved:

#define TILE_WIDTH 32
#define TILE_HEIGHT 32

client
var
mouse_x
mouse_y
mouse_screen_loc
proc
MousePosition(params)
var/s = params2list(params)["screen-loc"]
var/x = 0
var/y = 0

var/s1 = copytext(s,1,findtext(s,",",1,0))
var/s2 = copytext(s,length(s1)+2,0)

var/colon1 = findtext(s1,":",1,0)
var/colon2 = findtext(s1,":",colon1+1,0)

if(colon2)
x = (text2num(copytext(s1,colon1+1,colon2))-1) *TILE_WIDTH
x += text2num(copytext(s1,colon2+1,0))-1

else
x = (text2num(copytext(s1,1,colon1))-1) * TILE_WIDTH
x += text2num(copytext(s1,colon1+1,0))-1

colon2 = findtext(s2,":",1,0)
y = (text2num(copytext(s2,1,colon2))-1) * TILE_HEIGHT
y += text2num(copytext(s2,colon2+1,0))-1

mouse_screen_loc = s
mouse_x = x
mouse_y = y


Runs marginally faster. Does roughly the same thing.

Benchmarked at 1,000,000 operations.

Yours: 17.1 seconds avg.
Mine: 12.7 seconds avg.

at 30FPS:

Yours: 1950 operations per frame (avg, undisturbed)
Mine: 2625 operations per frame (avg, undisturbed)

I also converted yours to use the DEFINES rather than the procs for the benchmark, so it was fair.

Mine works from 0,0 being the bottom left, though. That's how I do my positioning math.
Also: as a footnote:

As of version 500, I'm done using screen_loc where it can be avoided. Instead, I'm using transform matrixes to do my work for me.

The only instance where this is inferior is when you need to generate extra edge space on the map using a <1,1 screen loc. For which, I will use an invisible object to pad the screen, then insert the rest of my elements using transform.

Makes calculations a breeze.
Kaiochao wrote:
    //  when the mouse moves around and at least
// one mouse button is down
MouseDrag(over_object, src_location, over_location, src_control, over_control, params)
..()
usr.client.MousePosition(params)


So what happens when the mouse moves around within an atom and at least one mouse button is down? Nothing! This implementation is broken. BYOND's mouse tracking is still incomplete, and until that changes, I will keep using an opacity grid system.
In response to Multiverse7
Multiverse7 wrote:
Kaiochao wrote:
>   //  when the mouse moves around and at least
> // one mouse button is down
> MouseDrag(over_object, src_location, over_location, src_control, over_control, params)
> ..()
> usr.client.MousePosition(params)
>

So what happens when the mouse moves around within an atom and at least one mouse button is down? Nothing! This implementation is broken. BYOND's mouse tracking is still incomplete, and until that changes, I will keep using an opacity grid system.

I think someone's sarcasm detector is broken...

[Edit:] Oh wait... Maybe it's mine? Is this also sarcasm?
In response to Multiverse7
If MouseMove is defined, MouseDrag updates within atoms. It wasn't like that until I brought it up.
SuperSaiyanGokuX wrote:
I think someone's sarcasm detector is broken...

I don't think Kaiochao uses much sarcasm. I know that I wasn't being sarcastic.
However, this does make me wonder:
And that's all you need to do! Simple, right?

The new MouseMove event isn't a disappointment, right?

It looks a lot better than the code in Forum_account's Mouse Position library, right?

That does seem pretty sarcastic.

Kaiochao wrote:
If MouseMove is defined, MouseDrag updates within atoms. It wasn't like that until I brought it up.

Are you serious? I didn't see any mention of that change anywhere.
he's totes serious.

it wasn't a documented change. It was a bug initially, that MouseDrag didn't update, it was silently fixed after Kaio mentioned it.
In response to Super Saiyan X
It wasn't a bug, it was an oversight.
Well, I will have to check that out then!

It seems kind of odd that defining one thing modifies the functionality of something else though. The only problem is that I would have to deal with it tracking the mouse whether a button is held or not.
In response to Ter13
Does yours account for the case where screen-loc is in the form of "map_id:x:px,y:py"?
In response to Multiverse7
Multiverse7 wrote:
SuperSaiyanGokuX wrote:
I think someone's sarcasm detector is broken...

I don't think Kaiochao uses much sarcasm. I know that I wasn't being sarcastic.

There is absolutely NO way that someone could say "This is so simple!", and then post a "system" that uses that many lines of code (granted, he padded it by tossing in extra lines of comments, just to further emphasize his point, I would guess)

My guess is that his point is that the entire thing should be done with one single procedure, that always reports the mouse's pixel coordinates (relative to whatever; the screen, the map, the interface element, whatever), and he's made this post to sarcastically point out how "simple" the current tools can be used to achieve that end result.

How can this NOT be sarcasm? lol

(And there I've gone and ruined the joke by explaining it... :( )
In response to SuperSaiyanGokuX
SuperSaiyanGokuX wrote:
There is absolutely NO way that someone could say "This is so simple!", and then post a "system" that uses that many lines of code (granted, he padded it by tossing in extra lines of comments, just to further emphasize his point, I would guess)

Well, most things are "simple" for Kaio, so I had my doubts.
In response to Multiverse7
Everything to Kaio is simple. It's a proven fact.

Question for Kaiochao;
- What's 2+2?

(hoping his reply would be .. "that's simple, 4!")
In response to Multiverse7
Multiverse7 wrote:
SuperSaiyanGokuX wrote:
There is absolutely NO way that someone could say "This is so simple!", and then post a "system" that uses that many lines of code (granted, he padded it by tossing in extra lines of comments, just to further emphasize his point, I would guess)

Well, most things are "simple" for Kaio, so I had my doubts.

Well, this definitely seems to be true. But really, I'd bet the farm on this case being sarcastic.

In response to Flysbad
Flysbad wrote:
Everything to Kaio is simple. It's a proven fact.

Question for Kaiochao;
- What's 2+2?

(hoping his reply would be .. "that's simple, 2!")

I'm gonna go with 4, actually.
In response to Kaiochao
Welp.. I feel stupid. I didn't notice I put 2 instead of 4.

But, on the other hand.. Told ya everything is simple to Kaio.
Page: 1 2