Creating 2D Hexagonal Tile Map

Hi everyone,

I finally got Panda3D compiling and working on OS X, and I’ve been reading through the manual. I am hoping I can get some feedback on what I am planning to do…

I want to create a 2D map composed of hexagonal tiles. I am thinking of doing the following:

  • Locking the camera in a top down position, and arranging the tiles as if they were on a flat surface

  • There will be many of these maps, each unique in the arrangement of the tiles.

  • The maps themselves cannot be stored on the user’s computer.

  • The hex tiles will be the only 3D objects, and each tile will receive one of several textures.

  • All information about the tiles and map will be stored on the server

I am thinking that I can either model a tile using 3D software and just create one where appropriate, or I can dynamically model a hexagon using Panda. Any recommendations on which way to go?

I should construct the maps on the server (each tile’s x/y coords, texture, etc), and just send the information to the client, which will then create and display the map.

Another way might be to model the terrain as one piece, and somehow break it up into tiles? I don’t really have any idea how to go about doing this…

The maps will consist of perhaps 50-300 tiles, but there will be little to no animation (at least for now) or other 3D models. Will there be performance problems if I do each hex as a seperate model?

Any thoughts are greatly appreciated!

Thanks,
Kuros

doesnt really make a huge difference. do what you’r more comfortable with.
given the fact that modellers and exporters tend to loose some precision and might cause grafical glitches at the borders of tiles. so it might be better to create them with panda. note that you can save meshes you use in panda to disk again.

with 50 to 300 it might still just work with seperate models, but you would waste a lot of performance. if there is no animation on it just grep a bunch of meshes which are close together and call flattenStrong() on them. dont flatten all of them into one mesh.
flattenStrong can, especially in your case , boost performance a lot. see the chapter in the manual about it.

  • i dont think you are right on this Thomas.
  • This is totally bad advice i think.

just getting the “map” node (where all the tile parent to) and calling flattenStrong() should do. FlattenStrong finds models with common textures and flattens them correctly.

I would not worry about performance there is far more harder problem like actually making the game…

well i experienced problems when exporting single tiles from blender.they where supposed to fit perfectly but you could see glitches. the background appeared a little since the vertices didnt match 100% on the borders. in such a case it might be more accurate to generate the tiles inside panda.

Yeah you might be right after trying it. But then on the other hand i would want to the tiles to over lap (so that they blend a little) with all kind of little tricks not just the ground plate but the trees and house mountains or roads…

any ways if you want 3d tiles get the code here:

treeform.p3dp.com/p/tiles/tiles.zip

hehe, forgot tiles can be rotated :slight_smile:

import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.task.Task import Task
import random 

tilesEgg = loader.loadModel("tiles.egg")

plain = tilesEgg.find('**/plain')
city = tilesEgg.find('**/city')
hill = tilesEgg.find('**/hill')

tiles = [plain,plain,plain,plain,city,hill,hill,hill]
print tiles

map = NodePath('map')
map.reparentTo(render)
for x in xrange(-15,15):
    for y in xrange(-15,15):
        tile = random.choice(tiles)
        tile.copyTo(map)
        tile.setPos(.75*(x*2),.8*(x%2+y*2),0)
        tile.setH(tile.getH()+60*random.randint(0,6))
map.flattenStrong()       
run()

Thanks so much for the code, it is quite helpful. I’m actually terrible at modeling…I couldn’t even model a hex tile. =)

Thanks again. I’m sure I’ll have more questions as I go along.

-Kuros

Any idea why I ALWAYS have 3 tiles blank?

The first tile is always blank, then most of the time tile 2 is blank, then one other tile in the first collum is blank.

It looks like the first hex of each type is blank. Why would this happen?

Sammual

P.S. I am running

import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.task.Task import Task
import random 

tilesEgg = loader.loadModel("tiles.egg")

plain = tilesEgg.find('**/plain')
city = tilesEgg.find('**/city')
hill = tilesEgg.find('**/hill')

tiles = [plain,plain,plain,plain,city,hill,hill,hill]
print tiles

map = NodePath('map')
map.reparentTo(render)
for x in xrange(-15,15):
    for y in xrange(-15,15):
        tile = random.choice(tiles)
        tile.copyTo(map)
        tile.setPos(.75*(x*2),.8*(x%2+y*2),0)
map.flattenStrong()       
run()

One observation. Try replacing:

tile.copyTo(map)

with:

tile = tile.copyTo(map)

The former makes a copy of the tile and parents the copy to map, but the variable “tile” still contains a reference to the original tile.

The latter variation is necessary in order to make your subsequent tile.setPos() call make sense.

David

Thanks David. That was it.

Sammual

Maybe one little note. If you have a really large map, you should not call to flattenStrong on map directly. First create some empty nodes at position 0, 5, 10, 15, … (choose this values carefully) then add your tiles to this nodes and call flattenStrong only on this empty nodes. This way the engine can cull away nodes that are not visible. If you flattenStrong the map, Panda3D has to draw the whole map, even if you can’t see 99% (If you don’t understand I’ll try to extend the example).

map = render.attachNewNode("Map")
for sectorx in range(-10, 10):
    for sectory in range(-10, 10):
        sector = map.attachNewNode("Sector")
        sector.setPos(sectorx * TODO, sectory * TODO, 0.0)
        for x in range(-5, 5);
            for y in range(-5, 5):
                tile = TODO
                tile.reparentTo(sector)
                tile.setPos(x * TODO, y * TODO, 0.0)
        sector.flattenStrong()

Im using this code for my 2d tile engine:


import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import Point2,Point3,Vec3,Vec4
from direct.task.Task import Task
from math import sin, cos, pi
import cPickle, sys

import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.task.Task import Task
import random

def loadObject(tex = None, pos = Point2 (0,0), depth = 100, scale = 10,
transparency = True):
obj = loader.loadModel(“Models/plane”)
obj.reparentTo(camera)
obj.setPos(Point3(pos.getX(), depth, pos.getY()))
obj.setScale(scale)
obj.setBin(“unsorted”, 0)
obj.setDepthTest(False)
if tex:
tex = loader.loadTexture(“Textures/”+tex+".png")
obj.setTexture(tex, 1)

return obj

class mygame(DirectObject):
def init(self):

gras = loadObject("grass", scale = 5,transparency = False)
bocht = loadObject("road2", scale = 5,transparency = False)

tiles = [“gras,gras, bocht, bocht, bocht, bocht, bocht, gras”]
print tiles

map = NodePath(‘map’)
map.reparentTo(render)
for x in xrange(-15,15):
for y in xrange(-15,15):
tile = random.choice(tiles)
tile.copyTo(map)
tile.setPos(.75*(x2),.8(x%2+y*2),0)
map.flattenStrong()

q = racegame()

run()

But I still get this error : ‘str’ object has no attribute ‘copyTo’. How can I fix this?