Example #1
0
    Container = 4


class FlagSet:
    def __init__(self, *flags):
        self.flagset = set(flags)
        self.nameset = set(flag.name for flag in flags)
        # Attribute-based access
        for name in TileFlags.__members__:
            setattr(self, name, name in self.nameset)

    def copy(self):
        return FlagSet(*self.flagset)


config = json.loadf("configs/dungeon.json")
level_size = config["level_size"]
tile_size = config["tile_size"]
tile_size_t = (tile_size, tile_size)

# ===== ===== ===== ===== ===== ===== ===== ===== ===== =====
# ===== ===== =====       Basic Tiles       ===== ===== =====
# ===== ===== ===== ===== ===== ===== ===== ===== ===== =====


class BaseTile(AbstractLevelTile):
    needs_update = False
    passable = True
    transparent = True
    flags_template = FlagSet()
Example #2
0
class GameConsole:
    class Status:
        Standby = 0
        Interpret = 1

    config = json.loadf("configs/console.json")
    size = config["console_size"]
    background_color = config["console_background_color"]
    font_filename = "fonts/camingocode.ttf"
    font_size = 14
    font = fontutils.get_font(font_filename, font_size)
    valid_letter_range = range(pygame.K_a, pygame.K_z + 1)
    valid_chars = set(range(pygame.K_0, pygame.K_9 + 1)) | set(valid_letter_range) | \
                  {pygame.K_ASTERISK, pygame.K_COMMA, pygame.K_PERIOD, pygame.K_EQUALS,
                   pygame.K_GREATER, pygame.K_LESS, pygame.K_LEFTBRACKET, pygame.K_RIGHTBRACKET,
                   pygame.K_LEFTPAREN, pygame.K_RIGHTPAREN, pygame.K_QUESTION,
                   pygame.K_SEMICOLON, pygame.K_COLON, pygame.K_PLUS, pygame.K_MINUS,
                   pygame.K_UNDERSCORE, pygame.K_SPACE, pygame.K_QUOTE, pygame.K_QUOTEDBL,
                   pygame.K_SLASH, pygame.K_BACKSLASH, pygame.K_DOLLAR, pygame.K_BACKQUOTE}
    shift_fixes = {
        pygame.K_1: pygame.K_EXCLAIM,
        pygame.K_2: pygame.K_AT,
        pygame.K_3: pygame.K_HASH,
        pygame.K_4: pygame.K_DOLLAR,
        pygame.K_5: 37,  # percent sign
        pygame.K_6: pygame.K_CARET,
        pygame.K_7: pygame.K_AMPERSAND,
        pygame.K_8: pygame.K_ASTERISK,
        pygame.K_9: pygame.K_LEFTPAREN,
        pygame.K_0: pygame.K_RIGHTPAREN,
        pygame.K_EQUALS: pygame.K_PLUS,
        pygame.K_SEMICOLON: pygame.K_COLON,
        pygame.K_QUOTE: pygame.K_QUOTEDBL,
        pygame.K_MINUS: pygame.K_UNDERSCORE,
        pygame.K_LEFTBRACKET: 123,  # left curly bracket
        pygame.K_RIGHTBRACKET: 125,  # right curly bracket,
        pygame.K_COMMA: pygame.K_LESS,
        pygame.K_PERIOD: pygame.K_GREATER,
        pygame.K_SLASH: pygame.K_QUESTION,
        pygame.K_BACKSLASH: 124,  # pipe character
        pygame.K_BACKQUOTE: 126,  # tilde
    }
    uppercase_fix = -32  # a (97) -> A (65) when shift is pressed
    linegap = 1
    history_length_limit = 100
    current_line_prefix = ">>> "
    view_change_speed = 3
    # This won't work well with non-monospace fonts
    charsize = font.size(" ")
    charlimit = size[0] // charsize[0]

    def __init__(self, parent):
        self.parent = parent
        self.interpreter = EmbeddedInterpreter()
        self.background = self.get_empty_background_surface()
        self.rect = pygame.Rect((0, 0), self.size)
        self.renders = []
        self.view = 0
        self.current_line = ""
        self.history = []
        self.history_pointer = None
        self.pointer = None
        self.last_key = None
        self.last_char_pressed_for = 0
        self.next_last_char_cd = -1
        self.erase_all()
        inrend = fontutils.get_text_render(self.font, self.get_intext(), False,
                                           Color.Green, None, False, False)
        self.add_to_output(inrend)

    def update(self, events, pressed_keys, mouse_pos, namespace=None):
        self.changed = False
        interpret_status = False
        edited_events = []
        shift = shift_pressed(pressed_keys)
        if self.last_key is not None and pressed_keys[self.last_key] and \
          not any(event.type == pygame.KEYDOWN for event in events):
            self.last_char_pressed_for += 1
        else:
            self.last_char_pressed_for = 0
        if self.last_char_pressed_for >= 40 and self.next_last_char_cd <= -1:
            self.next_last_char_cd = 3
        if not self.next_last_char_cd:
            events.append(pygame.event.Event(pygame.KEYDOWN,
                                             key=self.last_key))
        if self.next_last_char_cd >= 0:
            self.next_last_char_cd -= 1
        if pressed_keys[controls.ConsoleKeys.ScrollUp]:
            self.view -= self.view_change_speed
            if self.view < 0:
                self.view = 0
        if pressed_keys[controls.ConsoleKeys.ScrollDown]:
            self.view += self.view_change_speed
            lasty = self.renders[-1][1][1] + self.renders[-1][0].get_height()
            if self.view > lasty:
                self.view = lasty
        for event in events:
            mute = False
            if event.type == pygame.KEYDOWN:
                mute = True
                key = event.key
                if key != self.last_key:
                    self.last_char_pressed_for = 0
                self.last_key = key
                if event.key in self.valid_chars:
                    self.put_char(self.convert_key_to_char(key, shift))
                elif event.key == controls.ConsoleKeys.DeleteChar:
                    self.delete_char()
                elif event.key == controls.ConsoleKeys.Enter:
                    self.changed = True
                    if namespace is not None:
                        self.interpret_current(namespace)
                    else:
                        interpret_status = True
                elif event.key == controls.ConsoleKeys.DeleteLine:
                    if not shift:
                        self.erase_current()
                    else:
                        self.erase_all()
                elif event.key == controls.ConsoleKeys.HistoryNext:
                    if self.history:
                        if self.history_pointer is None:
                            self.history_pointer = 1
                        elif self.history_pointer < len(self.history):
                            self.history_pointer += 1
                        self.pointer = None
                        print(self.history_pointer,
                              self.history[-self.history_pointer])
                        self.current_line = self.history[-self.history_pointer]
                        self.re_render_current()
                elif event.key == controls.ConsoleKeys.HistoryPrevious:
                    if self.history:
                        if self.history_pointer is None:
                            self.history_pointer = 1
                        elif self.history_pointer > 1:
                            self.history_pointer -= 1
                        self.pointer = None
                        print(self.history_pointer,
                              self.history[-self.history_pointer])
                        self.current_line = self.history[-self.history_pointer]
                        self.re_render_current()
                elif event.key == controls.ConsoleKeys.PointerLeft:
                    if self.current_line and self.pointer is None:
                        self.pointer = -1
                    else:
                        if self.pointer > -len(self.current_line):
                            self.pointer -= 1
                    self.re_render_current()
                elif event.key == controls.ConsoleKeys.PointerRight:
                    if self.pointer is not None and self.pointer < -1:
                        self.pointer += 1
                    else:
                        self.pointer = None
                    self.re_render_current()
                else:
                    mute = False
            if not mute:
                edited_events.append(event)
                try:
                    pressed_keys[event.key] = 0
                except (IndexError, AttributeError):
                    pass
        events.clear()
        events.extend(edited_events)
        for k in self.valid_chars | {
                pygame.K_BACKSPACE, pygame.K_RETURN, pygame.K_DELETE,
                pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT, pygame.K_RIGHT,
                pygame.K_PAGEUP, pygame.K_PAGEDOWN
        }:
            try:
                pressed_keys[k] = 0
            except IndexError:
                pass
        if interpret_status:
            return self.Status.Interpret
        else:
            return self.Status.Standby

    def draw(self, screen):
        screen.blit(self.background, self.rect)
        checkrect = pygame.Rect(-self.size[0], -self.size[1], self.size[0] * 2,
                                self.size[1] * 2)
        for render, pos in self.renders + [
            (self.current_line_render, self.current_line_pos)
        ]:
            apos = (pos[0], pos[1] - self.view)
            if self.rect.y - render.get_height(
            ) <= apos[1] <= self.rect.y + self.size[1]:
                area = render.get_rect().move(apos).clip(checkrect).move(
                    -apos[0], -apos[1])
                screen.blit(render, apos, area)

    def get_empty_background_surface(self):
        surface = pygame.Surface(self.size)
        surface.fill(self.background_color[:3])
        surface.set_alpha(self.background_color[3])
        return surface

    def get_empty_output_surface(self):
        surface = pygame.Surface(self.size)
        surface.fill(Color.Black)
        surface.set_colorkey(Color.Black)
        return surface

    def get_intext(self):
        return "Python {} on {} {} [{}]".format(platform.python_branch(),
                                                platform.system(),
                                                platform.release(),
                                                platform.machine())

    def add_to_output(self, render):
        if render.get_height() < self.rect.height:
            self.renders.append((render, self.current_line_pos.copy()))
            self.current_line_pos[1] += render.get_height() + self.linegap
        else:
            parts = [
                render.subsurface(
                    0, y, render.get_width(),
                    min(render.get_height() - y, self.rect.height))
                for y in range(0, render.get_height(), self.rect.height)
            ]
            for part in parts:
                self.renders.append((part, self.current_line_pos.copy()))
                self.current_line_pos[1] += part.get_height()

    def re_render_current(self, with_vline=True):
        if with_vline and self.pointer is not None:
            i = self.pointer
            line = self.current_line[:i] + fontutils.VLINE + self.current_line[
                i:]
        else:
            line = self.current_line
        render = fontutils.get_text_render(self.font,
                                           self.current_line_prefix + line,
                                           False, Color.White, None, False,
                                           False)
        self.current_line_render = render
        self.changed = True
        cbottom = self.current_line_pos[
            1] + self.current_line_render.get_height()
        if cbottom - self.view > self.rect.height:
            self.view = cbottom - self.rect.height

    def erase_current(self):
        if self.current_line and (not self.history
                                  or self.history[-1] != self.current_line):
            self.history.append(self.current_line)
            while len(self.history) > self.history_length_limit:
                self.history.pop(0)
        self.history_pointer = None
        self.pointer = None
        self.current_line = ""
        self.current_line_render = pygame.Surface((0, 0))
        self.re_render_current()

    def erase_all(self):
        self.current_line_pos = [0, 0]
        self.renders.clear()
        self.erase_current()

    def interpret_current(self, namespace):
        self.re_render_current(with_vline=False)
        self.add_to_output(self.current_line_render)
        interpret_line = fontutils.remove_render_tags_from_text(
            self.current_line)
        log("Interpreting: {}".format(interpret_line))
        result = self.interpreter.run(interpret_line, namespace)
        if result:
            log("Result:\n{}".format(result))
        if result and result != "None":
            try:
                color = Color.White
                if "[ERROR]" in result:
                    color = Color.Red
                    result = result.replace("[ERROR]", "")
                render = fontutils.get_multiline_text_render(
                    self.font,
                    result,
                    False,
                    color,
                    None,
                    self.linegap,
                    dolog=False,
                    cache=False,
                    with_render_tags=False,
                    wordwrap_chars=self.charlimit)
            except pygame.error as e:
                render = fontutils.get_text_render(
                    self.font,
                    "[Error while rendering output! '{}']".format(str(e)),
                    False, Color.Red, None, False, False)
            self.add_to_output(render)
            self.changed = True
        else:
            render = None
            log("No result")
        self.erase_current()

    def convert_key_to_char(self, key, shift):
        if shift:
            if key in self.valid_letter_range:
                key += self.uppercase_fix
            elif key in self.shift_fixes:
                key = self.shift_fixes[key]
        return chr(key)

    def put_char(self, char):
        if self.pointer is None:
            self.current_line += char
        else:
            i = self.pointer
            self.current_line = self.current_line[:
                                                  i] + char + self.current_line[
                                                      i:]
        self.re_render_current()

    def delete_char(self):
        if self.current_line:
            if self.pointer is None:
                self.current_line = self.current_line[:-1]
            else:
                i = self.pointer
                self.current_line = self.current_line[:i -
                                                      1] + self.current_line[i:]
            self.re_render_current()
Example #3
0
import math
import pygame

import json_ext as json
from colors import Color
import imglib
from abc_uiwidget import AbstractUIWidget

print("Load player UI")

config_ui = json.loadf("configs/playerui.json")


class MinimapWidget(AbstractUIWidget):
    minimap_tile = config_ui["minimap_blocksize"]
    minimap_tile_t = (minimap_tile, minimap_tile)
    minimap_tiles = config_ui["minimap_tiles"]
    question_mark = imglib.load_image_from_file(
        "images/sl/minimap/QuestionMarkM.png", after_scale=minimap_tile_t)
    tile_empty = imglib.load_image_from_file("images/dd/env/Bricks.png",
                                             after_scale=minimap_tile_t)
    tile_wall = imglib.load_image_from_file("images/dd/env/WallSmall.png",
                                            after_scale=minimap_tile_t)
    border_color = (0, 29, 109)

    def __init__(self, game, player):
        super().__init__(game, player)
        full_minimap_size_px = (self.game.vars["mapsize"][0] *
                                self.minimap_tile,
                                self.game.vars["mapsize"][1] *
                                self.minimap_tile)
Example #4
0
import particles
import statuseffects

print("Load player")


def _clamp(mn, mx, v):
    if v < mn:
        return mn
    elif v > mx:
        return mx
    else:
        return v


config_dungeon = json.loadf("configs/dungeon.json")
level_size = config_dungeon["level_size"]
tile_size = config_dungeon["tile_size"]
tile_size_t = (tile_size, tile_size)
screen_size = config_dungeon["level_surface_size"]
screen_rect = pygame.Rect((0, 0), screen_size)

config_ui = json.loadf("configs/playerui.json")
minimap_tile = config_ui["minimap_blocksize"]
minimap_tiles = config_ui["minimap_tiles"]


class PlayerCharacter(BaseSprite):
    is_entity = True
    size = (32, 32)
    surface = imglib.load_image_from_file("images/dd/player/HeroBase.png",