Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Isometric Layering offset not happening? #74

Closed
SuckyNoob opened this issue May 16, 2017 · 22 comments
Closed

Isometric Layering offset not happening? #74

SuckyNoob opened this issue May 16, 2017 · 22 comments

Comments

@SuckyNoob
Copy link

Hey again.

So got everything into my project and working.

However when I load my map in it seems that it is drawing all the layers on the first floor layer. Instead of taking in the offsets I set up inside Tiled. (For Height and Depth Effect)

Is this how it's supposed to work? Am I supposed to set up the offsets in my code? Or are the layers supposed to be rendered as they are in Tiled without needing to write anything for that, and I'm doing something wrong?

Thanks for your time.

@fallahn
Copy link
Owner

fallahn commented May 16, 2017

To be honest this sounds like a bug. The map should be rendered as it appears in Tiled by default. It is possible that you are using newer, unsupported features - the map loader only supports Tiled up to 0.9 iirc, whereas Tiled is up to 0.18 now

@SuckyNoob
Copy link
Author

Where in the library could I go about adding that code to support the features?

@SuckyNoob
Copy link
Author

SuckyNoob commented May 16, 2017

It would seem what I'm talking about was added in 0.4 Tiled.

https://github.com/bjorn/tiled/blob/0.9/NEWS
0.4.0 (30 January 2010)

  • Added support for isometric maps
  • Added automatic reloading of tileset images when they change
    Added Offset Map action that can shift a set of layers by a certain amount
  • Added a fill tool
  • Added ability to duplicate map objects
  • Added support for choosing the tile layer data format used when saving
  • Added mouse wheel zooming support to the tileset view
  • Added an object display color attribute to object groups
  • Added ability to edit tile properties through a context menu
  • Made writing out a DTD reference optional and disabled it by default
  • Made translations functional
  • Updated Dutch, Portuguese, Spanish and German translations

It's almost as if the layers are all locked into place. They all render, and in proper order. They just dont take into account the offset.

Or are you saying that the .tmx that the latest version of Tiled saves as might be different and incompatible with tmxloader?

@fallahn
Copy link
Owner

fallahn commented May 16, 2017

Looks like I never added support for it. You'll probably want to start by parsing the node property here, then add it to a new property in the Layer class and use it to draw the offset

@SuckyNoob
Copy link
Author

SuckyNoob commented May 16, 2017

Thanks so much man! Awesome thing you made here. Been reading your blog too.

There a way to contact you by email or just here?

@SuckyNoob
Copy link
Author

SuckyNoob commented May 16, 2017

Just trying to figure out where to put the property now for the drawing. Is that in MapLayer I need to change the draw method? I already parsed the node properties.

edit*

Such as this?

void LayerSet::draw(sf::RenderTarget& rt, sf::RenderStates states) const
{
//std::vectorsf::Int32 dirtyPatches; //TODO prevent patches being duplicated
for(const auto& q : m_dirtyQuads)
{
for(const auto& p : q->m_indices)
{
m_patches[q->m_patchIndex][p].position += q->m_movement; //<<<<<< add offsets here?
m_patches[q->m_patchIndex][p].color = q->m_colour;
}

@fallahn
Copy link
Owner

fallahn commented May 16, 2017

To be honest I can't remember exactly what that bit does :) If you have the offset available in the draw function you can try modifying the states transform here by adding:

states.transform.translate(offset.x, offset.y);

@SuckyNoob
Copy link
Author

SuckyNoob commented May 16, 2017

Thanks again, I guess I don't have it available in the draw function yet. I will work on that, haven't figured it out. I haven't used translate and transforms yet in SFML. I'm guessing I need to somehow make the offsety and offsetx that were parsed, into the offset.x and offset.y. I am the suckiest noob after all. No formal education in this stuff. :P

Wish me luck!

@SuckyNoob
Copy link
Author

SuckyNoob commented May 17, 2017

I guess I was wrong. Custom Layer offsets weren't added til .14 of Tiled.

You said development of tmxloader is ended indefinitely? Was going to ask how much it costs to get you to add a feature, through that patreon.

Still working on adding it myself however :P

Could you possibly tell me the difference between the MapLoaderPublic vs MapLoaderPrivate .cpps? And why there is a MapLoader.h and a MapLoader.hpp? If you have the time.

@SuckyNoob
Copy link
Author

SuckyNoob commented May 18, 2017

Is there a way to share with you what I've changed? I am new to this github stuff.

Maybe get your input on it? It compiles and everything but for some reason the layers still don't move, I must be missing something minor.

edit** I just saw your TMXlite will do isometric orientation. I thought I read it only did orthogonal :P. Going to try again to make that work.

@fallahn
Copy link
Owner

fallahn commented May 18, 2017

Hi
Yes, I'm afraid I'm unlikely to do any more work on this project, it's actually very badly made and pretty much beyond redemption, hence its deprecation in favour of tmxlite.

If you want to share your changes, however, I'll happily review them. The general github workflow is to first make a fork of the repository, which creates a copy under your own username. You may then clone it, makes changes, then push those changes back to your fork. When this is done you can do side by side comparisons of changes with the original, and submit 'pull requests' whereby I can choose to accept a change and 'pull' those into the original repository.

tmxlite will indeed parse all the information you're looking for, but I should point out that the example renderer does only support orthogonal maps. It's shouldn't be too much of a stretch to adapt it, however. The idea behind tmxlite is to separate the parsing of map files from the rendering. You'll end up with a map object which is effectively a C++ representation of the xml file. You can then use this data to draw the maps as best suits the framework you are using. This is why there are two examples included, one for sfml, and one for SDL2. If you're having difficulty building tmxlite there are binaries for visual studio for download under the 'releases' tab.

@SuckyNoob
Copy link
Author

SuckyNoob commented May 18, 2017

Ah okay. Thanks for the lesson on github workings. I actually found those releases last night looking through your blog. I have tmxlite working now.

The map loads, but I can't get the layers to draw yet. I will get it to work though.

@fallahn
Copy link
Owner

fallahn commented May 18, 2017

Good to hear!

Personally I've never tried drawing non-orthogonal maps so I can't say for sure, but I'd assume it's a matter of correctly setting up the points of the vertex array to match the tiles, in which case you probably want to start here. The other thing worth bearing in mind is to add the vertices in the correct order (top down?) so that the tiles overlap properly if they need to. Once you get isometric maps working I'd love to see it so I can add it to the examples! ;)

@SuckyNoob
Copy link
Author

SuckyNoob commented May 21, 2017

Hey, back finally. Alright will do once I get it working.

Maybe you could help me out. It seems the example renderer has quite a bit to it. The map is split into "chunks"? I imagine so that there can be large or perhaps endless maps?

I'm having trouble pinpointing exactly where I need to place things because it's not as straight forward as I'm, used to.

For Isometric without layers I need to fit code that looks like this.

`
void Map::draw(sf::RenderWindow& window, float dt)
{
for (int y = 0; y < this->height; ++y)
{
for (int x = 0; x < this->width; ++x)
{
//Set the position of the tile in the 2d world
sf::Vector2f pos;
pos.x = (x - y) * this->tileSize + this->width * this->tileSize;
pos.y = (x + y) * this->tileSize * 0.5;
this->tiles[y*this->width + x].sprite.setPosition(pos);

		// Draw the tile
		this->tiles[y*this->width + x].draw(window, dt);
	}
}
return;

}
`

That would be the code I have made for isometric without layers for a custom map format in binary.

Now I came across this, someone had been kind enough to show me how they get Z layers inside their game. And it would be akin to this.

`
for (int y = 0; y < viewModelMap.GetLength(1); y++)
for (int x = viewModelMap.GetLength(0) - 1; x >= 0; x--)
for (int z = viewModelMap.GetLength(2) - 1; z >= 0; z--)

                    if (viewModelMap[x, y, z] != -1)
                    {
                        int xPos = -(x * (Tileset.TileSize / 2));
                        int yPos = -(y * (Tileset.TileSize / 2));
                        int zPos = -(z * (Tileset.TileSize / 2));
                        int xPosition = -(xPos - zPos);
                        int yPosition = (xPos / 2) + (zPos / 2) + yPos;
                        
                        spriteBatch.Draw(Tileset.GetTileSprite(viewModelMap[x, y, z]), new Vector2(xPosition, yPosition) + Position);

                    }

`

So this second snippet will do layers.

But seeing as the render example you have is split up between chunks and such. I am not quite sure where to place this code/where to get started.

You say start with the vertex array?

@SuckyNoob
Copy link
Author

Not quite sure why those snippets didn't post properly...?

@fallahn
Copy link
Owner

fallahn commented May 22, 2017

The chunks are there for performance reasons - it basically splits the layer into smaller parts so that there are only 1-4 chunks per layer drawn at any time, depending on what's visible for the current view. Of course if there are two layers visible the count jumps to 2-8 and so on. You should be fine to leave that as it is, and concentrate on where the tile quads are added. Like I say I've not done isometric rendering myself, but I should imagine it's only a case of making the vertices rectangular per tile, rather than square, or perhaps even diamond shaped to match the tile. Adding the vertices to the vertex array and drawing the arrays/chunk should stay the same (unless there's some special case I'm not aware of).

To post code snippets in markdown each line must begin with at least 4 spaces. I've found this page is worth bookmarking ;)

@SuckyNoob
Copy link
Author

SuckyNoob commented May 23, 2017

Alright so I think I've figured it out. The vertexes I don't think I need to change because it just takes in the parsed values for tileSize x and y. So it's just the tileOffset I need to change.

edit* erased what I wrote before. Realized it was something I had done when generation the tmx file. Still working on that offset though.

@SuckyNoob
Copy link
Author

SuckyNoob commented May 26, 2017

Hey again.

So I've almost got it working changing around that orthogonal example. The map loads, not sure if the offsets are working exactly but I am thinking that isn't the problem. The tile sizes also correctly parse and load.

I put some couts in there to tell me what was going on. The offsets are definitely wonky but I think it has more to do with the "chunk" system you have in there (which I want to keep to see how it works).

You said you didn't write Isometric before? (I am still using tmxlite)
Did someone else add this to your tmxloader?

https://github.com/fallahn/sfml-tmxloader/blob/master/src/MapLoaderPrivate.cpp#L706
https://github.com/fallahn/sfml-tmxloader/blob/master/src/MapLoaderPrivate.cpp#L170
https://github.com/fallahn/sfml-tmxloader/blob/master/src/MapLoaderPublic.cpp#L178-L184

^^^ When I had tmxloader working before (albeit without the Layer Offsets) it rendered isometric great. Just didnt have those offsets. I like your Tmxlite too it is definitely more flexible, so I'm going to stick with it.

So for that chunk system. In your example renderer.

https://github.com/fallahn/tmxlite/blob/master/SFMLExample/src/SFMLOrthogonalLayer.hpp#L63-L83

(I'm trying to get this to work before attempting to write my own loader with your tmxlite parser, though I'd say it works great when I tested it for orthogonal)

So in that code for splitting it up into chunks. The cout on the last line there does print to the console telling me it's an invalid map.

Will I have to apply the same math to how the "chunks" are created as I did to the layer/tiles and their offsets? Like is that "chunk" system set up for Orthogonal at the moment and I'll have to change it too to render the tiles?

@SuckyNoob
Copy link
Author

SuckyNoob commented May 26, 2017

This is what I've changed so far. If you want to see. It's the header file I just renamed it from IsometricLayer.h to what you see there to get it into a txt file.

IsometricLayerDOTh.txt

The changes I tried to make to the tileOffset and such is down by where the Vertexes are created like you pointed out before, starting at around Line 111 if you turn that into a header file or throw it in Sublime text or something. I actually tried a fiew different ways of making the tile offset including the one u had in tmxloader, which I think is the one uncommented now. I had some others that arent commented in but it looks like I deleted them.

@SuckyNoob
Copy link
Author

Also here.

https://github.com/fallahn/tmxlite/blob/master/SFMLExample/src/SFMLOrthogonalLayer.hpp#L279-L301

Will I need to change some stuff around in there to get it to render properly?

@fallahn
Copy link
Owner

fallahn commented May 27, 2017

Did someone else add this to your tmxloader?

Yeah the tile flipping was contributed by someone else - you'll have to check the file history to find out who :)

The chunk system works something like this: It starts with a fixed size - in this case 1024x1024. It then looks at the tile size, divides the current size by that, then rounds it to the nearest whole tile (there's actually an open issue with this right now). Once it has calculated the chunk size the renderer calculates as many vertex arrays needed to create all the chunks it needs to draw the entire map. A chunk also has a global bounds of chunkSize which the renderer can then use to check whether or not it intersects the current view.

I think the problem you'll have with isometric maps is that tiles aren't square - which the chunk calculation assumes. You'll need to update it to calculate both the width and the height of the chunk accordingly - as opposed to assuming the height is the same as the width, which it does currently.

@SuckyNoob
Copy link
Author

SuckyNoob commented May 28, 2017

Thanks!

I'm reeeally close now, even have the tileoffsets working properly. Still can't see them though. The last sentence you wrote is exactly what I need to do.

Could you by any chance highlight the section of code that calculates the chunks like the entire "scope", like the part I need to change? I am having difficulty pinpointing it (Noobishness)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants