Source

BASIC-RoBots / src / worldmap.py

##
## worldmap.py for BASIC-RoBots
## 
## Copyright (C) 2012 Pierre Surply
## <pierre.surply@gmail.com>
##
## This file is part of BASIC-RoBots.
##
##    BASIC-RoBots is free software: you can redistribute it and/or modify
##    it under the terms of the GNU General Public License as published by
##    the Free Software Foundation, either version 3 of the License, or
##    (at your option) any later version.
##
##    BASIC-RoBots is distributed in the hope that it will be useful,
##    but WITHOUT ANY WARRANTY; without even the implied warranty of
##    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##    GNU General Public License for more details.
##
##    You should have received a copy of the GNU General Public License
##    along with BASIC-RoBots.  If not, see <http://www.gnu.org/licenses/>.
## 
## Started on  Thu Jun 28 20:42:21 2012 Pierre Surply
## Last update Mon Sep  3 18:12:42 2012 Pierre Surply
##

import os
import pygame
import array
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *

import surface
import savable
import noise
import env
from robot import mothership
from robot import woodcutter
from robot import tipper
from robot import thermalpowerstation

class WorldMap(savable.Savable):
    biomes = [((0,0,255,255), 0, "Sea", 0),\
                  ((100,100,0,255), 1, "Beach", 2),\
                  ((0,255,0,255),2, "Plains", 0),\
                  ((10,10,10,255),3, "Montainous", 2),\
                  ((250,250,250,255),5,"Snowy", 3),\
                  ((0,250,0,255),6, "Forest", 1),\
                  ((100,0,100,255),7, "Corruption", 4),\
                  ((255,0,100,255),8, "Meteorite", 3),\
                  ((0,0,100,255),9, "Deep sea", 2),\
                  ((255,255,0,255),10, "Montainous", 2),\
                  ((255,0,0,255),4, "Volcanic", 4)]
    size = 32
    s = [(0.2, 9),\
             (0.5, 0),\
             (0.55, 1),\
             (0.555,7),\
             (0.56, 8),\
             (0.65, 2),\
             (0.75, 6),\
             (0.83, 3),\
             (0.85, 10),\
             (0.9, 5),\
             (1.0, 4)]

    def __init__(self, path):
        self.path = path
        self.sprite_biomes = surface.cut_surface(pygame.image.load("res/img/biomes.png").convert_alpha(), (8, 8))
        self.cursor = surface.surface2texture(pygame.image.load("res/img/cursor.png").convert_alpha())
        self.init_tile()
        self.build()

    def init_tile(self):
        self.tile = array.array('B', [0] * (self.size**2))
        self.env = [[None] * self.size for i in range(self.size)]
        
    def render(self, (w, h), (sx, sy)):
        size_biome = min((w/2) / 34, (h/2) / 34)
        size_large_biome = min((w/4)/9, (h/2) / 9)
        dx = (w/2) + ((w/2) - size_biome*32)/2
        dy = size_biome
        dlx = dx + size_biome*16 + (size_biome*16)/9
        dly = dy + (h/2) + (((h/2) - size_large_biome*9)/2)
        for y in range(self.size):
            for x in range(self.size):
                glBindTexture(GL_TEXTURE_2D, self.sprite_biomes[self.tile[(y*self.size)+x]])
                glBegin(GL_QUADS)
                
                glTexCoord2f(0, 0); glVertex2f(x*size_biome+dx, (y+1)*size_biome+dy)
                glTexCoord2f(0, 1); glVertex2f(x*size_biome+dx, y*size_biome+dy)
                glTexCoord2f(1, 1); glVertex2f((x+1)*size_biome+dx, y*size_biome+dy)
                glTexCoord2f(1, 0); glVertex2f((x+1)*size_biome+dx, (y+1)*size_biome+dy)
                
                glEnd()
        glBindTexture(GL_TEXTURE_2D, self.cursor)
        glBegin(GL_QUADS)
        
        glTexCoord2f(0, 0); glVertex2f(sx*size_biome+dx, (sy+1)*size_biome+dy)
        glTexCoord2f(0, 1); glVertex2f(sx*size_biome+dx, sy*size_biome+dy)
        glTexCoord2f(1, 1); glVertex2f((sx+1)*size_biome+dx,  sy*size_biome+dy)
        glTexCoord2f(1, 0); glVertex2f((sx+1)*size_biome+dx, (sy+1)*size_biome+dy)
        
        glEnd()
        #if self.env[sx][sy] != None:
        #    self.env[sx][sy].render_mini(surface, (dx-1, (self.size*8) + dy+2))
        for y in range(max(0,sy - 4), min(sy + 4, self.size)):
            for x in range(max(0,sx - 4), min(sx + 4, self.size)):
                glBindTexture(GL_TEXTURE_2D, self.sprite_biomes[self.tile[(y*self.size)+x]])
                glBegin(GL_QUADS)
                
                glTexCoord2f(0, 0); glVertex2f((x-(sx-4))*size_large_biome+dlx, \
                                                   (y-(sy-4)+1)*size_large_biome+dly)
                glTexCoord2f(0, 1); glVertex2f((x-(sx-4))*size_large_biome+dlx, \
                                                   (y-(sy-4))*size_large_biome+dly)
                glTexCoord2f(1, 1); glVertex2f((x-(sx-4)+1)*size_large_biome+dlx, \
                                                   (y-(sy-4))*size_large_biome+dly)
                glTexCoord2f(1, 0); glVertex2f((x-(sx-4)+1)*size_large_biome+dlx, \
                                                   (y-(sy-4)+1)*size_large_biome+dly)
            
                glEnd()
        glBindTexture(GL_TEXTURE_2D, self.cursor)
        glBegin(GL_QUADS)
        
        glTexCoord2f(0, 0); glVertex2f(dlx+size_large_biome*4, dly+size_large_biome*5)
        glTexCoord2f(0, 1); glVertex2f(dlx+size_large_biome*4, dly+size_large_biome*4)
        glTexCoord2f(1, 1); glVertex2f(dlx+size_large_biome*5, dly+size_large_biome*4)
        glTexCoord2f(1, 0); glVertex2f(dlx+size_large_biome*5, dly+size_large_biome*5)
        
        glEnd()

    def build(self):
        self.init_tile()
        n = noise.Noise(33, 33, 4, 8)
        for y in range(self.size):
            for x in range(self.size):
                biome = self.get_rndtile(x, y, n)
                self.tile[(y*self.size)+x] = biome

    def get_rndtile(self, x, y, noise):
        val = noise.smooth_noise(x, y, 0.4)
        for i in self.s:
            if val < i[0]:
                return i[1]
        return self.s[0][1]

    def build_env(self, (x, y), events):
        if self.env[x][y] == None:
            self.env[x][y] = env.Env(self.path, \
                                         self.tile[(y*self.size)+x],\
                                         (x, y), events)


    def load(self, events):
        self.load_img("saves/" + self.path + "/env/worldmap.bmp",\
                          self.size,\
                          self.tile,\
                          self.color2tile)
        for y in range(self.size):
            for x in range(self.size):
                if os.path.isfile("saves/" + self.path + "/env/" + str(x) + "_" + str(y) + ".bmp"):
                    self.env[x][y] = env.Env(self.path, \
                                                 self.tile[(y*self.size)+x],\
                                                 (x, y), events)

        for i in os.listdir("saves/" + self.path + "/robots"):
            part = i.split("_")
            coord = [int(x) for x in part[1].split("-")]
            if part[0] == "Mothership":
                r = mothership.Mothership(False,\
                                              self.path, \
                                              i,\
                                              self.env[coord[0]][coord[1]], \
                                              (0, 0),\
                                              events)
            elif part[0] == "Woodcutter":
                r = woodcutter.Woodcutter(False,\
                                              self.path, \
                                              i,\
                                              self.env[coord[0]][coord[1]], \
                                              (0, 0),\
                                              events)
            elif part[0] == "Tipper":
                r = tipper.Tipper(False,\
                                       self.path, \
                                       i,\
                                       self.env[coord[0]][coord[1]], \
                                       (0, 0),\
                                       events)
            elif part[0] == "TPS":
                r = thermalpowerstation.ThermalPowerStation(False,\
                                                                self.path, \
                                                                i,\
                                                                self.env[coord[0]][coord[1]], \
                                                                (0, 0),\
                                                                events)
            self.env[coord[0]][coord[1]].robots.append(r)
            self.env[coord[0]][coord[1]].calculate_light()

    def save(self):
        self.save_img("saves/" + self.path + "/env/worldmap.bmp",\
                          self.size,\
                          self.tile,\
                          self.tile2color)
        for y in range(self.size):
            for x in range(self.size):
                if self.env[x][y] != None:
                    self.env[x][y].save()

    def tile2color(self, (x, y)):
        n = self.tile[(y*self.size)+x]
        for i in self.biomes:
            if n == i[1]:
                return pygame.Color(i[0][0], \
                                        i[0][1], \
                                        i[0][2],\
                                        i[0][3])

    def color2tile(self, color):
        for i in self.biomes:
            if color == i[0]:
                return i[1]