def hit_wall(x, y): return ( state.board.outside(x, y) or is_wall(state.board.get(x, y)) or dist(state.player.pos, (x, y)) > state.max_range or is_door(state.board.get(x, y)) )
def encode_wall(board: Board, index: int) -> int: val = 0b10000 x, y = index_to_pos(index, board.side) neighs = [(x - 1, y), (x, y + 1), (x + 1, y), (x, y - 1)] for i, (x_, y_) in enumerate(neighs): if board.outside(x_, y_) or is_wall(board.get(x_, y_)): val = val | (1 << i) return int("{0:b}".format(val))
def draw(self, state): offx, offy = 48, 48 pyxel.rect(offx - 5, offy - 5, 42, 42, 7) pyxel.rect(offx - 4, offy - 4, 40, 40, 0) pyxel.rect(offx - 2, offy - 2, 36, 36, 5) for x, y in state.visited: col = 7 v = state.board.get(x, y) if is_door(v): col = 8 if is_locked(v) else 4 elif is_wall(v): col = 1 elif is_active_tile(v): col = 12 pyxel.pix(offx + x, offy + y, col) x, y = state.player.pos pyxel.pix(offx + x, offy + y, 11)
def encode_door(board: Board, index: int) -> int: x, y = index_to_pos(index, board.side) top = x, y - 1 top_val = board.get(*top) if board.outside(*top): return 22 elif is_wall(top_val): bin_str = str(top_val) if bin_str[4] == "0" and bin_str[2] == "1": return 21 elif bin_str[4] == "1" and bin_str[2] == "1": return 22 elif bin_str[2] == "0": return 23 return 20
def amend_door(board: Board, room_index: int, door_fn) -> Board: nodes = list(range(len(board))) start = board.to_index(*room_anchor(room_index)) target = board.entrance neighs = partial(board_neighbours, board, lambda x: not is_wall(x)) path = extract_path(find_paths(nodes, start, neighs), target) for i in path: if is_door(board[i]): board[i] = door_fn(board[i]) botx, boty = board.to_pos(i) boty += 1 # might rencode floor below if is_empty(board.get(botx, boty)): i = board.to_index(botx, boty) floor = encode_floor(board, i) board.set(botx, boty, floor) return board return board
def encode_floor(board: Board, index: int) -> int: x, y = index_to_pos(index, board.side) top = x, y - 1 top_val = board.get(*top) if board.outside(*top): return 32 elif is_wall(top_val): bin_str = str(top_val) if bin_str[4] == "0" and bin_str[2] == "1": return 31 elif bin_str[4] == "1" and bin_str[2] == "1": return 32 elif bin_str[4] == "1" and bin_str[2] == "0": return 33 elif bin_str[4] == "0" and bin_str[2] == "0": return 34 elif top_val == 20: # front door return 35 return 30
def draw(state: State): pyxel.cls(0) non_walls = { 0: (32, 16), 30: (40, 24), 31: (0, 24), 32: (8, 24), 33: (16, 24), 34: (40, 16), 35: (48, 8), 40: (40, 32), 41: (32, 32), 42: (32, 32), 43: (32, 32), 20: (48, 0), 21: (56, 16), 22: (56, 8), 23: (56, 0), 25: (64, 0), 26: (72, 16), 27: (72, 8), 28: (72, 0), 66: (64, 16), # UP 99: (64, 24), # DOWN } # draw in range for x, y in state.visible: # for i in range(len(state.board)): # x, y = index_to_pos(i, state.board.side) if state.board.outside(x, y): continue v = state.board.get(x, y) x, y = state.to_cam_space((x, y)) colors = WALLS if is_wall(v) else non_walls u_, v_ = colors[v] pyxel.blt( x * CELL_SIZE, y * CELL_SIZE, 0, u_, v_, CELL_SIZE, CELL_SIZE ) # draw collectibles and stuff for item in state.level.items: if item.square not in state.visible: continue x, y = state.to_cam_space(item.square) pyxel.blt(x * CELL_SIZE, y * CELL_SIZE, 0, *item.sprite) x, y = state.to_cam_space(state.player.pos) sp = state.player.sprite pyxel.blt( x * CELL_SIZE - sp.center[0], y * CELL_SIZE - sp.center[1], 0, *sp.uv, CELL_SIZE * state.player.orientation, CELL_SIZE, 1, ) enemies = sorted(state.enemies, key=lambda e: e.zindex) for enemy in enemies: if enemy.square not in state.visible: continue x, y = state.to_cam_space(enemy.pos) sp = enemy.sprite pyxel.blt( x * CELL_SIZE - sp.center[0], y * CELL_SIZE - sp.center[1], 0, *sp.uv, enemy.sprite.size[0] * enemy.orientation, enemy.sprite.size[1], 1, ) for p in state.particles: p.draw(state) # Active Tool if state.active_tool is not None: state.active_tool.draw(state) if state.text_box is not None: state.text_box.draw(state) # HUD pyxel.rect(3, 3, 2 * state.player.pv, 7, 2) pyxel.rect(3, 3, 2 * state.player.pv, 5, 8) pyxel.rect(4, 4, 2 * state.player.pv - 2, 1, 14) pyxel.rectb(2, 2, 42, 8, 1) for i in range(state.player.keys): pyxel.blt(3 + i * 7, 12, 0, *ITEMS["key"]) for i, flag in enumerate( ["wand", "teleport", "thunder", "armor", "tri", "triB", "triA"] ): if flag in state.player.flags: if flag in {"triA", "triB"} and "tri" in state.player.flags: continue pyxel.blt(117 - i * 8, 2, 0, *ITEMS[flag]) # MENU menu_ = menu(state) if state.menu_index is not None: h = 4 + len(menu_) * 8 pyxel.rect(40, 40, 48, h, 0) pyxel.rectb(40, 40, 48, h, 5) for i, (code, item, _) in enumerate(menu_): col = 5 if state.player.cooldown(code) else 7 pyxel.text(50, 43 + i * 8, item, col) pyxel.blt(41, 42 + state.menu_index * 8, 0, *ITEMS["dot"]) pyxel.rect(17, 121, 128, 7, 0) pyxel.text(19, 122, "X: Exit / C: Confirm", 7) elif state.text_box is not None: pyxel.text(3, 122, "X/C: Close", 7) else: pyxel.text(3, 122, "C: Menu", 7)
def player_action(state: State): if state.player.is_busy(): return x, y = state.player.square _end = end_turn(state) if state.active_tool is not None: return state.active_tool.update(state, _end) elif pyxel.btnr(pyxel.KEY_X) and state.menu_index is not None: state.menu_index = None return elif pyxel.btnr(pyxel.KEY_C): if state.menu_index is None: state.menu_index = 0 return else: menu_select = menu_item(state) if state.player.cooldown(menu_select[0]): return state.menu_index = None return menu_select[2](state) if state.menu_index is not None: return update_menu(state) elif pyxel.btn(pyxel.KEY_DOWN): delta = 0, 1 elif pyxel.btn(pyxel.KEY_UP): delta = 0, -1 elif pyxel.btn(pyxel.KEY_LEFT): delta = -1, 0 elif pyxel.btn(pyxel.KEY_RIGHT): delta = 1, 0 elif pyxel.btn(pyxel.KEY_SPACE): for _ in range(50): state.particles.append(Aura(_center(state.player.pos))) return else: return target = x + delta[0], y + delta[1] val = state.board.get(*target) entity = find_entity(state, *target) item = find_item(state, *target) if entity: a = state.player.attack(entity, _end) pyxel.play(3, 50) draw_damage(state, entity.pos, a, 12) elif item: item.interact(state) state.player.wait(FPS * 0.3, _end) elif can_walk(state.board, *target): def _change_level(val, caller): if val == 66: state.change_level(-1) elif val == 99: state.change_level(1) return _end(caller) if is_active_tile(val): state.player.move(*target, partial(_change_level, val)) else: state.player.move(*target, _end) elif is_door(val): if is_locked(state.board.get(*target)): if state.player.keys: unlock_door(state, target) pyxel.play(3, 53) else: pyxel.play(3, 54) else: open_door(state, target) pyxel.play(3, 49) state.player.wait(FPS * 0.3, _end) elif is_wall(val) or state.board.outside(*target): state.player.bump_to(target, _end) elif is_hole(val): if can_teleport(state): target = tuple(sum(e) for e in zip(target, delta)) for _ in range(50): state.particles.append( Molecule(_center(state.player.pos), _center(target), TPV) ) state.player.teleport(*target, _end, TPV) else: state.player.bump_to(target, _end) else: state.player.wait(FPS * 0.3, _end)