Logo Search packages:      
Sourcecode: whichwayisup version File versions  Download package

level.py

import pygame
import os

from pygame.locals import *

from locals import *

import data
from util import dir_from_str

from variables import error_message

from tile import Tile
from spikes import Spikes
from item import Item
from player import Player
from spider import Spider
from blob import Blob
from scripted_event import Scripted_event
from animation import Animation

class Level:

  def __init__(self, screen, level_name = "w0-l0"):
    self.screen = screen
    self.image = None
    self.flipping = False
    self.flipcounter = 0
    self.set = "brown"  #The default tileset, can be changed through level configuration

    self.tiles = []
    self.objects = []

    self.scripted_events = []

    self.cached_ground_check = {}
    
    self.dust_color = COLOR_DUST

    conffile = open(data.levelpath(level_name))
    
    tiley = 0
    values = []

    trigger = False
    current_event = None

    parse_tiles = False

    for line in conffile.readlines():

      if parse_tiles:
        if tiley < FULL_TILES_VER:
          tilex = 0
          while tilex < FULL_TILES_VER:
            if (line[tilex] == "W"):
              self.tiles.append( Tile(self.screen, tilex, tiley, self.set) )
            if (line[tilex] == "B"):
              self.tiles.append( Tile(self.screen, tilex, tiley, self.set, "bars") )
            if (line[tilex] == "S"):
              self.tiles.append( Spikes(self.screen, tilex, tiley, self.set) )
            tilex += 1
          tiley += 1
          continue
        else:
          parse_tiles = False
          continue

      elif line.strip() != "":
          values = line.split()
          
          #Parsing special commands

          if trigger:
            if values[0] == "end" and values[1] == "trigger":
              trigger = False
            else:
              current_event.add_element(line)
            continue
          elif values[0] == "trigger":
            trigger = True
            current_event = Scripted_event(values[1], int(values[2]))
            self.scripted_events.append(current_event)
            continue
          elif values[0] == "tiles":
            parse_tiles = True
            continue
          elif values[0] == "set":
            self.set = values[1]
            continue

          #Parsing objects

          x = (float(values[1]) - (FULL_TILES_HOR - TILES_HOR)) * TILE_DIM
          y = (float(values[2]) - (FULL_TILES_VER - TILES_VER))* TILE_DIM
          if values[0] == "player":
            self.player = Player(self.screen, x, y)
            continue
          elif values[0] == "spider":
            self.objects.append(Spider( self.screen, x, y, dir_from_str(values[3]) ))
            continue
          elif values[0] == "blob":
            self.objects.append(Blob(self.screen, x, y, self.player))
            continue
          elif values[0] == "lever":
            trigger_type = TRIGGER_NONE
            if values[4] == "TRIGGER_FLIP":
              trigger_type = TRIGGER_FLIP
            self.objects.append( Item(self.screen, x, y, self.set, values[0], int(values[3]), trigger_type) )
            continue
          else:
            try:
              self.objects.append(Item(self.screen, x, y, self.set, values[0]))
            except:
              error_message("Couldn't add object '" + values[0] + "'")
            continue

    if self.set == "green":
      self.dust_color = COLOR_DUST_GREEN

    self.bg_animations = {}
    self.bg_animations["default"] = Animation(self.set + "_background", "static")
    self.current_animation = "default"
    self.rect = (self.bg_animations[self.current_animation].update_and_get_image()).get_rect()
    self.rect.centerx = SCREEN_WIDTH / 2
    self.rect.centery = SCREEN_HEIGHT / 2

    self.reset_active_tiles()
    return

  def update(self):
    return_trigger = TRIGGER_NONE
    if self.flipping:
      self.flipcounter += 1
      if self.flipcounter > FLIP_FRAMES:
        self.flipcounter = 0
        self.flipping = False
        self.reset_active_tiles()
        return_trigger = TRIGGER_FLIPPED
        self.image = None
      for t in self.tiles:
        t.update()
    return return_trigger

  def reset_active_tiles(self):
    self.active_tiles = []
    for t in self.tiles:
      if (t.x > 0 and t.y > 0):
        self.active_tiles.append(t)
    return

  def get_objects(self):
    return self.objects

  def get_player(self):
    return self.player

  def get_scripted_events(self):
    return self.scripted_events

  #Renders the background and the tiles
  def render(self):
    if self.flipping or self.image == None:
      self.image = pygame.Surface((self.rect.width, self.rect.height))
      bg = self.bg_animations[self.current_animation].update_and_get_image()
      self.image.blit(bg, self.rect)
      for t in self.tiles:
        t.render(self.image)

    #Blits the cached background
    self.screen.blit(self.image, self.rect)
    return

  #Starts the flipping of the level
  def flip(self, flip_direction = CLOCKWISE):
    if self.flipping:
      return
    else:
      self.cached_ground_check = {}
      self.flipping = True
      for t in self.tiles:
        t.flip(flip_direction)
      return

  #Triggers an object in the position specified
  def trigger(self, x, y):
    for o in self.objects:
      if o.rect.collidepoint(x, y):
        if o.itemclass == "lever":
          trigg = o.activate()
          if trigg != TRIGGER_NONE:
            return trigg
    return TRIGGER_NONE

  #Gives an object from the level (also removes it from the level)
  def pick_up(self, x, y):
    for o in self.objects:
      if o.rect.collidepoint(x, y):
        if o.pickable:
          self.objects.remove(o)
          return o
    return None

  #Checks the point for solid ground
  def ground_check(self, x, y):
    if self.cached_ground_check.has_key(str(x) + "_" +  str(y)):
      return self.cached_ground_check[str(x) + "_" +  str(y)]
    else:
      if x > SCREEN_WIDTH or y > SCREEN_HEIGHT or x < 0 or y < 0:
        return True
      for t in self.active_tiles:
        if t.rect.collidepoint(x, y):
          self.cached_ground_check[str(x) + "_" +  str(y)] = True
          return True
      self.cached_ground_check[str(x) + "_" +  str(y)] = False
      return False

  #This functions tests (approximately) if a rect collides with another and from which direction.
  #It's one of the most performance-heavy functions in the game, and thus should be optimized.
  #indexing: right left bottom top
  def collide(self, rect, dy, dx, topcollision = True):
    collision = [None, None, None, None, 0]
    for t in self.active_tiles:
      if t.rect.collidepoint(rect.right + 1, rect.centery - dy) and dx > 0:
        collision[RIGHT] = t.rect.left
      if (t.rect.collidepoint(rect.right + 1, rect.bottom - dy - 1) or t.rect.collidepoint(rect.right + 1, rect.top - dy + 1)) and dx > 0:
        collision[RIGHT] = t.rect.left
      if t.rect.collidepoint(rect.left - 1, rect.centery - dy) and dx < 0:
        collision[LEFT] = t.rect.right
      if (t.rect.collidepoint(rect.left - 1, rect.bottom - dy - 1) or t.rect.collidepoint(rect.left - 1, rect.top - dy + 1)) and dx < 0:
        collision[LEFT] = t.rect.right
      if (t.rect.collidepoint(rect.centerx - dx, rect.bottom + 1) or t.rect.collidepoint(rect.right - dx - 1, rect.bottom + 1) or t.rect.collidepoint(rect.left - dx + 1, rect.bottom + 1)) and dy > 0:
        if (t.itemclass == "spikes"):
          if (collision[DOWN] == None):
            collision[DAMAGE] = 5
            collision[DOWN] = t.rect.top
        else:
          collision[DOWN] = t.rect.top
          if collision[DAMAGE] > 0:
            collision[DAMAGE] = 0
      if t.rect.collidepoint(rect.centerx - dx, rect.top - 1) and dy < 0:
        collision[UP] = t.rect.bottom
      if (t.rect.collidepoint(rect.right - dx - 1, rect.top - 1) or t.rect.collidepoint(rect.left - dx + 1, rect.top - 1)) and dy < 0:
        collision[UP] = t.rect.bottom

    return collision

Generated by  Doxygen 1.6.0   Back to index