ID:2021466
 
(See the best response by Ter13.)
Hello everyone.

I've seen a few threads related to "Zelda Camera Style", but none of them seem to cover a view size with WIDTHxHEIGHT instead of one number. lazy_eye seems to make the camera jump halfway of what I'm aiming for. Hiead's Scrolling Camera gives an error with WIDTHxHEIGHT views as well. Each room in this world is 13x9 and the mobs are tile-based. I don't intend for it to scroll, I'm trying to get the camera to jump from the center of the last room I was in to the center of the next room I'm entering.

Problem description: I can't seem to get the camera to lock-on to the center of the next room when I exit the previous room (and therefore, the camera boundaries) using a WIDTHxHEIGHT view of "13x9".

Best response
I wouldn't bother with lazy eye at all. Just set the eye to the center of the room.

This can be calculated:

room_x = ceil(map_x/VIEW_WIDTH)
room_y = ceil(map_y/VIEW_HEIGHT)


Once you know the room_x/room_y, finding the center of the room is easy:

center_x = (room_x-1)*VIEW_WIDTH + 1 + floor(VIEW_WIDTH/2)
center_y = (room_y-1)*VIEW_HEIGHT + 1 + floor(VIEW_HEIGHT/2)



As for ceil and floor:

#define floor(x) round(x)
#define ceil(x) (-round(-(x)))


These two rounding functions should be a part of every programmer's repertoire. They are way too useful not to be.

Once you have the center_x and center_y values, you can simply:

client.eye = locate(center_x,center_y,z)


A highly efficient way to manage this sort of setup in tiled movement:

atom
movable
Move(atom/NewLoc,Dir=0)
var/atom/OldLoc = loc
var/OldDir = dir
. = ..()
if(.)
Moved(OldLoc,OldDir)
proc
//called after a movement
Moved(atom/OldLoc,OldDir)

mob
Moved(atom/OldLoc,OldDir)
if(client) client.ViewMoved()

client
var
cur_room_x
cur_room_y
cur_room_z
proc
ViewMoved()
if(mob.z)
var/room_x = ceil(mob.x/VIEW_WIDTH)
var/room_y = ceil(mob.y/VIEW_HEIGHT)
var/room_z = mob.z
if(room_z==cur_room_z&&cur_room_x==room_x&&cur_room_y==room_y) return
var/center_x = (room_x-1)*VIEW_WIDTH + 1 + floor(VIEW_WIDTH/2)
var/center_y = (room_y-1)*VIEW_HEIGHT + 1 + floor(VIEW_HEIGHT/2)
cur_room_x = room_x
cur_room_y = room_y
cur_room_z = room_z
eye = locate(center_x,center_y,room_z)
else if(cur_room_z)
cur_room_x = 0
cur_room_y = 0
cur_room_z = 0
eye = mob


Optionally, you can create an object that will act as the client's eye and then smoothly move it from one room to the next if the cumulative abs(xdelta)+abs(ydelta)+abs(zdelta) is equal to 1.