Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pygame Help
#7
Edit: Just realize this is an old thread.
Maybe this will give you some idea. Haven't done score card yet.
import pygame
import random

from itertools import count
from pygame.sprite import Group, Sprite

# Interface
class State:
    def __init__(self, engine):
        self.engine = engine

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

# Engine
class DisplayEngine:
    def __init__(self, caption, width, height, flags=0):
        # Basic Pygame Setup
        pygame.display.set_caption(caption)
        self.surface = pygame.display.set_mode((width, height), flags)
        self.rect = self.surface.get_rect()
        self.clock = pygame.time.Clock()
        self.running = True
        self.delta = 0
        self.fps = 60

        # Handle what state is active.
        self._state = State(self)
        self.next_state = None

    # Main Loop
    def run(self, state=None):
        if state:
            self._state = state

        while self.running:
            # State Changer
            if self.next_state:
                self._state = self.next_state
                self.next_state = None

            # Event Loop
            for event in pygame.event.get():
                # Just send the events to state to handle
                self._state.on_event(event)

            ticks = pygame.time.get_ticks()
            self._state.on_draw(self.surface)
            self._state.on_update(self.delta, ticks)
            pygame.display.flip()
            self.delta = self.clock.tick(self.fps)

    def quit(self):
        self.running = False

class SimpleSprite(Sprite):
    def __init__(self, image):
        super().__init__()
        self.image = image
        self.rect = image.get_rect()

class Callback:
    def __init__(self, callback, user_data=None):
        self.parent = None
        self.callback = callback
        self.user_data = user_data

    def link(self, parent):
        self.parent = parent
        return self

    def call(self):
        self.callback(self)

class Pen:
    def __init__(self, font, color):
        self.font = font
        self.color = color

    def render(self, text):
        return self.font.render(text, 1, self.color)

    def write(self, text):
        return SimpleSprite(self.render(text))

class ButtonImages:
    def __init__(self, normal, hover, pushed):
        self.normal = normal
        self.hover = hover
        self.pushed = pushed

class ButtonGroup:
    def __init__(self):
        self.buttons = Group()
        self.text = Group()

    def add(self, button):
        self.buttons.add(button)
        self.text.add(button.tsprite)

    def draw(self, surface):
        self.buttons.draw(surface)
        self.text.draw(surface)

class Button(Sprite):
    def __init__(self, images, pen, text, position, callback):
        super().__init__()
        self.pen = pen
        self.images = images
        self.image = images.normal
        self.rect = self.images.normal.get_rect(topleft=position)

        self.is_mouse_over = False
        self.is_pushed = False
        self.callback = callback.link(self)
        self.update_text(text)

    def mouse_over(self, event):
        self.is_mouse_over = self.rect.collidepoint(event.pos)
        self.update_image()

    def click(self, event):
        self.mouse_over(event)
        if self.is_mouse_over:
            #self.is_pushed = False
            self.callback.call()

    def update_image(self):
        if self.is_pushed:
            self.image = self.images.pushed
        elif self.is_mouse_over:
            self.image = self.images.hover
        else:
            self.image = self.images.normal

    def update_text(self, text):
        self.tsprite = self.pen.write(text)
        self.tsprite.rect.center = self.rect.center

# Store images. Because you want to create/load, convert, and/or size once.
class Images:
    def __init__(self):
        self.dice = self.create_dice(40, 'snow', 'black', 3)
        self.hdice = self.create_dice(40, 'skyblue', 'black', 3)
        self.sdice = self.create_dice(40, 'lightgreen', 'black', 3)

        self.button_images = self.create_button((100, 30), 'blue', 'dodgerblue', 'navy')

    def create_dice(self, size, color, dot_color, dot_size):
        surface = pygame.Surface((size, size))
        surface.fill(color)
        rect = surface.get_rect()
        inner = rect.inflate(-rect.centerx, -rect.centery)
        images = []

        for i in range(1, 7):
            s = surface.copy()
            if i in [1, 3, 5]:
                pygame.draw.circle(s, dot_color, rect.center, dot_size)

            if i != 1: # 2-6
                pygame.draw.circle(s, dot_color, inner.topleft, dot_size)
                pygame.draw.circle(s, dot_color, inner.bottomright, dot_size)

            if i > 3:
                pygame.draw.circle(s, dot_color, inner.topright, dot_size)
                pygame.draw.circle(s, dot_color, inner.bottomleft, dot_size)

            if i == 6:
                pygame.draw.circle(s, dot_color, inner.midleft, dot_size)
                pygame.draw.circle(s, dot_color, inner.midright, dot_size)

            images.append(s)
        return images

    def create_button(self, size, color, hcolor, pcolor):
        surface = pygame.Surface(size)
        surface.fill(color)
        hsurface = surface.copy()
        hsurface.fill(hcolor)
        psurface = surface.copy()
        psurface.fill(pcolor)
        return ButtonImages(surface, hsurface, psurface)

class Die(Sprite):
    def __init__(self, images, position):
        super().__init__()
        # These are just reference
        self.images = images
        self.rect = images[0][0].get_rect(topleft=position)
        self.is_mouse_over = False
        self.is_selected = False
        self.roll()

    def roll(self):
        self.value = random.randint(1, 6)
        self.is_selected = False
        self.update_image()

    def mouse_over(self, mpos):
        self.is_mouse_over = self.rect.collidepoint(mpos)
        self.update_image()

    def selected(self):
        if self.is_mouse_over:
            self.is_selected = not self.is_selected
            self.update_image()

    def update_image(self):
        if self.is_selected:
            self.image = self.images[2][self.value - 1]
        elif self.is_mouse_over:
            self.image = self.images[1][self.value - 1]
        else:
            self.image = self.images[0][self.value - 1]

class DisplayLines:
    def __init__(self, pen, position):
        self.position = position
        self.lines = []
        self.pen = pen

    def add(self, text):
        self.lines.append(self.pen.render(text))

    def clear(self):
        self.lines = []

    def draw(self, surface):
        y = count(self.position[1], self.pen.font.get_linesize() + 2)
        for line in self.lines:
            surface.blit(line, (self.position[0], next(y)))

class GameState(State):
    def __init__(self, engine):
        super().__init__(engine)
        self.dice_space = 50
        self.dice_fromedgex = 30
        self.dice_fromedgey = 30

        self.images = Images()
        self.roll_button = self.create_roll_button()
        self.bgroup = ButtonGroup()
        self.dice = Group()
        self.set_up()

    def create_roll_button(self):
        pen = Pen(pygame.font.Font(None, 28), 'snow')
        pos = self.dice_space * 5 - 100 + self.dice_fromedgex, 80
        callback = Callback(self.push_rolled)
        return Button(self.images.button_images, pen, "Roll", pos, callback)

    def set_up(self):
        images = self.images.dice, self.images.hdice, self.images.sdice
        for i in range(5):
            pos = self.dice_space * i + self.dice_fromedgex, self.dice_fromedgey
            self.dice.add(Die(images, pos))

        self.bgroup.add(self.roll_button)
        pos = self.engine.rect.centerx, 10
        pen = Pen(pygame.font.Font(None, 22), 'lawngreen')
        self.lines = DisplayLines(pen, pos)
        self.get_data()

    def push_rolled(self, callback):
        for d in self.dice:
            if d.is_selected:
                d.roll()

        self.get_data()

    def get_data(self):
        self.lines.clear()
        values = [d.value for d in self.dice]
        set_v = set(values)
        if len(set_v) == 1:
            self.lines.add("Yahtzee")

        if len(set_v) == 2:
            for v in set_v:
                if values.count(v) == 4:
                    self.lines.add("4 of a kind")
                elif values.count(v) == 3:
                    self.lines.add("Fullhouse")

        if len(set_v) == 3:
            data = [values.count(i) for i in set_v]
            if 3 in data:
                self.lines.add("3 of a kind")
            else:
                self.lines.add("two pair")

        if len(set_v) == 4:
            data = list(set_v)
            data.sort()
            if [1, 2, 3, 4] == data or [2, 3, 4, 5] == data or [3, 4, 5, 6] == data:
                self.lines.add("small straight")

        if len(set_v) == 5:
            data = list(set_v)
            data.sort()
            if [1, 2, 3, 4, 5] == data or [2, 3, 4, 5, 6] == data:
                self.lines.add("large straight")

            if ([1, 2, 3, 4] == data[:-1] or
                [2, 3, 4, 5] == data[:-1] or
                [2, 3, 4, 5] == data[1:] or
                [3, 4, 5, 6] == data[1:]):

                self.lines.add("small straight")

    # Override. From state interface
    def on_draw(self, surface):
        surface.fill('gray10')
        self.dice.draw(surface)
        self.bgroup.draw(surface)
        self.lines.draw(surface)

    # Override. From state interface
    def on_event(self, event):
        if event.type == pygame.QUIT:
            self.engine.quit()
        elif event.type == pygame.MOUSEMOTION:
            for d in self.dice:
                d.mouse_over(event.pos)

            for b in self.bgroup.buttons:
                b.mouse_over(event)

        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                self.roll_button.click(event)
                for d in self.dice:
                    d.selected()

if __name__ == '__main__':
    pygame.init()
    engine = DisplayEngine("Dice", 800, 600)
    game = GameState(engine)
    engine.run(game)
    pygame.quit()
99 percent of computer problems exists between chair and keyboard.
Reply


Messages In This Thread
Pygame Help - by piznac - Jun-30-2021, 09:58 PM
RE: Pygame Help - by piznac - Jul-01-2021, 09:54 PM
RE: Pygame Help - by BashBedlam - Jul-04-2021, 12:44 PM
RE: Pygame Help - by piznac - Jul-04-2021, 09:32 PM
RE: Pygame Help - by noahcentineo - Jul-12-2021, 02:28 AM
RE: Pygame Help - by stephanilope - Nov-19-2022, 03:28 AM
RE: Pygame Help - by Windspar - Nov-25-2022, 03:14 AM

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020