# This file is part of A Robot's Conundrum. # # A Robot's Conundrum 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. # # A Robot's Conundrum 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 # A Robot's Conundrum. If not, see . # # ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' # # block.py # -------------------- # date created : Tue Aug 7 2012 # copyright : (C) 2012 Sakse Dalum # maintained by : Sakse Dalum """ A generic block. And other block derivatives. """ import pygame import itertools import worldobject import copy class Block(worldobject.WorldObject): def __init__(self, level, x, y, img_str='block1', movable=False, visible=True, width=1, height=1, blit_area=None, blocking=True, z=0): self.__dict__.update(locals()) worldobject.WorldObject.__init__(self, level, x, y, z=z, movable=movable, visible=visible, blit_area=blit_area, blocking=blocking) for i in range(width): for j in range(height): if width != 1 or height != 1: self.level.objects.append( InvisBlock(self.level, self.x + 64 * i, self.y - 48 * j)) self.load() # self.orig_alphas = { # 'normal': # pygame.surfarray.array_alpha(self.level.imgs[self.img_str]), # 'lifted': # pygame.surfarray.array_alpha( # self.level.imgs[self.img_str + '_lifted'])} # self.orig_alpha = self.orig_alphas['normal'] def load(self): if not isinstance(self.img_str, str): self.img_str = self.level.reverse_imgs[self.img_str] self.img = self.level.imgs[self.img_str] # def update_alpha(self): # be_opaque = not (self.y + self.z >= self.level.player.move_y # + self.level.player.move_z) # if be_opaque and not self.is_currently_opaque: # self.is_currently_opaque = True # self.set_alpha(1) # elif not be_opaque and self.is_currently_opaque: # self.is_currently_opaque = False # self.set_alpha(0.5) def use(self, obj): if self.movable: if obj == self.holder: obj.holding = None self.holder = None if hasattr(self, 'img_str'): self.img = self.level.imgs[self.img_str] # self.orig_alpha = self.orig_alphas['normal'] else: obj.holding = self self.holder = obj if hasattr(self, 'img_str'): self.img = self.level.imgs[self.img_str + '-lifted'] # self.orig_alpha = self.orig_alphas['lifted'] def draw(self, window): if self.visible: window.blit(self.img, (self.x - 32 - self.level.camera_x, self.y - self.img.get_size()[1] + 24 - self.level.camera_y), self.blit_area) class InvisBlock(Block): def __init__(self, level, x, y): self.__dict__.update(locals()) worldobject.WorldObject.__init__(self, level, x, y, visible=False) class ArrowBlock(Block): def __init__(self, level, x, y, direction, movable=True, is_up=True): self.__dict__.update(locals()) worldobject.WorldObject.__init__(self, level, x, y, direction=direction, movable=movable) self.frame = 0 self.anim_speed = 15 self.setting = False if direction == (1, 0): self.anim = 'arrow_right' if direction == (-1, 0): self.anim = 'arrow_left' if direction == (0, -1): self.anim = 'arrow_up' if direction == (0, 1): self.anim = 'arrow_down' self.img_str = self.anim def activate(self, setting): self.movable = True if not self.share_tile(worldobject.WorldObject): self.is_up = not setting self.movable = False def update(self, e, t, dt): # Update the animation if not self.is_up: self.frame = min(self.frame + self.anim_speed * dt, len(self.level.imgs[self.anim]) - 1) else: self.frame = max(self.frame - self.anim_speed * dt, 0) if self.frame == len(self.level.imgs[self.anim]) - 1: self.movable = self.blocking = False self.z = -48 if self.holder: self.holder.holding = None self.holder = None else: self.movable = self.blocking = True self.z = 0 worldobject.WorldObject.update(self, e, t, dt) def draw(self, window): if not self.holder: self.img = self.level.imgs[self.anim][int(self.frame)] Block.draw(self, window) class RisingBlock(Block): def __init__(self, level, x, y, movable=False, is_up=True): self.__dict__.update(locals()) worldobject.WorldObject.__init__(self, level, x, y, movable=movable) self.frame = 0 self.anim_speed = 15 self.setting = [0, 0] self.init_setting = self.setting self.anim = 'arrow_right' def set_init_pos(self): worldobject.WorldObject.set_init_pos(self) self.init_setting = [self.setting[0], self.setting[1]] def reset_pos(self): worldobject.WorldObject.reset_pos(self) self.setting = [self.init_setting[0], self.init_setting[1]] self.is_up = self.setting[1] == self.setting[0] def activate(self, setting): if setting in [2, 3]: self.setting[1] = setting - 2 else: self.setting[0] = setting if not self.share_tile(worldobject.WorldObject): self.is_up = self.setting[1] == self.setting[0] def update(self, e, t, dt): # Update the animation if not self.is_up: self.frame = min(self.frame + self.anim_speed * dt, len(self.level.imgs[self.anim]) - 1) else: self.frame = max(self.frame - self.anim_speed * dt, 0) if self.frame == len(self.level.imgs[self.anim]) - 1: self.blocking = False self.z = -48 else: self.blocking = True self.z = 0 worldobject.WorldObject.update(self, e, t, dt) def draw(self, window): self.img = self.level.imgs[self.anim][int(self.frame)] Block.draw(self, window) class ActionBlock(Block): def __init__(self, level, x, y, action=None, movable=True): self.__dict__.update(locals()) Block.__init__( self, level, x, y, 'block1', movable=movable) self._last_pos = None def update(self, e, t, dt): if (self.x, self.y) != self._last_pos and not self.is_moving: self.action(self) self._last_pos = self.x, self.y worldobject.WorldObject.update(self, e, t, dt) class ColorWell(Block): def __init__(self, level, x, y, img_str='well'): self.__dict__.update(locals()) worldobject.WorldObject.__init__( self, level, x, y, movable=False) Block.load(self) self.col_img = pygame.Surface((32, 32)) def set_colour(self, r, g, b): self.well_colour = r * 255, g * 255, b * 255 self.col_img.fill(self.well_colour) def draw(self, window): if self.visible: window.blit(self.col_img, (self.x - self.level.camera_x + 16, self.y - self.img.get_size()[1] + 52 - self.level.camera_y)) Block.draw(self, window) class Door(Block): def __init__(self, level, x, y, movable=False, setting=False): self.__dict__.update(locals()) worldobject.WorldObject.__init__(self, level, x, y, z=32, movable=movable) self.frame = 0 self.anim_speed = 15 self.init_setting = self.setting self.anim = 'door' self.level.objects.append(InvisBlock(self.level, self.x + 64, self.y)) self.level.objects.append(InvisBlock(self.level, self.x - 64, self.y)) def set_init_pos(self): worldobject.WorldObject.set_init_pos(self) self.init_setting = self.setting def reset_pos(self): worldobject.WorldObject.reset_pos(self) self.setting = self.init_setting def activate(self, setting): self.setting = setting def update(self, e, t, dt): # Update the animation if self.setting: self.frame = min(self.frame + self.anim_speed * dt, len(self.level.imgs[self.anim]) - 1) else: self.frame = max(self.frame - self.anim_speed * dt, 0) if self.frame == len(self.level.imgs[self.anim]) - 1: self.blocking = False else: self.blocking = True worldobject.WorldObject.update(self, e, t, dt) def draw(self, window): self.img = self.level.imgs[self.anim][int(self.frame)] if self.visible: window.blit(self.img, (self.x - (32 + 64) - self.level.camera_x, self.y - self.img.get_size()[1] + 24 - self.level.camera_y)) class LaserSource(Block): def __init__(self, level, x1, y1, source_direction): self.__dict__.update(locals()) Block.__init__(self, level, x1, y1, 'lasersource_' + source_direction.to_str(), movable=False) class LaserTarget(Block): def __init__(self, level, x0, y0): self.__dict__.update(locals()) self.xd, self.yd = self.x0 * 64, (self.y0 + 4) * 48 Block.__init__(self, level, self.xd, self.yd, 'lasertarget', movable=False) self.glows = False def new_playfield_update(self): self.glows, self.img_str = (True, 'lasertarget_glow') \ if (self.x0, self.y0) in itertools.chain(*self.level.lasers_orig) \ else (False, 'lasertarget') self.load()