Source

pygamegsoc12 / alchemymadness / blocks.py

"""Mixing potion"""

import pygame
from pygame.locals import Rect
from pygame.sprite import DirtySprite

import resources

GRID_SIZE_W = 9
GRID_SIZE_H = 16

BLOCK_W = 30
BLOCK_H = 30

# small block size.
SBLOCK_W = BLOCK_W / 2
SBLOCK_H = BLOCK_H / 2

class Block(DirtySprite):
    """ A single block.
    """

    changed = False

    def __init__(self, color, small, *groups):
        """
            color - (r,g,b) tuple.
            small - True if we are to be drawn small.
        """
        super(Block, self).__init__(*groups)

        self.small = small
        if self.small:
            self.rect = Rect(0, 0, SBLOCK_W, SBLOCK_W)
        else:
            self.rect = Rect(0, 0, BLOCK_W, BLOCK_W)

        self._image = pygame.Surface(self.rect.size) # Sprite image
        self._color = color  # Block color
        self.changed = True
        self.dirty = 1

    @property
    def image(self):
        if self.changed:
            if self.small:
                self._image = resources.sblock.copy()
            else:
                self._image = resources.block.copy()
            self._image.fill(self._color, special_flags=pygame.locals.BLEND_RGBA_MULT)
        return self._image

    @property
    def color(self):
        return self._color

    @color.setter
    def color(self, value):
        self._color = value
        self.changed = True


    def grid_pos(self, pos, grid_rect):
        """ set the rect for the given (x,y) grid pos
        """
        ox, oy, w, h = self.rect

        gx, gy = pos
        x, y = gx * w, gy * h
        x += grid_rect[0]
        y += grid_rect[1]
        self.rect = pygame.Rect(x, y, w, h)
        #print self.rect
        #self.changed = True
        self.dirty = 1



class Blocks(object):
    """ contains 3 Block() instances.
    """
    def __init__(self, parent):
        """ parent - a Grid instance.
        """
        super(Blocks, self).__init__()

        self.parent = parent
        #TODO: randomise these colors.
        self.colors = [(255,0,0), (0,255,0), (0,0,255)]

        # how do we handle location, and rotation? We say where the grid it is on.
        #     top, left is (0,0)
        self.grid_positions = [[0,0], [1,0], [2,0]]

        self.blocks = [Block(c, self.parent.small) for c in self.colors]
        self.on_moved()

    def on_moved(self):
        """ called when we have moved.
        """
        i = 0
        for b, pos in zip(self.blocks, self.grid_positions):
            #print "on_moved {} {}".format(i, pos)
            b.grid_pos(pos, self.parent.rect)
            i += 1

        #print "-" * 20

    def update(self, time):
        pass
        



    def has_collided(self):
        """ checks if we have collided with some other blocks.
              See if the blocks of the same color are below.
        """
        # TODO: self.parent is the grid.
        raise NotImplementedError()

    def make_frozen(self):
        """ makes this a frozen block in the grid.
        """
        # TODO: self.parent is the grid.
        #    Probably create a new grid.blocks...
        #      The Block instances will stay where they are in the sprite_group.
        raise NotImplementedError()





    # action_* methods are inputs.

    def action_move_left(self):
        # if any of them are going out of bounds, we don't move.
        doit = True
        for b in self.grid_positions:
            b[0] -= 1
            if b[0] < 0:
                doit = False
        if not doit:
            # oops!  out of bounds, so reverse moves.
            for b in self.grid_positions:
                b[0] += 1
                
        self.on_moved()

    def action_move_right(self):
        doit = True
        for b in self.grid_positions:
            b[0] += 1
            if b[0] >= GRID_SIZE_W:
                doit = False
        if not doit:
            for b in self.grid_positions:
                b[0] -= 1

        self.on_moved()


    def action_move_up(self):
        doit = True
        for b in self.grid_positions:
            b[1] -= 1
            if b[1] < 0:
                doit = False
        if not doit:
            for b in self.grid_positions:
                b[1] += 1
                
        self.on_moved()

    def action_move_down(self):
        doit = True
        for b in self.grid_positions:
            b[1] += 1
            if b[1] >= GRID_SIZE_H:
                doit = False
        if not doit:
            for b in self.grid_positions:
                b[1] -= 1
                
        self.on_moved()









class Grid(object):
    """ Contains Blocks()
    """
    def __init__(self, grid_num):
        super(Grid, self).__init__()
        self.grid_num = grid_num
        # draw the first one big.
        self.small = grid_num != 0

        self.GRID_SIZE_W = GRID_SIZE_W
        self.GRID_SIZE_H = GRID_SIZE_H

        if self.small:
            # TODO: get correct coords for where the grids are on screen.
            if self.grid_num == 1:
                self.rect = pygame.Rect(300, 20, GRID_SIZE_W * SBLOCK_W, GRID_SIZE_H * SBLOCK_H)
            if self.grid_num == 2:
                self.rect = pygame.Rect(470, 20, GRID_SIZE_W * SBLOCK_W, GRID_SIZE_H * SBLOCK_H)
            if self.grid_num == 3:
                self.rect = pygame.Rect(630, 20, GRID_SIZE_W * SBLOCK_W, GRID_SIZE_H * SBLOCK_H)
        else:
            self.rect = pygame.Rect(30, 20, GRID_SIZE_W * BLOCK_W, GRID_SIZE_H * BLOCK_H)

        self.restart()

    def restart(self):
        """ restart this Grid instance.
        """
        self.init_grid()
        self.blocks = Blocks(self)


        # TODO: what about frozen Blocks?




    def init_grid(self):
        """ init_grid initialises the Grid to be all clear.
        """
        # init our 10x10 grid, to show the color of each grid part.
        #[[(0,0,0), ...],
        # ...
        #]
        self.grid = []
        for x in range(self.GRID_SIZE_H):
            self.grid.append([(0,0,0)] * self.GRID_SIZE_W)

        #import pprint
        #pprint.pprint(self.grid)







class Grids(object):
    """ This contains all the main Grid objects.
    """
    NUM_GRIDS = 4
    def __init__(self, sprite_group):
        """ sprite_group - which we add sprites to.
        """
        self.sprite_group = sprite_group
        self.grids = [Grid(x) for x in range(self.NUM_GRIDS)]

        for grd in self.grids:
            for b in grd.blocks.blocks:
                self.sprite_group.add(b)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.