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
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 load(self, blocks): self.surface = pg.Surface((CHUNK_W_PX, CHUNK_W_PX), SRCALPHA) for y in range(self.y, min(self.y + CHUNK_W, blocks.shape[0])): for x in range(self.x, min(self.x + CHUNK_W, blocks.shape[1])): val = blocks[y][x] # negative ID signifies a multiblock if val < 0: # Find topleft of multiblock using global coords x_, y_ = game_vars.get_topleft(x, y) val = blocks[y_][x_] # Make x and y relative to the chunk's topleft corner x_ -= self.x y_ -= self.y else: # Make x and y relative to the chunk's topleft corner x_ = x - self.x y_ = y - self.y if val > 0: tile = game_vars.tiles[val] # TODO: Air light self.surface.blit(tile.image, (x_ * BLOCK_W, y_ * BLOCK_W)) if tile.updates: self.updates[(x_, y_)] = val if tile.img_updates: self.img_updates[(x_, y_)] = val if tile.emits_light: self.lights[(x_, y_)] = val # TODO: Block light pg.draw.rect(self.surface, (0, 0, 0), (0, 0, CHUNK_W_PX, CHUNK_W_PX), 2)
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))
def destroy_block(self, x, y): x, y = game_vars.get_topleft(x, y) tile_id = self.blocks[y][x] tile = game_vars.tiles[tile_id] # Destroy all parts w, h = tile.dim self.blocks[y:y + h, x:x + w] = [[AIR] * w] * h # Redraw block pg.draw.rect(self.map, (64, 64, 255), (x, y, *tile.dim)) light_arr = pg.surfarray.pixels_alpha(self.light) light_arr[x:x + tile.dim[0], y:y + tile.dim[1]] = [[0] * tile.dim[1]] * tile.dim[0] # Update data self.remove_block(x, y, tile.idx) self.manager.block_change(x, y, tile_id, False)
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
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
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