def get_spawn_spaces(center, r, walking):
    # X range
    v1_min, v1_max = max(0, center[0] - r), min(game_vars.world_dim()[0] - 1,
                                                center[0] + r)
    # When calculating max, add 1 so that if we have only air but
    # there is a solid block just outside our range, we can still spawn
    # Y range
    v2_min, v2_max = max(0, center[1] - r), min(game_vars.world_dim()[1] - 1,
                                                center[1] + r + 1)
    air = {}

    # For all ranges, use max + 1 to be inclusive
    for v1 in range(v1_min, v1_max + 1):
        air_count = -1
        v2 = 0
        for v2 in reversed(range(v2_min, v2_max + 1)):
            block = game_vars.get_block_at(*(v1, v2) if walking else (v2, v1))
            if block != AIR:
                if air_count > 0:
                    # Coords of ground = current (solid) + 1 + air count
                    update_dict(v1, v2 + 1 + air_count, air_count, air)
                air_count = 0
            elif air_count != -1:
                air_count += 1
        if air_count > 0:
            # Coord of ground = current (air) + air count
            update_dict(v1, v2 + air_count, air_count, air)
    return air
Esempio n. 2
0
 def spawn(self):
     spawn = game_vars.world.spawn
     self.set_pos((spawn[0] * BLOCK_W, spawn[1] * BLOCK_W))
     for x in range(spawn[0], ceil(spawn[0] + self.dim[0])):
         for y in range(spawn[1], ceil(spawn[1] + self.dim[1])):
             if game_vars.get_block_at(x, y) not in game_vars.non_solid:
                 self.break_block(x, y)
Esempio n. 3
0
 def right_click(self):
     pos = pg.mouse.get_pos()
     global_pos = game_vars.global_mouse_pos()
     if not self.inventory.right_click(pos):
         block_x, block_y = game_vars.get_topleft(
             *[p // BLOCK_W for p in global_pos])
         tile = game_vars.tiles[game_vars.get_block_at(block_x, block_y)]
         # First attempt to activate the tile
         # Make sure we didn't click the same block more than once
         if tile.clickable and self.placement_range.collidepoint(*global_pos) and \
                 (not tile.has_ui or self.active_ui is None or self.active_ui.block_pos != [block_x, block_y]):
             if tile.activate((block_x, block_y)):
                 return
         # Then try to drop the cursor item
         if self.inventory.selected_item.is_item:
             # Check if we dropped an item
             drop = self.inventory.drop_item()
             if drop is not None:
                 # This determines if we clicked to the left or right of the player
                 left = global_pos[0] < self.rect.centerx
                 game_vars.drop_item(drop, left)
         # If there is no cursor item, use the current hotbar item
         else:
             item = self.inventory.get_current_item()
             if item.is_item:
                 item_obj = game_vars.items[item.item_id]
                 if item_obj.right_click and (self.first_swing
                                              or item_obj.auto_use):
                     self.first_swing = False
                     # Use item
                     item_obj.on_right_click()
                     self.item_used = item_obj
                     self.use_time = item_obj.use_time
Esempio n. 4
0
 def on_right_click(self):
     item = game_vars.player_inventory().get_current_item()
     if item.item_id != i.MAGIC_WAND:
         return
     entities = game_vars.handler.entities
     # Check if we clicked on a mage
     pos = game_vars.global_mouse_pos(blocks=False)
     for key, entity in entities.items():
         if isinstance(entity, Mobs.Mage) and entity.rect.collidepoint(pos):
             print("Selected mage")
             item.data = key.to_bytes(2, byteorder)
             entity.target = (-1, -1)
             return
     # Get the clicked on tile
     pos = game_vars.get_topleft(*game_vars.global_mouse_pos(blocks=True))
     tile_id = game_vars.get_block_at(*pos)
     # Check if we clicked on a pedestal
     if item.data and tile_id == t.PEDESTAL:
         key = int.from_bytes(item.data[:2], byteorder)
         if isinstance(entities.get(key), Mobs.Mage):
             print("Bound mage")
             entities[key].set_target(pos)
             entities[key].set_pos(pos[0] * BLOCK_W, (pos[1] - entities[key].dim[1]) * BLOCK_W)
         item.data = None
     # Check if we clicked on a portal
     elif tile_id == t.PORTAL:
         game_vars.tiles[t.PORTAL].summon(pos)
def get_spawn_spaces_with_hole(center, r_inner, r_outer, walking):
    # X range
    v1_min, v1_max = max(0, center[0] - r_outer), min(game_vars.world_dim()[0], center[0] + r_outer)
    # Y bounds
    v2_min1, v2_max1 = max(0, center[1] - r_outer), max(0, center[1] - r_inner)
    v2_min2 = min(game_vars.world_dim()[1], center[1] + r_inner)
    v2_max2 = min(game_vars.world_dim()[1], center[1] + r_outer)

    v2_range_full = (range(v2_min1, v2_max2))
    v2_range_parts = (range(v2_min1, v2_max1), range(v2_min2, v2_max2))
    air = {}

    def add_val(v1_, v2_, val):
        if v1_ not in air.keys():
            air[v1_] = {}
        air[v1_][v2_] = val

    for v1 in range(v1_min, v1_max):
        for v2_range in v2_range_full if abs(v1 - center[1]) <= r_inner else \
                v2_range_parts:
            air_count = 0
            hit_block = False
            v2 = 0
            for v2 in v2_range:
                block = game_vars.get_block_at(*(v1, v2) if walking else (v2, v1))
                if block != AIR:
                    hit_block = True
                    if air_count > 0:
                        add_val(v1, v2 - air_count, air_count)
                    air_count = 0
                elif hit_block:
                    air_count += 1
            if air_count > 0:
                add_val(v1, v2 - air_count, air_count)
    return air
Esempio n. 6
0
 def on_left_click(self):
     pos = game_vars.get_topleft(*game_vars.global_mouse_pos(blocks=True))
     item_id = game_vars.get_block_at(*pos)
     if item_id == t.PORTAL:
         data = game_vars.get_block_data(pos)
         if data:
             # TODO: ingame message system
             print("Magic Stored:", int.from_bytes(data, byteorder))
Esempio n. 7
0
 def get_space(self, x, y):
     tile_id = game_vars.get_block_at(x, y)
     if tile_id == t.PEDESTAL:
         data = game_vars.get_block_data((x, y))
         if data and len(data) > 2:
             item = game_vars.items[int.from_bytes(data[:2], byteorder)]
             if isinstance(item, ItemTypes.MagicContainer):
                 current_amnt = int.from_bytes(data[3:item.int_bytes + 3],
                                               byteorder)
                 return item.capacity - current_amnt
     return 0
Esempio n. 8
0
 def ai(self):
     self.time -= game_vars.dt
     # Check if we are standing on the ground
     if self.collisions[1] == 1:
         too_far = self.bound and not self.drag and abs(
             self.rect.centerx - self.target[0] * BLOCK_W) >= self.MAX_DX
         # Check if we are ready to start/stop moving
         if self.time <= 0 or too_far:
             # We were stopped
             if self.drag:
                 if self.bound:
                     self.a[0] = math.copysign(
                         self.stats.get_stat("acceleration"),
                         self.target[0] * BLOCK_W - self.rect.centerx)
                 else:
                     self.a[0] = self.stats.get_stat(
                         "acceleration") * random_sign()
                 self.drag = False
                 max_t = self.MAX_DX / self.stats.get_stat("max_speedx")
                 self.time = uniform(max_t / 3, max_t * .9)
             # We were moving
             else:
                 self.a[0] = 0
                 self.drag = True
                 self.time = uniform(1, 3)
         # Check if we need to jump
         if self.collisions[0] != 0:
             self.v[1] = -self.stats.get_stat("jump_speed")
             self.time = uniform(1, 3)
     # Increment magic
     self.magic = min(self.capacity,
                      self.magic + self.production * game_vars.dt)
     if self.magic >= 5 and self.bound and self.transfer_cooldown <= 0:
         x, y = game_vars.get_topleft(*self.target)
         tile_id = game_vars.get_block_at(x, y)
         if tile_id != tiles.PEDESTAL:
             self.target = (-1, -1)
         else:
             tile = game_vars.tiles[tile_id]
             transfer = min(self.production, self.magic,
                            tile.get_space(x, y))
             if transfer > 0:
                 game_vars.shoot_projectile(
                     self.P1(transfer, self.rect.center, (x, y)))
                 self.transfer_cooldown = 1
     elif self.transfer_cooldown > 0:
         self.transfer_cooldown -= game_vars.dt
Esempio n. 9
0
 def move(self):
     if super().move():
         return True
     x, y = game_vars.get_topleft(*self.target)
     tile_id = game_vars.get_block_at(x, y)
     if tile_id != tiles.PEDESTAL:
         return True
     else:
         tile = game_vars.tiles[tile_id]
         rect = pg.Rect((x * BLOCK_W, y * BLOCK_W),
                        [i * BLOCK_W for i in tile.dim])
         if abs(self.rect.centerx -
                rect.centerx) < self.HIT_RAD and abs(
                    self.rect.centery - rect.centery) < self.HIT_RAD:
             tile.add_magic(x, y, self.magic)
             return True
     return False
Esempio n. 10
0
 def break_block(self, block_x, block_y):
     # Make sure we aren't hitting air
     block_x, block_y = game_vars.get_topleft(block_x, block_y)
     block = game_vars.get_block_at(block_x, block_y)
     if block == AIR:
         return
     tile = game_vars.tiles[block]
     # Make sure this block does not have a ui open
     if self.active_ui is not None and self.active_ui.block_pos == [
             block_x, block_y
     ]:
         return False
     # Make sure the block is in range and check if we destroyed the block
     power = self.stats.get_stat("power")
     block_rect = Rect(block_x * BLOCK_W, block_y * BLOCK_W,
                       BLOCK_W * tile.dim[0], BLOCK_W * tile.dim[1])
     if self.placement_range.collidepoint(*block_rect.center) and tile.hit(
             block_x, block_y, power):
         return game_vars.break_block(block_x, block_y)
     return False
Esempio n. 11
0
    def tick(self, dt):
        self.time = (self.time + dt) % c.SEC_PER_DAY
        # Run auto save
        self.next_save -= game_vars.dt
        if self.next_save <= 0:
            self.save_progress = self.save_world(self.save_progress)
            if self.save_progress >= 1:
                self.save_progress = 0
                self.next_save = 30
                game_vars.player.write()
        # Update minimap
        pos = game_vars.player_pos(True)
        left, top = max(int(pos[0] - 10), 0), max(int(pos[1] - 10), 0)
        # Go through every row, column pair where the color is black
        section = pg.surfarray.pixels2d(self.map)[left:math.ceil(pos[0] + 10),
                                                  top:math.ceil(pos[1] + 10)]
        for x, y in zip(*np.where(section == 0)):
            map_color = game_vars.tiles[game_vars.get_block_at(
                left + x, top + y)].map_color
            section[x][y] = self.map.map_rgb(map_color)
        del section

        self.manager.tick(dt)