Open evbo opened 9 years ago
Thanks for your interest with pytmx. As far as inverting the y-coordinate, there is a way to do that already (has partial support). Pass 'invert_y=True' to whatever loader or to the TiledMap constructor. That value will be saved in the TiledMap instance. I think the proper solution would be to modify TiledTileLayer.parse_xml to be inverted_axis aware. That would be somewhere around here: https://github.com/bitcraft/PyTMX/blob/master/pytmx/pytmx.py#L916 It would remove the need for a special loader and all data access would be flipped. Of course, then the data in memory will be flipped as well. Thoughts?
tmx_data = pytmx.TiledMap(..., invert_y=True)
As far as image loading goes, there is another approach to image loading that you may be interested in. You can define a function to load images, without resorting to subclassing...pass an argument to the TiledMap constructor. Please see the link below for more information: https://github.com/bitcraft/pytmx#custom-image-loading
What graphics library are you using now? ...just curious.
thanks, the built-in invert_y
argument looks promising and it appears to only need a simple fix:
line 316 - 317 of pytmx.py:
if self.invert_y:
o.y -= tileset.tileheight
should be:
if self.invert_y:
o.y = tileset.height - tileset.tileheight - o.y
However, this code never actually runs for me because self.objects
is empty since my Tiled tmx file does not contain objectgroup
s.
In otherwords, for me self.objects
is empty since none of my layers are the expected instance on line 629:
if isinstance(layer, TiledObjectGroup))
Also, I am already using the image_loader approach you recommend. See my original comment, with the only difference being that I subclass in order to pass the current tileset. It is necessary to know the current tileset in order to get height
and tileheight
information. I need to subclass so that reload_images
passes the current tileset to the image_loader
function.
I guess I'm confused here. Does your graphics lib require a flipped tileset image? Could you tell me what graphics lib you are using? That would help me out a lot here. Any code that you've already created would be nice, too. I'd like to see what you are doing, and how I can make pytmx better with your contributions. Thanks.
Sorry, forgot to mention I am using the Python framework Kivy. It displays content assuming y=0 is at the bottom of the page (hence why I must change content at the top of the page to have y>0)
Awesome! I'm a big fan of kivy. I've gotten a few requests for ivy support now, I suppose I should do something about it. It would be a great help if you could send your changes in a PR (or diff/paste), so I have somewhere to start.
Sorry, I'm not too familiar with git hub but here is a working example with Kivy and Tiled tmx:
from kivy.uix.widget import Widget
from kivy.properties import StringProperty
from kivy.core.image import Image as CoreImage
from kivy.uix.image import Image
from pytmx import TiledMap
class TileGrid(Widget):
"""Creates a Kivy grid and puts the tiles in a KivyTiledMap in it."""
map_file = StringProperty('path\to\tmx.tmx')
def __init__(self, **kwargs):
self.map = OpenGLTiledMap(self.map_file)
# self.map = TiledMap(self.map_file, invert_y=True)
super(TileGrid, self).__init__(
rows=self.map.height, cols=self.map.width,
row_force_default=True,
row_default_height=self.map.tileheight,
col_force_default=True,
col_default_width=self.map.tilewidth,
**kwargs
)
layer = self.map.get_layer_by_name('ground')
max_y = len(layer.data)
for (x, y, ts_props) in layer.tiles():
tileset_fname = ts_props[0]
(tx, ty, tw, th) = ts_props[1]
texture = CoreImage(tileset_fname).texture.get_region(
tx, ty, tw, th)
y = max_y - y
pos = (x*tw, y*th)
image = Image( texture=texture,
texture_size=(tw, th),
pos=pos)
self.add_widget(image)
class OpenGLTiledMap(TiledMap):
def reload_images(self):
def GL_image_loader(filename, flags, **kwargs):
""" convert the y coordinate to opengl format where
the bottom-most coordinate in the image is 0
"""
ts = self.fname2ts[filename]
def load((x,y,w,h)=None, flags=None):
GL_y = ts.height - ts.tileheight - y
return filename, (x,GL_y,w,h), flags
return load
self.fname2ts = dict((ts.source, ts) for ts in self.tilesets)
self.image_loader = GL_image_loader
super(OpenGLTiledMap, self).reload_images()
from kivy.app import App
from kivy.base import EventLoop
EventLoop.ensure_window()
class MyApp(App):
def build(self):
layout = TileGrid()
return layout
MyApp().run()
No worries! Thanks so much for sharing that. I will take a look at it later today.
Any news on this?
How about simply passing tileset object into image_loader? (see #72). This approach still requires manually converting y axis coordinate inside the loader, but it provides all necessary data required to do the math. You can use it this way: https://gist.github.com/labuzm/6ee08adfa64e6dc6e4e0 This also wouldn't break anything.
Iabuzm, I've been busy with other projects at the moment, but I will look into your proposal. Thanks for your suggestions, I will check back when I get time.
helo i am on a project and i need to use pytmx i need pytmx support for kivy today itself plz
Hi thanks for your interest. I haven’t worked with kivy compatibility lately. Have you tried the code that is in this thread?
yes but i am getting some errors in this part of the code
def load((x,y,w,h)=None, flags=None):
can you give me a clean code from that
when i am using opengltilemap class its working fine
but when i am using your code
self.map = TiledMap(self.map_file, invert_y=True)
i am getting the image
its displaying another image in my directorythat i used in that tmx file
i am not giving up on pytmx because i love pytmx with pygame
and the first image is correct i made i test tmx it worked with the opengltiled class in the thread
but not working with your way of coding i love that neet
bythaby this is the only image i am using
and i am a student at 13 years sorry to ask this much questions wasting your time i would like to know how to scale our scrolling tmx file accourding to the window
looks pretty good so far. one thing i notice is that the images don't seem to align with the tiles. that looks like the margin or spacing of the tileset isn't set or being used properly. if you can share the map and code you are using, i could help you get this fixed. as for scrolling, you would have to rely on Kivy to do that...its been a long time since i've used it so i don't have a good idea for that right now.
When displaying tiles in OpenGL formatted coordinate systems (y=0 occurs at bottom of page instead of top of page), there is a simple transformation needed to ensure data appearing at the top of the page has coordinates starting from max(y) rather than 0. Would it make sense to incorporate an image loader that handles this simple, yet common transformation?
See below where I had to subclass TiledMap and override the
reload_images
method just to set theimage_loader
to one that sets the y ordinate based on the currenttileset
'stileheight
andheight
. Is there a cleaner, more future-version-compatible-robust way for loading images with correct coordinates for OpenGL displays?Also, this issue comes up again after you've loaded the images from the tileset and now need to play them as widgets in your OpenGL display window. Again, the conversion is needing to know
tileset
specific dimensions. Is there a convenient way to look this up?For instance, I do something kinda ugly like this: