Posts: 3,458
Threads: 101
Joined: Sep 2016
Could you share the Tiled map file?
It looks like they're being rendered in the right order, there's just a missing offset, and the number of tiles per row is off. I'm not sure if that info is available in the file itself, or if it needs to be calculated, and I'd like to play around with it.
Posts: 72
Threads: 14
Joined: Jul 2019
(Feb-10-2020, 07:23 PM)nilamo Wrote: Could you share the Tiled map file?
It looks like they're being rendered in the right order, there's just a missing offset, and the number of tiles per row is off. I'm not sure if that info is available in the file itself, or if it needs to be calculated, and I'd like to play around with it.
Although it is already in my first post in this thread, here you go, in it's full version. (Not meant mean!  )
NOTE: Some of the information in there is not necessary for the map to load (I think):
import pygame as pg
import pytmx
from settings import *
def collide_hit_rect(one, two):
return one.hit_rect.colliderect(two.rect)
class TiledMap:
def __init__(self, filename):
tm = pytmx.load_pygame(filename, pixelalpha=True)
self.width = tm.width * tm.tilewidth
self.height = tm.height * tm.tileheight
self.tmxdata = tm
def render(self, surface):
ti = self.tmxdata.get_tile_image_by_gid
for layer in self.tmxdata.visible_layers:
if isinstance(layer, pytmx.TiledTileLayer):
for x, y, gid, in layer:
tile = ti(gid)
if tile:
surface.blit(tile, (x * self.tmxdata.tilewidth,
y * self.tmxdata.tileheight))
def make_map(self):
temp_surface = pg.Surface((self.width, self.height))
self.render(temp_surface)
return temp_surface
class Camera:
def __init__(self, width, height):
self.camera = pg.Rect(0, 0, width, height)
self.width = width
self.height = height
def apply(self, entity):
return entity.rect.move(self.camera.topleft)
def apply_rect(self, rect):
return rect.move(self.camera.topleft)
def update(self, target):
x = -target.rect.centerx + int(WIDTH / 2)
y = -target.rect.centery + int(HEIGHT / 2)
# limit scrolling to map size
x = min(0, x) # left
y = min(0, y) # top
x = max(-(self.width - WIDTH), x) # right
y = max(-(self.height - HEIGHT), y) # bottom
self.camera = pg.Rect(x, y, self.width, self.height) Hope you can figure out my problem now. Thanks for your help!
Posts: 419
Threads: 34
Joined: May 2019
(Feb-11-2020, 06:44 PM)Piethon Wrote: Hope you can figure out my problem now. Thanks for your help! I think he's asking for the .tmx file to find out how the tile locations are expressed to figure out hoe to code the offset.
Posts: 72
Threads: 14
Joined: Jul 2019
Feb-12-2020, 06:58 PM
(This post was last modified: Feb-17-2020, 01:52 PM by metulburr.)
(Feb-11-2020, 08:47 PM)michael1789 Wrote: (Feb-11-2020, 06:44 PM)Piethon Wrote: Hope you can figure out my problem now. Thanks for your help! I think he's asking for the .tmx file to find out how the tile locations are expressed to figure out hoe to code the offset.
If I try to upload it here, it says, I can't.
So you can download it here:
https://ufile.io/e4ikmqms
Hope that is working for you!
Posts: 72
Threads: 14
Joined: Jul 2019
Hello.
I just thought, that in my code is a grid.
In my settings file, there are the following things:
WIDTH = 1024
HEIGHT = 768
TILESIZE = 64
GRIDWIDTH = WIDTH / TILESIZE
GRIDHEIGHT = HEIGHT / TILESIZE Probably I could change these numbers, to make an isometric grid. But I don't know how to change them. Do you think that could solve my problem?
Thanks for your help.
Piethon
Posts: 419
Threads: 34
Joined: May 2019
Feb-18-2020, 06:51 PM
(This post was last modified: Feb-18-2020, 06:51 PM by michael1789.)
(Feb-17-2020, 11:58 AM)Piethon Wrote: Probably I could change these numbers, to make an isometric grid. But I don't know how to change them. Do you think that could solve my problem?
I don't think so. Looking at you pics, while the individual tiles are at the proper 45degree orientation, they are blit to the screen in a straight pattern across the screen. If we look at your isometric picture and take the top as the first tile, then the next is (x =+ TILESIZE / 2, y =+ TILESIZE / 2). But your program blits at x += TILESIZE. It's just writing them across instead of at the right angle.
nilamo, might be better help with deciphering the .tmx, but I can't read it.
I think the problem needs to be fixed here:
for x, y, gid, in layer:
tile = ti(gid)
if tile:
surface.blit(tile, (x * self.tmxdata.tilewidth,
y * self.tmxdata.tileheight)) I really think there needs to be an offset figured out to put here
x * self.tmxdata.tilewidth + OFFESET What that is would be the problem. It might be simple. Just to test the theory, try this and see what it looks like.
surface.blit(tile, (x * self.tmxdata.tilewidth / 2,
y * (self.tmxdata.tileheight * 1.5) )) It think it will show a mess, but it might let us know we are on the right track. I suspect that in the end that the OFFSET will have to be a complex variable that tracks the rows and offsets the starting position, but who knows... that might fix it.
Posts: 3,458
Threads: 101
Joined: Sep 2016
The offset is definitely the way to go. I opened the map, and re-saved it using csv instead of base64, so you can see how it's organizing the tiles. The file itself has no direction whatsoever of how to format the tiles, and pytmx doesn't help there, either.
I think what you want to do, is calculate how many tiles are in each row, which you can use to determine the offset (offset is based on the width of the tiles*number of tiles), and try to format it that way. I can't test it right now, but I'll try to try it out tonight.
The file: <?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="1.3.2" orientation="isometric" renderorder="left-down" compressionlevel="0" width="16" height="16" tilewidth="64" tileheight="32" infinite="0" nextlayerid="8" nextobjectid="1">
<tileset firstgid="1" source="outdoor pack.tsx"/>
<layer id="1" name="Ground" width="16" height="16">
<data encoding="csv">
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,31,11,11,11,
11,11,11,11,11,31,11,11,13,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,31,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,13,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
</data>
</layer>
<layer id="2" name="Floor" width="16" height="16">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,175,175,175,175,175,175,175,175,0,0,0,0,
0,0,0,175,175,175,175,175,175,175,175,175,0,0,0,0,
0,0,0,175,175,172,172,172,171,175,175,175,175,0,0,0,
0,0,0,175,0,0,0,0,0,0,175,175,175,175,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,175,175,175,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="3" name="M1" width="16" height="16">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,256,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,273,0,0,0,0,0,0,111,0,0,
0,0,0,0,0,0,0,0,0,0,256,0,0,0,0,0,
0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,0,
0,0,0,0,0,0,251,0,0,0,0,0,0,0,0,76,
0,0,0,0,0,0,0,0,0,0,0,0,93,0,92,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="4" name="M2" width="16" height="16">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,230,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,263,0,0,0,0,0,0,101,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,
0,0,0,0,0,0,241,0,0,0,0,0,0,0,66,0,
0,0,0,0,0,0,0,0,0,0,0,83,0,82,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="5" name="M3" width="16" height="16">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,253,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="6" name="m4" width="16" height="16">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,243,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="7" name="m5" width="16" height="16">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
</map>
Posts: 3,458
Threads: 101
Joined: Sep 2016
Feb-19-2020, 07:06 AM
(This post was last modified: Feb-19-2020, 07:06 AM by nilamo.)
Alright, give this a shot: import pygame as pg
import pytmx
WIDTH = 1024
HEIGHT = 768
TILESIZE = 16
GRIDWIDTH = WIDTH / TILESIZE
GRIDHEIGHT = HEIGHT / TILESIZE
class TiledMap:
def __init__(self, filename):
tm = pytmx.load_pygame(filename, pixelalpha=True)
self.width = tm.width * tm.tilewidth
self.height = tm.height * tm.tileheight
self.tmxdata = tm
def render(self, surface):
ti = self.tmxdata.get_tile_image_by_gid
for layer in self.tmxdata.visible_layers:
if isinstance(layer, pytmx.TiledTileLayer):
# top left corner, is in the middle of the screen, at the top
x_start = (WIDTH / 2)
y_start = 0
x_offset = x_start
y_offset = y_start
for x, y, gid, in layer:
if x == 0:
# each new row resets the y-offset, and we back the x-offset a little more to the left
# the map is defined as left to right, then top to bottom
y_start += self.tmxdata.tileheight
x_start -= (self.tmxdata.tilewidth / 2)
y_offset = y_start
x_offset = x_start
tile = ti(gid)
if tile:
surface.blit(tile, (x_offset, y_offset))
# move the offset for the next tile
y_offset += self.tmxdata.tileheight
x_offset += (self.tmxdata.tilewidth / 2)
def make_map(self):
temp_surface = pg.Surface((self.width, self.height))
self.render(temp_surface)
return temp_surface
if __name__ == "__main__":
pg.init()
win = pg.display.set_mode((WIDTH, HEIGHT))
iso = TiledMap("iso.tmx")
running = True
while running:
for ev in pg.event.get():
if pg.QUIT == ev.type:
running = False
iso.render(win)
pg.display.flip() The map is defined in a left to right, then top to bottom fashion. So (0, 0) is the "top left" tile, which should be rendered at the very top of the window, center screen. By doing a little calculation to get the center of the window (WIDTH / 2) , all that's left is to move the offset by a tile (or half a tile, for the x-axis) to get the position of the next tile, and then reset the offsets for the next "row".
Posts: 3,458
Threads: 101
Joined: Sep 2016
...and once I actually woke up, I realized all that math can be based entirely off the indices, instead of having temporary variables. And also, that the tiles needed to be rotated 45 degrees: def render(self, surface):
ti = self.tmxdata.get_tile_image_by_gid
for layer in self.tmxdata.visible_layers:
if isinstance(layer, pytmx.TiledTileLayer):
for x, y, gid, in layer:
x_offset = (WIDTH / 2) + (self.tmxdata.tilewidth / 2 * (x+1)) - (self.tmxdata.tilewidth / 2 * (y+1))
y_offset = ((y+1) * self.tmxdata.tileheight) + (self.tmxdata.tileheight * x)
tile = ti(gid)
if tile:
rotated = pg.transform.rotate(tile.convert_alpha(), 45)
surface.blit(rotated, (x_offset, y_offset))
and mattwins like this post
|