I'm working with Panda3d and recently switched my game to isometric rendering. I moved the virtual camera accordingly and set an orthographic lens. Then I implemented the classes "Map" and "Canvas".

A canvas is a dynamically generated mesh: a flat quad. I'm using it to render the ingame graphics. Since the game itself is still set in a 3d coordinate system I'm planning to rely on these canvases to draw sprites. I could have named this class "Tile" but as I'd like to use it for non-tile sketches (enemies, environment) as well I thought canvas would describe it's function better.

Map does exactly what it's name suggests. Its constructor receives the number of rows and columns and then creates a standard isometric map. It uses the canvas class for tiles. I'm planning to write a map importer that reads a file to create maps on the fly.

Here's the canvas implementation:

    class Canvas:
    def __init__(self, texture, vertical=False, width=1,height=1):
        
        # create the mesh         
        format=GeomVertexFormat.getV3t2()
        format = GeomVertexFormat.registerFormat(format)
        vdata=GeomVertexData("node-vertices", format,  Geom.UHStatic)
        
        vertex = GeomVertexWriter(vdata, 'vertex')
        texcoord = GeomVertexWriter(vdata, 'texcoord')

        # add the vertices for a flat quad
        vertex.addData3f(1, 0, 0)
        texcoord.addData2f(1, 0)
        vertex.addData3f(1, 1, 0)
        texcoord.addData2f(1, 1)
        vertex.addData3f(0, 1, 0)
        texcoord.addData2f(0, 1)
        vertex.addData3f(0, 0, 0)
        texcoord.addData2f(0, 0)
        
        prim = GeomTriangles(Geom.UHStatic)
        prim.addVertices(0, 1, 2)
        prim.addVertices(2, 3, 0)
        
        self.geom = Geom(vdata)
        self.geom.addPrimitive(prim)
 
        self.node = GeomNode('node')
        self.node.addGeom(self.geom)
        
        # this is the handle for the canvas
        self.nodePath=NodePath(self.node)
        
        self.nodePath.setSx(width)
        self.nodePath.setSy(height)
        
        if vertical:
            self.nodePath.setP(90)
        
        # the most important part: "Drawing" the image
        self.texture=loader.loadTexture(""+texture+".png")
        self.nodePath.setTexture(self.texture)

Now the code for the Map class

    class Map:
    def __init__(self,rows,columns,size):
        self.grid=[]
        for i in range(rows):
            self.grid.append([])
            for j in range(columns):
                
                # create a canvas for the tile. For testing the texture is preset
                tile=Canvas(texture="../assets/textures/flat_concrete",width=size,height=size)
                x=(i-1)*size
                y=(j-1)*size
                
                # set the tile up for rendering
                tile.nodePath.reparentTo(render)
                tile.nodePath.setX(x)
                tile.nodePath.setY(y)
                
                # and store it for later access
                self.grid[i].append(tile)

And finally the usage

        def loadMap(self):
            self.map=Map(10, 10, 1)

this function is called within the constructor of the World class. The instantiation of world is the entry point to the execution.

The code is pretty straightforward and runs good. Sadly the output is not as expected:

![isometric ?][1]

Please note: The problem is not the white rectangle, it's my player object. The problem is that although the map should have equal width and height. With orthographic rendering I expected the map to be a perfect square.


**What did I do wrong ?**


  [1]: https://i.sstatic.net/eV35E.png