ID:259509
 
I suppose this falls under "General", since this is a "query about a feature"...

I'm considering trying my hand at creating a Byond game with isometric graphics. If I set a pixel_x and pixel_y offset on a turf, and then have a mob move to that turf, does the engine account for the fact that the turf's visual location isn't the same as its actual location? Would my mob's icon end up positioned over the turf's offset? Or would it end up positioned over the turf's actual location?

Assuming that the mob's icon would end up positioned over the turf's offset, would it appear to be moving towards that point during it's movement animation? Or would it move towards the actual location of the turf, and then "jump" to the offset position at the end of the movement?

Thanks,
Corporate Dog
Corporate Dog wrote:
I suppose this falls under "General", since this is a "query about a feature"...

I'm considering trying my hand at creating a Byond game with isometric graphics. If I set a pixel_x and pixel_y offset on a turf, and then have a mob move to that turf, does the engine account for the fact that the turf's visual location isn't the same as its actual location? Would my mob's icon end up positioned over the turf's offset? Or would it end up positioned over the turf's actual location?

Assuming that the mob's icon would end up positioned over the turf's offset, would it appear to be moving towards that point during it's movement animation? Or would it move towards the actual location of the turf, and then "jump" to the offset position at the end of the movement?

In the few tests I've run, the mob or obj's position appears to be completely independent of pixel_x and pixel_y of the turf.

Lummox JR
In response to Lummox JR
In addition, if you want to make the mob or obj glide to the new location, you should gradually alter the mob or obj's pixel offsets over the next 4 ticks (about how long it takes a smooth animation to get to the destination). Otherwise it will snap to the offset you are using.
In response to Shadowdarke
Shadowdarke wrote:
In addition, if you want to make the mob or obj glide to the new location, you should gradually alter the mob or obj's pixel offsets over the next 4 ticks (about how long it takes a smooth animation to get to the destination). Otherwise it will snap to the offset you are using.

Just to be clear, that snap only happens if you actually change the pixel_x and pixel_y values manually.

Lummox JR
In response to Lummox JR
Lummox JR wrote:

In the few tests I've run, the mob or obj's position
appears to be completely independent of pixel_x and
pixel_y of the turf.

Ugg. I was afraid of that.

So I guess we have to write our own routines to handle mob movement animation if we want to do isometric graphics.

Thinking out loud, this would entail setting the mob icon to an animation sequence, adjusting the mob's pixel_x and pixel_y values in a loop (making it appear to move towards the turf's VISUAL location), moving the mob to the turf's ACTUAL location (in one big jump), and then resetting the mob's icon.

Groovy.

Regards,
Corporate Dog
In response to Corporate Dog
Corporate Dog wrote:
So I guess we have to write our own routines to handle mob movement animation if we want to do isometric graphics.

Thinking out loud, this would entail setting the mob icon to an animation sequence, adjusting the mob's pixel_x and pixel_y values in a loop (making it appear to move towards the turf's VISUAL location), moving the mob to the turf's ACTUAL location (in one big jump), and then resetting the mob's icon.

Don't forget to turn off the animate_movement var, or else resetting the mob's location will cause it to jump back and then slide into place.

Lummox JR
In response to Corporate Dog
Corporate Dog wrote:
So I guess we have to write our own routines to handle mob movement animation if we want to do isometric graphics.

I need to go back and re-read the traditional way for handling isometric drawing (I have a URL about it that someone posted), but I suspect that people are too tied to tradition here.

For L&D we use isometric for everything, and we don't have to do any of this fancy stuff in the code. We don't use pixel offsets and we don't have to do anything funky with mob movement.

In our case, we handle it in the drawing technique...I started to try and explain it, but perhaps I shouldn't rob Guy of a good opportunity for a BYONDscape article!

Since I'm not very familiar with traditional isometric techniques, perhaps there is some element I'm missing. I would be interested in having someone who is familiar with traditional techniques check out L&D and indicate whether we're meeting the same requirements.
In response to Deadron
For Isometric movement, moving diagonally, you should move half the distance vertically that you move horizontally. (I'll call the distance X.) Moving solely up or down would move 1X, and moving left or right would move 2X.

L&D is graphically isometric (and looks great!), but the movement isn't to scale with the isometric background.
In response to Shadowdarke
Shadowdarke wrote:
L&D is graphically isometric (and looks great!), but the movement isn't to scale with the isometric background.

Hmm...well looks like I do need to research some things.

In this case, then, I think someone should think long and hard about whether it's important for the movement to be properly isometric. It's taking on a big chunk of complexity and possible lag-inducing code to deal with it...

Of course the DDT has little room to talk on that score, in general.
In response to Deadron
Of course the DDT has little room to talk on that score, in general.

On the plus side, the hub package for L&D is VERY nicely compressed. I groaned at the prospect of downloading such a beast now that I'm back on dial-up, but it's no bigger than some of the other games I've seen on BYOND--and many of those didn't have half as impressive a graphical impact in their entirety as the two screenshots I've seen for L&D have!
In response to Deadron
Finally got a basic isometric engine to work in Byond. Here are the hoops I had to jump through to get it to work:

First, all mobs must be the standard 32x32 (so unfortunately, no multi-tile mobs... yet). Isometric tiles are 64x32. Map objects (walls and such) are 64 pixels in width, but can be any height.

First, after creating your tile/map object images, import them to dmi files, and when asked, break them up into seperate states within the dmi.

The turf and obj classes which contain these icons have a New() method which first sets the icon_state to "0,0", and
then goes through each of the states, and attaches the other icon states as offset overlay images on the turf or obj. If the x location of the turf or obj is evenly divisible by two, we offset the icon and its overlays by 16 pixels in the y direction. This New() method also serves to set the appropriate drawing layer for turfs or objs (which takes into account, among other factors, how many Byond tiles we are from the top of the map... tiles towards the bottom of the map get drawn in a higher layer).

We also have some weird mob movement tricks, very much like the ones described elsewhere in the thread. Check to see if we can move into a tile, and if we can, move the mob there in one jump. Immediately set the mob's offsets, so it looks as if he hasn't moved from the previous tile. Then, in a loop, add to/subtract from the offsets until we reach the desired offset in the new tile.

Here's what it looks like in the map editor... a little cludgy, I know, but the thing wasn't made for isometric graphics. When designing your map, it helps to picture all of the green columns shifted half a tile up...




And here's what it looks like in practice...



At some point, after I clean the code up, I'll be sure to post it to the libraries here.

Regards,
Corporate Dog



In response to Corporate Dog
Interesting approach! My method is and still remains having tiles as 4x2 isometric tiles. It allows me to have lots of terrain data and the like without much mapwork. In addition, it makes allowing players to create their own structures easier (people can plant their own grass!), as well as giving the game a very big scale, which, as intended, makes players look smaller, as though they aren't kings or queens of the universe (fancy that!).

And to top it off, it's a WYSIWYG map editing style -- I draw it in the map editor exactly like I want it to appear in-game. Or, if I want, I can simply place little 'wall-builder' pieces, which will dynamically create the wall, but will not be WYSIWYG.


The player movement is handled in a simulated 32x16 pixel grid -- the tiles themselves are actually represented by the 4x2 tiles, but the internal movement can be handled on a grid that isn't actually apparent to the player. Incidentally, mobs and objs conform to the small grid, while terrain, walls, and floors conform to the large grid.
In response to Corporate Dog
I've been commisioned to make an isometric BYOND system. It hasn't gone to code yet, but my notebook is full of theory. I had considered offset turfs, but decided against it because of the DM map editor and difficulty of explaining it to my taskmaster... er... client. I figured it would be easier to just make the isometric turfs graphically, then worry about isometric movement for movable atoms.

I find your idea about graphic layers particularly interesting. As far as I know, the project I'm working for doesn't have multi-tile objects.

If I understand your post correctly, you are shifting the layer of the entire object based on it's y coordinate. Does that mean your movement routines also have to shift the layer of objects that move between y values?

As an alternative, you could make each row have a layer based on it's distance above the base of the object. Then you can leave the layers untouched as objects move and just worry about pixel offsets. No layer manipulations will be required after the objects are initialized.

For example, a tree that is 3 turfs tall might draw the top on layer 22, the middle on layer 12, and the bottom on layer 2 (default turf layer) if you choose an offset of 10 layers per y shift. A mob two tiles high would be drawn on layers 14 and 4. The mob will show over top of trees that have the same y or higher, but will display behind trees that have a lower y.
In response to Shadowdarke
Shadowdarke wrote:
If I understand your post correctly, you are shifting the layer of the entire object based on it's y coordinate. Does that mean your movement routines also have to shift the layer of objects that move between y values?

Presumably...that's how we're doing it for L&D. Some of this might be automated now if you are using pixel offsets, since the algorithm that Tom described for their layering is pretty much the same: The drawing layer is determined by who is further down and to the left I believe.
In response to Shadowdarke
Shadowdarke wrote:

If I understand your post correctly, you are shifting the
layer of the entire object based on it's y coordinate.

For the most part, yes.
For a turf, I might set its layer to TURF_LAYER+(world.maxy-y), for instance.
And when I'm "constructing" a multi-tile object from its icon states, I'll often set the base tiles to OBJ_LAYER+(world.maxy-y) and the other tiles to MOB_LAYER+1+(world.maxy-y)

Does that mean your movement routines also have to shift
the layer of objects that move between y values?

Yep.


As an alternative, you could make each row have a layer
based on it's distance above the base of the object. Then
you can leave the layers untouched as objects move and
just worry about pixel offsets. No layer manipulations
will be required after the objects are initialized.

For example, a tree that is 3 turfs tall might draw the
top on layer 22, the middle on layer 12, and the bottom on
layer 2 (default turf layer) if you choose an offset of 10
layers per y shift. A mob two tiles high would be drawn on
layers 14 and 4. The mob will show over top of trees that
have the same y or higher, but will display behind trees >that have a lower y.

I'm trying to get my mind around what you're saying here. If the mob moves "behind" the tree in the scenario you're describing (meaning its y is one greater than the tree's y) won't it still show through the tree? 14 and 4 are higher than 12 and 2. Or am I missing something here?

EDIT: Scratch that. I see it now. If the mob is behind the tree, it's 14 and 4 layer fiddly bits will actually be compared to the 22 and 12 layer fiddly bits of the tree. Got it.

Regards,
Corporate Dog
In response to Shadowdarke
I don't quite get why you'd set objects' layers based just on their y coordinate on the map. The system I would use: Give every "tile" and every "object" (actually a collection of atoms) an x and y coordinate for the regular rectangular map: mx and my. Then give it a sub-coordinate for its location within the tile, plus z. The layer of the object would be mapx+mapy, or if you use BYOND-style Cartesian coordinates, mapx+(max_mapy-mapy). Thus tiles would layer like this:
1234
2345
3456
4567

That's in the view of the 2D map, not the isometric map that represents it, which would be thus:
   1
2 2
3 3 3
4 4 4 4
5 5 5
6 6
7

The sub-position in a tile could determine pixel offsets:
// this is a 64x32 tile
pixel_x=subx+suby-32
pixel_y=round((suby-subx)/2)+z
layer=(mapx+(max_mapy-mapy))*32-round((suby-subx)/2)

Lummox JR
In response to Lummox JR
This sort of confuses me... partially because I'm not sure whether or not we're even using common terminology, and partially because I just got back from happy hour with my co-workers. :)

So let's step through this...

Lummox JR wrote:
The system I would use: Give every "tile" and
every "object" (actually a collection of atoms) an x and
y coordinate for the regular rectangular map: mx and my.

Gotcha.

Then give it a sub-coordinate for its location within the > tile, plus z.

When you say "within the tile" are you referring to an object's location within the isometric tile, or within the 32x32 standard Byond tile?

The layer of the object would be mapx+mapy, or if you use
BYOND-style Cartesian coordinates, mapx+(max_mapy-mapy).
Thus tiles would layer like this:
1234
> 2345
> 3456
> 4567

That's in the view of the 2D map, not the isometric map
that represents it, which would be thus:
   1
> 2 2
> 3 3 3
> 4 4 4 4
> 5 5 5
> 6 6
> 7


OK, I understand that.

The sub-position in a tile could determine pixel offsets:
// this is a 64x32 tile
> pixel_x=subx+suby-32
> pixel_y=round((suby-subx)/2)+z
> layer=(mapx+(max_mapy-mapy))*32-round((suby-subx)/2)


But this last part is what completely confuses me. This is the pixel_x, pixel_y, and layer for WHAT exactly? An isometric tile? An isometric object within an isometric tile? Could you explain this part a little better?

Also, how are you imagining the icon for an isometric tile? As a 2:1 ratio rhombus?

Regards,
Corporate Dog
In response to Corporate Dog
Corporate Dog wrote:
Then give it a sub-coordinate for its location within the tile, plus z.

When you say "within the tile" are you referring to an object's location within the isometric tile, or within the 32x32 standard Byond tile?

I meant within the isometric tile, yes. Specifically, if you imagine the isometric tile as a regular tile on a standard rectangular map. Think of the tile as drawn being the "projected" version, vs. how it actually exists within an internal map. For clarity, I'll call the internal version the virtual tile, and the one seen on the screen (consisting of several atoms) will be the projected tile.

The sub-position in a tile could determine pixel offsets:
// this is a 64x32 tile
pixel_x=subx+suby-32
pixel_y=round((suby-subx)/2)+z
layer=(mapx+(max_mapy-mapy))*32-round((suby-subx)/2)

But this last part is what completely confuses me. This is the pixel_x, pixel_y, and layer for WHAT exactly? An isometric tile? An isometric object within an isometric tile? Could you explain this part a little better?

Those would be the settings for the projected object. That defines the layer of an obj or turf, and its pixel offset (where subx=16 and suby=16 is the center of the virtual tile).

Also, how are you imagining the icon for an isometric tile? As a 2:1 ratio rhombus?

In this case, yes. It's just a foreshortened diamond drawn at 64x32. The object it's representing is a virtual 32x32 tile, projected isometrically so that its 0,0 corner (lower left) is to the viewer's left, and 32,32 is to the right.

Lummox JR