CCCPaste

Simple State Machine And Transparency Example

import pygame

# Simple Infinite State Machine
class State:
    def __init__(self, control):
        self.control = control

    def on_draw(self, surface): pass
    def on_event(self, event): pass
    def on_update(self, delta): pass

class StateHandler:
    def __init__(self):
        self.states = {}
        self.current = None
        self.next_ = None

    def add(self, name, state):
        self.states[name] = state

    def get(self, name):
        return self.states[name]

    def push(self, state):
        self.next_ = self.states[state]

    def update(self):
        if self.next_:
            self.current = self.next_
            self.next_ = None

class StateControl:
    def __init__(self, caption, size, flags=0, fps=0):
        pygame.display.set_caption(caption)
        self.display = pygame.display.set_mode(size, flags)
        self.rect = self.display.get_rect()
        self.clock = pygame.time.Clock()
        self.running = True
        self.delta = 0
        self.fps = fps

        self.state = StateHandler()

    def loop(self):
        while self.running:
            self.state.update()
            for event in pygame.event.get():
                if event.type != pygame.QUIT:
                    self.state.current.on_event(event)
                else:
                    self.running = False

            self.state.current.on_update(self.delta)
            self.state.current.on_draw(self.display)
            pygame.display.flip()
            self.delta = self.clock.tick(self.fps)

    def run(self, state=None):
        if state:
            self.state.current = state
        else:
            if self.state.current is None:
                self.state.current = State(self)
                print("You forgot to set state")

        self.loop()

# States
class Intro(State):
    def __init__(self, control):
        super().__init__(control)
        font = pygame.font.Font(None, 30)
        self.image = font.render("Game Intro", 1, "dodgerblue")
        self.rect = self.image.get_rect()
        self.rect.top = self.control.rect.top + 20
        self.rect.centerx = self.control.rect.centerx

    def on_draw(self, surface):
        surface.fill("black")
        surface.blit(self.image, self.rect)

    def on_event(self, event):
        if event.type == pygame.KEYDOWN:
            self.control.state.push("Game")

class Game(State):
    def __init__(self, control):
        super().__init__(control)
        self.images = self.create_images()
        self.positions = (40, 30), (500, 200), (150, 320)

    def create_images(self):
        box = pygame.Surface((100, 100))
        box.fill("blue")

        rect = pygame.Rect(0, 0, 50, 50)
        circle = pygame.Surface(rect.size, pygame.SRCALPHA)
        pygame.draw.circle(circle, "lawngreen", rect.center, rect.width / 2 - 1)

        rect = pygame.Rect(0, 0, 60, 60)
        triangle = pygame.Surface(rect.size, pygame.SRCALPHA)
        points = rect.midtop, rect.bottomright, rect.bottomleft
        pygame.draw.polygon(triangle, "firebrick", points)

        return box, circle, triangle

    def on_draw(self, surface):
        surface.fill("black")
        for (image, pos) in zip(self.images, self.positions):
            surface.blit(image, pos)

    def on_event(self, event):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                self.control.state.push("Pause")

class Pause(State):
    def __init__(self, control):
        super().__init__(control)
        self.image = pygame.Surface(self.control.rect.size, pygame.SRCALPHA)
        self.fill_color = pygame.Color(250, 250, 0, 100)
        self.font = pygame.font.Font(None, 24)
        self.alpha_sprite = QuickSprite()
        self.update_alpha()

    def on_draw(self, surface):
        game = self.control.state.get("Game")
        game.on_draw(surface)
        surface.blit(self.image, (0, 0))
        self.alpha_sprite.draw(surface)

    def on_event(self, event):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                if self.fill_color.a < 250:
                    self.fill_color.a += 10
                    self.update_alpha()
            elif event.key == pygame.K_DOWN:
                if self.fill_color.a > 10:
                    self.fill_color.a -= 10
                    self.update_alpha()
            else:
                self.control.state.push("Game")

    def update_alpha(self):
        self.image.fill(self.fill_color)
        image = self.font.render(str(self.fill_color.a), 1, 'navy')
        self.alpha_sprite.set_image(image)
        self.alpha_sprite.rect.top = 20
        self.alpha_sprite.rect.right = self.control.rect.right - 20

# Other
class QuickSprite:
    def __init__(self, image=None):
        if image:
            self.set_image(image)

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def set_image(self, image):
        self.image = image
        self.rect = image.get_rect()

def main():
    control = StateControl("Example", (800, 600))
    control.state.add("Game", Game(control))
    control.state.add("Pause", Pause(control))
    control.run(Intro(control))

if __name__ == "__main__":
    pygame.init()
    main()
    pygame.quit()