简体   繁体   中英

Creating/Importing A Custom Map in Python using Libtcod?

I have been in the works of creating a Roguelike in Python, using Libtcod!

However, one of my major hurdles that i have been faced with - is that i have absolutely no idea how to make a CUSTOM map (as in, i define the cells and what elements they entail) OR, if it's possible - How you import a custom map into Python using Libtcod.

As of right now, i am using a definition that essentialy renders the map after certain patterns (number of rooms, no intersections etc.) - But i wish to make it so that i can import a already custom made map - Or actually just made a definition for one, so i can load it in given certain criterias.

Any help on this subject would be greatly appreciated, thanks! :)

There are lots of interesting ways you can import map data into your program.

Typically, with a roguelike, you would generate that data. Though, of course, this isn't strictly necessary.

A pretty basic way of generating would be to try out libtcod's heightmap toolkit. This is extracted from a game I've written, and might give you a decent idea how to approach the problem. This code is extracted from my Map class:

import random
import libtcodpy as libtcod
class Map
  def __init__(self,w,h) :

    self.width = w
    self.height = h

    self._hm = libtcod.heightmap_new(w,h)
    self._cells = []
    self.initMap()

  def initMap(self) :
    print "Initing map"
    for y in range(self.height) :
      for x in range(self.width) :
        c = cell.Cell(x,y)
        self._cells.append(c)
    self.resetMap()
    return

  def resetMap(self):
    print "Resetting map"
    for y in range(self.height) :
      for x in range(self.width) :
        self._cells[x + y * self.width].reset()
    ## Heightmap generation
    self.randomizeHeightmap()

    for y in range(self.height) :
      for x in range(self.width) :

        alt = libtcod.heightmap_get_value(self._hm, x, y)
        self._cells[x + y * self.width].dig(alt > 1)

  def randomizeHeightmap(self) :
    print "Setting up heightmap"
    hills = 1000
    hillSize = 7

    halfX = self.width / 2
    halfY = self.height / 2
    libtcod.heightmap_clear(self._hm)
    for i in range(hills) :
      size = random.randint(0,hillSize)

      hillX1 = random.randint(0,halfX - hillSize / 2)
      hillY1 = random.randint(0,self.height)

      hillX2 = random.randint(halfX + hillSize / 2, self.width)
      hillY2 = random.randint(0,self.height)

      libtcod.heightmap_add_hill(self._hm,hillX1, hillY1, size, size)
      libtcod.heightmap_add_hill(self._hm,hillX2, hillY2, size, size)

    libtcod.heightmap_normalize(self._hm, 0.0, 2.0)
[...]

Note I'm not using libtcod's map functionality here. You certainly can, and that would allow you to use the built in Field of View toolkit as well (which is pretty awesome!).

The Cell class's dig method accepts a boolean value to determine whether or not the cell is passable. After the heightmap is generated, I normalize it so it only contains values of 0, 1, and 2. Then I just make any corresponding cell that ended up with an "altitude" of 2 a wall, and 1 or 0 an opening. This gave me a good balance to work with.

The heightmap functions are great for creating an organic sort of layout, with round features, rather than the typical square-roomed dungeons often seen in roguelikes.

If you're looking to generate more traditional dungeons, there is a BSP toolkit included with libtcod that is designed exactly for this task. See the documentation for it here .

There's also an incredible python tutorial which has a dedicated map section here .

I've used other methods in the past, including, but not limited to reading each pixel in a simple .bmp image and interpreting the rgb values, each indicating something different about the given coordinate in the map (red might be wall/open, blue might indicate the presence/absence of a roof, etc).

The basic idea, though, is to just have an array of coordinates. It may be as simple as an array or integers, where 0 means passable, and 1 means a wall, or, as in my case, an array of objects that also store some other information that'd be useful for your game.

You can use a 2-d array (this is quite a bit more easy to wrap your head around, sometimes, as you would refer to the coordinates like map[x][y] rather than map[x + y*width] ) rather than the single-dimension array that I've used in the example code.

The world is your oyster! :) Just get that data into a structure that you can read it out of, then examine the coordinate you're interested in.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM