Terrain Parsing/Draw

Started by
8 comments, last by Captain P 16 years, 8 months ago
I recently changed how my game's terrain is drawn (it now parses it from a file of characters which are 1's, 2's and 3's to dictate grass, mountain and water) and it still runs. The problem, like most times, is it does not do what I want it to. :D When I run it, it displays all water, when the text file dictates all grass with a few mountains. I have a feeling that the terrainIdentifier is off, but when I error tested it with a print command, it printed 1's which should mean that grass will be drawn. Is it because of the last image I am loading that it goes screwy?

# MAIN.PY: Matt Gallivan, 2007, Terra Pugna
import pygame, sys, os
from pygame.locals import *

# -- Define DRAW functions --
def terrainDraw(terrainList):
    terrainType = pygame.image.load("mountain.png")
    terrainIdentifier = 0
    xCoordinate = 0
    yCoordinate = 0
    displayX = 768
    displayY = 1024
    n = 0
    for x in range(0, displayX, 32):
        for y in range(0, displayY, 32):
            terrainIdentifier = terrainList[n]
            if terrainIdentifier == 1:
                terrainType = pygame.image.load("grass.png")
            elif terrainIdentifier == 2:
                terrainType = pygame.image.load("mountain.png")
            else:
                terrainType = pygame.image.load("river.png")
            screen.blit(terrainType, (xCoordinate,yCoordinate))
            xCoordinate += 32
            n += 1
        yCoordinate += 32
        xCoordinate = 0
        
def windowDraw():
    window = pygame.display.set_mode((1024,768))
    pygame.display.set_caption('RPJEE')
    
# -- Define LOAD functions --
def loadImageFile( fileName, useColorKey = False ):
    try:
        image = pygame.image.load( fileName )
    except pygame.error, message:
        print "Cannot load image:", fileName
        raise SystemExit, message

    image = image.convert()

    if useColorKey is True:
        colorkey = image.get_at( (0,0) )
        image.set_colorkey( colorkey, RLEACCEL )
    return image

# -- Define PARSER functions --
def mapParser(terrainList):
    increment = 1
    while increment <= 768:
        f = open('C:/Documents and Settings/Matt/Desktop/RPJ/terrain.txt', 'r+')
        terrainList.append(f.read(1))
        increment += 1
    f.close()
    return terrainList

# -- Initialise pyGame and set up the window --
pygame.init()
windowDraw()
terrainList = []
screen = pygame.display.get_surface()
mapParser(terrainList)
terrainDraw(terrainList)
background = screen.copy()

# -- Load images and set the surfaces --
loadImageFile("hero-n.gif", True)
loadImageFile("hero-w.gif", True)
loadImageFile("hero-e.gif", True)
loadImageFile("hero-s.gif", True)
loadImageFile("grass.png", True)
loadImageFile("mountain.png", True)
loadImageFile("river.png", True)
backgroundimage = pygame.image.load("river.png")
hero_surface_n = pygame.image.load("hero-n.gif")
hero_surface_w = pygame.image.load("hero-w.gif")
hero_surface_e = pygame.image.load("hero-e.gif")
hero_surface_s = pygame.image.load("hero-s.gif")
heroimage = hero_surface_s

# -- Set user input values --
keys = {pygame.K_LEFT : False, pygame.K_RIGHT : False, pygame.K_UP : False, pygame.K_DOWN : False}
heroX = 50
heroY = 50

# -- MAIN GAME LOOP --
while True: 
    for event in pygame.event.get(): 
       if event.type == QUIT: 
          sys.exit(0)
       elif event.type == pygame.KEYDOWN:
          keys[event.key] = True
       elif event.type == pygame.KEYUP:
          keys[event.key] = False
    if keys[pygame.K_LEFT]:
        heroX -= 1
        heroimage = hero_surface_w
    if keys[pygame.K_RIGHT]:
        heroX += 1
        heroimage = hero_surface_e
    if keys[pygame.K_UP]:
        heroY -= 1
        heroimage = hero_surface_n
    if keys[pygame.K_DOWN]:
        heroY += 1
        heroimage = hero_surface_s
    screen.blit(background, (0,0))
    screen.blit(heroimage, (heroX,heroY))
    pygame.display.update()


EDIT: Changed source code since I revised the blitting in the while loop. [Edited by - Gallivan on August 12, 2007 3:01:44 PM]
Advertisement
Well turns out I had to have the numbers as strings... So now it displays grass, but it won't display the mountains still...
I didn't see where you stored the map...since I'm not a Python developer, I might have missed it completely. But shouldn't you have an array like
int[,] map[6, 6] { {1, 1, 2, 1, 3, 1},  {1, 2, 2, 1, 3, 3},  {1, 2, 1, 1, 1, 1}, {1, 2, 1, 1, 1, 1},  {2, 2, 2, 2, 2, 2},  {2, 2, 2, 2, 2, 2}}
http://neolithic.exofire.net
In map parser (where I think the problem is) it reads a .txt file which looks like:

1111211111
1112311131
etc.

And is supposed to take each of those values and place it in a list which is then read and drawn.
I commented out the map parser and went back to using a stored list of values. While it's not the prettiest thing I've seen I think I would rather code a map editor than edit .txt files by hand anyways.

Thanks for your help crayon. :D (Nice name)
Couldn't you just parse the information in a text file and then store it in your list of values? Or did I not understand you correctly?

And thanks. :D
http://neolithic.exofire.net
Well that's what I was attempting to do, but the problem (which I just discovered) was that through my means of parsing it was filling the list with 'None' values.
Ah. I see. Well, I wish I were a Python dev so I could help. :( I'm sure someone more knowledgeable will chime in.
http://neolithic.exofire.net
This appears to be more of a python scripting issue rather than some actual problem with your terrain engine.

I don't advocate cross posting but why don't you try asking in the scripting forum? I know that Kylotan the forum moderator knows a fair amount of python (rather unsurprisingly!) and someone there will actually know how to go about formatting your input file and reading the values in reliably.

Good luck

Andy

"Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile"

"Life is short, [the] craft long, opportunity fleeting, experiment treacherous, judgement difficult."

You're making a common mistake. For every tile in the map data, you're loading it's corresponding image. Now read that sentence again. If your map is 20x20 tiles, you're loading 400 images into memory - whether there's only 3 distinct images or 10. Obviously, that's a waste of memory. Just load every needed tile image once, and draw that image multiple times, once for every occurence in the map data.

Oh... it's even worse! Every time you draw the scene, you're loading these images again! Load them once, store them in some variabeles and use them throughout your program for as long as you need them. Get the idea? :)


As for your map parser, there's various things wrong or flawed in it. First, what does that magical number, 768, mean? I assume it's the size of your map-date. Don't do that! You won't remember it after a while, and you'll then wonder why your program breaks when you load in a larger map file. Also, you're opening your map file every loop cycle! Open it once, read your data from it, then close it. And another thing: you're reading characters from it, so don't check if a tile value is 0, but check if it's '0' instead.

Here's a revised version for you (and before you copy'n'paste, note that I'm using tabs, not spaces ;)):

# By passing the filename, this function becomes reusable:# you can now load different map files without changing this codedef ParseMapData(filename):	# Open the file, just once	file = open(filename)	# Create an empy array to hold our terrain data	terrain = []	# For every character that we can read from the file, do some stuff	# (the loop will stop when we reach the end of the file, so we don't	# need magical numbers here)	for char in file.read():		# A little check: lines contain an end-of-line character, and we		# don't want to store those!		if(char != '\n'):			terrain.append(char)	# We're done now, so close the file and return the terrain data array	file.close()	return terrain


I hope that helps you somewhat. Good luck! :)
Create-ivity - a game development blog Mouseover for more information.

This topic is closed to new replies.

Advertisement