#!/usr/bin/python """ Coral by Kris Schnee. A tiled graphics engine. Serves as an example of a minimal scrolling-tile engine. """ ##___________________________________ ## ~Header~ ##___________________________________ __author__ = "Kris Schnee" __version__ = "2008.1.27" __license__ = "Public Domain" ##___________________________________ ## ~Imported Modules~ ##___________________________________ ## Standard modules. import os import random ## Third-party modules. import pygame ## My modules. try: import art except: print "Showing off some placeholder tiles, since the art module wasn't found." class DemoArt: def __init__(self): w = pygame.surface.Surface((64,64)) w.fill((0,64,200)) s = pygame.surface.Surface((64,64)) s.fill((225,225,32)) g = pygame.surface.Surface((64,64)) g.fill((16,200,16)) self.tiles = {"water":w,"sand":s,"grass":g} art = DemoArt() ##___________________________________ ## ~Constants~ ##___________________________________ SCREEN_SIZE = (800,600) TILE_SIZE = 64 DEFAULT_ZONE_SIZE = (100,100) ##___________________________________ ## ~Classes~ ##___________________________________ class TileEngine: """Displays a scrolling array of 2D tiles.""" def __init__(self,**options): self.tile_size = options.get("tile_size",TILE_SIZE) self.zone_size = options.get("zone_size",DEFAULT_ZONE_SIZE) """Viewport: The surface to draw to. Normally the screen; can be a subsurface.""" self.viewport = options.get("self.vieport",screen) """Tilemap: a 1D array of references to tile surfaces. Start with random data. This paragraph uses the "art" module imported above, and assumes the existence of a set of pre-loaded tiles. """ self.tilemap = [] terrains = ["water","water","water","sand","sand","grass"] for n in range(self.zone_size[0] * self.zone_size[0]): terrain = terrains[random.randint(0,len(terrains)-1)] self.tilemap.append(art.tiles[terrain]) """Camera: Where is the upper-left corner of the tilemap segment to draw?""" self.camera_location = [0,0] ## How many tiles can this screen hold? self.tiles_drawable = ((screen.get_width() / TILE_SIZE)+2, (screen.get_height() / TILE_SIZE)+2) def SetViewport(self,surface=None): if not surface: surface = screen self.viewport = surface def Scroll(self,x=0,y=0,absolute=False): """Instantly scroll the screen.""" if absolute: self.camera_location = [x,y] else: self.camera_location[0] += x self.camera_location[1] += y def DrawLandscape(self): """Display part of the tilemap.""" upperleft_tile = [ int(max(0,self.camera_location[0] / TILE_SIZE)), int(max(0,self.camera_location[1] / TILE_SIZE)) ] """Now, figure out what range of tiles should be drawn in the landscape. If that range goes outside the zone, then it's time to get data from another zone, loading it if needed. Instead, for now at least I'm going to show black space outside the zone.""" self.range_of_tiles_drawn = (upperleft_tile[0], upperleft_tile[1], min(upperleft_tile[0] + self.tiles_drawable[0], self.zone_size[0]-1), min(upperleft_tile[1] + self.tiles_drawable[1], self.zone_size[1]-1) ) for x in range(self.range_of_tiles_drawn[0],self.range_of_tiles_drawn[2]): for y in range(self.range_of_tiles_drawn[1],self.range_of_tiles_drawn[3]): draw_pos = ((x*self.tile_size)-self.camera_location[0], (y*self.tile_size)-self.camera_location[1]) self.viewport.blit( self.tilemap[y*(self.zone_size[1]-1)+x],draw_pos ) ##___________________________________ ## ~Functions~ ##___________________________________ ##__________________________________ ## ~Autorun~ ##__________________________________ screen = pygame.display.set_mode(SCREEN_SIZE) if __name__ == "__main__": ## Run a demo. c = TileEngine() for n in range(50): c.DrawLandscape() c.Scroll(10,2) pygame.display.update()