class Player(EntityLiving): def __init__(self, pos, options): self.hair_color = options[0] self.hair_length = options[1] self.body_color = options[2] self.tail_color = options[3] super().__init__(pos, "", 20) self.max_speed = 0.25 self.acceleration = 0.01 self.inventory = Inventory(5, 10) self.selected_slot = 0 self.anim_timer = 0 self.anim_frame = False self.anim_state = 0 self.anim_dir = 0 #Temp items for testing self.inventory.insert(ItemStack.itemstack_from_name("magicStaff")) self.inventory.insert(ItemStack.itemstack_from_name("pickaxe")) self.inventory.insert(ItemStack.itemstack_from_name("sword")) def load_images_for(self, directory): img_idle_l = Images.load_imageurl("img/player/" + directory + "/idle.png") img_idle_r = Images.flip_horizontal(img_idle_l) imgs_idle = (img_idle_l, img_idle_r) img_swim_1_l = Images.load_imageurl("img/player/" + directory + "/swim1.png") img_swim_1_u = Images.rotate(img_swim_1_l, -90) img_swim_1_r = Images.flip_horizontal(img_swim_1_l) img_swim_1_d = Images.rotate(img_swim_1_l, 90) imgs_swim_1 = (img_swim_1_l, img_swim_1_u, img_swim_1_r, img_swim_1_d) img_swim_2_l = Images.load_imageurl("img/player/" + directory + "/swim2.png") img_swim_2_u = Images.rotate(img_swim_2_l, -90) img_swim_2_r = Images.flip_horizontal(img_swim_2_l) img_swim_2_d = Images.rotate(img_swim_2_l, 90) imgs_swim_2 = (img_swim_2_l, img_swim_2_u, img_swim_2_r, img_swim_2_d) return (imgs_idle, imgs_swim_1, imgs_swim_2) def load_image(self): self.hair_images = self.load_images_for("hair/" + HAIR_COLORS[self.hair_color] + "/" + HAIR_LENGTHS[self.hair_length]) self.body_images = self.load_images_for("body/" + BODY_COLORS[self.body_color]) self.tail_images = self.load_images_for("tail/" + TAIL_COLORS[self.tail_color]) self.img = self.body_images[0][0] self.hair_img = self.hair_images[0][0] self.tail_img = self.tail_images[0][0] def update(self, world): old_chunk = self.get_chunk() hspeed = min(abs(self.vel[0] + self.acceleration * self.move_dir[0]), self.max_speed) * self.move_dir[0] vspeed = min(abs(self.vel[1] + self.acceleration * self.move_dir[1]), self.max_speed) * self.move_dir[1] self.vel = [hspeed, vspeed] super().update(world) self.update_image(world) #should this be before the super update? new_chunk = self.get_chunk() if new_chunk != old_chunk: world.load_chunks(new_chunk) def transition_to_anim_state(self, anim_state, world): self.transition_to_anim(anim_state, self.anim_dir, world) def transition_to_anim_dir(self, anim_dir, world): if self.anim_state == 0: #this isn't right- we want to go to anim_state 1 or 2 print("CLIPPY") anim_dir = anim_dir // 2 self.transition_to_anim(self.anim_state, anim_dir, world) def transition_to_anim(self, anim_state, anim_dir, world): new_img = self.body_images[anim_state][anim_dir] new_width = new_img.get_width() new_height = new_img.get_height() old_pos = [self.pos[0], self.pos[1]] old_width = self.bounding_box.width old_height = self.bounding_box.height self.bounding_box.width = new_width self.bounding_box.height = new_height width_shift = (new_width - old_width) / Game.BLOCK_SIZE / Game.SCALE height_shift = (new_height - old_height) / Game.BLOCK_SIZE / Game.SCALE #try aligning to each corner #top left if not self.check_collisions(world): self.set_anim(anim_state, anim_dir, new_img) return True """ #top right self.update_pos([self.pos[0] + width_shift, self.pos[1]]) if not self.check_collisions(world): self.set_anim(anim_state, anim_dir, new_img) return True #bottom left self.update_pos([self.pos[0], self.pos[1] + height_shift]) if not self.check_collisions(world): self.set_anim(anim_state, anim_dir, new_img) return True #bottom right self.update_pos([self.pos[0] + width_shift, self.pos[1] + height_shift]) if not self.check_collisions(world): self.set_anim(anim_state, anim_dir, new_img) return True """ #transition failed- don't change anything self.update_pos(old_pos) self.bounding_box.width = old_width self.bounding_box.height = old_height #print("FAIL", old_height, new_height, anim_state, anim_dir, self.anim_state, self.anim_dir) return False def set_anim(self, anim_state, anim_dir, new_img): #succeeded- actually set the animation self.anim_state = anim_state self.anim_dir = anim_dir if self.anim_state == 0: self.anim_timer = 0 def update_anim_timer(self, moving, world): max_time = ANIM_TIME_MOVING if moving else ANIM_TIME_STOPPED self.anim_timer += 1 if self.anim_timer >= max_time: self.anim_timer = 0 self.anim_frame = not self.anim_frame if self.anim_frame: self.transition_to_anim_state(2, world) else: self.transition_to_anim_state(1, world) def update_image(self, world): xvel = Game.cutoff(self.vel[0], 0.01) yvel = Game.cutoff(self.vel[1], 0.01) if xvel != 0 or yvel != 0: self.update_anim_timer(True, world) if xvel < 0: self.transition_to_anim_dir(0, world) elif xvel > 0: self.transition_to_anim_dir(2, world) elif yvel < 0: self.transition_to_anim_dir(1, world) elif yvel > 0: self.transition_to_anim_dir(3, world) else: if self.facing == Game.LEFT: anim_dir = 0 else: anim_dir = 1 self.transition_to_anim(0, anim_dir, world) if self.anim_state != 0: self.update_anim_timer(False, world) self.img = self.body_images[self.anim_state][self.anim_dir] self.hair_img = self.hair_images[self.anim_state][self.anim_dir] self.tail_img = self.tail_images[self.anim_state][self.anim_dir] def render(self, screen, pos): screen.blit(self.tail_img, pos) super().render(screen, pos) screen.blit(self.hair_img, pos) if self.attack is None: item = self.get_held_item() if item is not None: self.render_held_item(screen, pos, item) else: self.attack.render_actual(screen) def render_held_item(self, screen, pos, item): #calculate position of held item in player's hand based on animation state # as well as whether it's a placeable block if self.anim_state == 0: offset_y = Game.BLOCK_SIZE * Game.SCALE * 1 / 16 if self.anim_dir == 0: #left offset_x = Game.BLOCK_SIZE * Game.SCALE * -12 / 16 if item.can_place: offset_x += Game.BLOCK_SIZE * Game.SCALE * 2 / 16 else: img = item.imgs[0] else: #right offset_x = Game.BLOCK_SIZE * Game.SCALE * 20 / 16 if item.can_place: offset_x += Game.BLOCK_SIZE * Game.SCALE * -2 / 16 else: img = item.imgs[1] else: if self.anim_dir == 0: #left offset_x = Game.BLOCK_SIZE * Game.SCALE * 0 / 16 offset_y = Game.BLOCK_SIZE * Game.SCALE * 12 / 16 if self.anim_state == 2: offset_x += Game.BLOCK_SIZE * Game.SCALE * 1 / 16 if item.can_place: offset_y += Game.BLOCK_SIZE * Game.SCALE * -2 / 16 else: img = item.imgs[2] elif self.anim_dir == 1: #up offset_x = Game.BLOCK_SIZE * Game.SCALE * -12 / 16 offset_y = Game.BLOCK_SIZE * Game.SCALE * 0 / 16 if self.anim_state == 2: offset_y += Game.BLOCK_SIZE * Game.SCALE * 1 / 16 if item.can_place: offset_x += Game.BLOCK_SIZE * Game.SCALE * 2 / 16 else: img = item.imgs[0] elif self.anim_dir == 2: #right offset_x = Game.BLOCK_SIZE * Game.SCALE * 27 / 16 offset_y = Game.BLOCK_SIZE * Game.SCALE * 12 / 16 if self.anim_state == 2: offset_x -= Game.BLOCK_SIZE * Game.SCALE * 1 / 16 if item.can_place: offset_y += Game.BLOCK_SIZE * Game.SCALE * -2 / 16 else: img = item.imgs[3] else: #down offset_x = Game.BLOCK_SIZE * Game.SCALE * 12 / 16 offset_y = Game.BLOCK_SIZE * Game.SCALE * 27 / 16 if self.anim_state == 2: offset_y -= Game.BLOCK_SIZE * Game.SCALE * 1 / 16 if item.can_place: offset_x += Game.BLOCK_SIZE * Game.SCALE * -2 / 16 else: img = item.imgs[4] if item.can_place: img = item.imgs[0] offset_x += Game.BLOCK_SIZE * Game.SCALE * 1 / 4 offset_y += Game.BLOCK_SIZE * Game.SCALE * 1 / 4 screen.blit(img, [pos[0] + offset_x, pos[1] + offset_y]) def collide_with(self, entity, world): super().collide_with(entity, world) if isinstance(entity, ItemDrop): if self.inventory.insert(entity.get_itemstack()) == None: world.remove_entity(entity) def left_click_continuous(self, world, mouse_pos, viewport, background): self.break_block(world, pygame.mouse.get_pos(), viewport, background) self.do_attack(world, mouse_pos, viewport) def right_click_continuous(self, world, mouse_pos, viewport, background): item = self.get_held_item() block_pos = self.find_angle_pos(mouse_pos, viewport) if item is None: return item.use_continuous(world, self, mouse_pos, viewport) if item.can_place: #try to place the block #don't want to place a solid block over an entity if not background: entities = world.get_nearby_entities(self.get_chunk()) entities.append(self) #check against player too for entity in entities: if entity.collides(block_pos) and entity.background == background and World.get_block(item.name)["solid"]: return if world.get_block_at(block_pos, False) == "water" and \ (not background or world.get_block_at(block_pos, True) == "water"): world.set_block_at(block_pos, World.get_block(item.name), background) blockentity = item.data if blockentity is not None: blockentity.load_image() blockentity.set_pos(block_pos) blockentity.background = background world.create_entity(blockentity) self.remove_held_item() def right_click_discrete(self, world, mouse_pos, viewport, background): item = self.get_held_item() block_pos = self.find_angle_pos(mouse_pos, viewport) entities = world.get_nearby_entities(self.get_chunk()) for entity in entities: if entity.collides(block_pos) and entity.background == background: if entity.interact(self, item): return if item is None: return item.use_discrete(world, self, mouse_pos, viewport) def left_click_discrete(self, world, mouse_pos, viewport, background): pass def do_attack(self, world, mouse_pos, viewport): if self.attack is not None: return held_item = self.get_held_item() if held_item is not None: damage = held_item.get_attack_damage() knockback = held_item.get_knockback() reach = ent.DamageSourceSweep.DEFAULT_REACH #TODO else: damage = ent.DamageSource.DEFAULT_ATTACK knockback = ent.DamageSource.DEFAULT_KNOCKBACK reach = ent.DamageSourceSweep.DEFAULT_REACH pos = self.pos[:] angle = self.find_angle(mouse_pos, viewport) self.attack = DamageSourceSweep(pos, damage, knockback, reach, angle, held_item, self, 30) world.create_entity(self.attack) def get_held_item(self): return self.inventory[0][self.selected_slot] def remove_held_item(self): item = self.get_held_item() item.count -= 1 if item.count == 0: self.inventory[0][self.selected_slot] = None def get_break_distance(self): #extend with certain items? return BREAK_DIST def find_angle(self, mouse_pos, viewport): #find nearest breakable block based on angle from player pos to mouse pos (raycasting?) x_diff = Convert.viewport_to_pixel(mouse_pos[0], viewport, 0) - self.bounding_box.centerx y_diff = Convert.viewport_to_pixel(mouse_pos[1], viewport, 1) - self.bounding_box.centery angle = math.atan2(y_diff, x_diff) return angle def find_pos(self, angle, offset, close_pos, max_dist): #in pixels dist = math.hypot(close_pos[0] - offset[0], close_pos[1] - offset[1]) capped_dist = min(dist, max_dist) return [offset[0] + capped_dist * math.cos(angle), offset[1] + capped_dist * math.sin(angle)] def find_angle_pos(self, mouse_pos, viewport): angle = self.find_angle(mouse_pos, viewport) return Convert.pixels_to_world(self.find_pos(angle, self.pixel_pos(True), Convert.viewport_to_pixels(mouse_pos, viewport), self.get_break_distance())) def break_block(self, world, mouse_pos, viewport, background): block_pos = self.find_angle_pos(mouse_pos, viewport) chunk = world.loaded_chunks.get(Convert.world_to_chunk(block_pos[0])[1]) #if there's a foreground block covering the background, don't break anything if background and world.get_block_at(block_pos, False) != "water": return block = World.get_block(world.get_block_at(block_pos, background)) held_item = self.get_held_item() if held_item is None: harvest_level = 0 break_speed = 1 else: harvest_level = held_item.get_harvest_level() break_speed = held_item.get_break_speed() if (not block["breakable"]) or (block["harvestlevel"] > harvest_level): return block_to_break = None breaking_blocks = world.breaking_blocks[background] for breaking_block in breaking_blocks: if breaking_block["pos"] == block_pos: block_to_break = breaking_block if block_to_break is None: block_to_break = {"pos": block_pos, "name": block["name"], "progress": 0, "breaktime": block["breaktime"]} breaking_blocks.append(block_to_break) block_to_break["progress"] += 2 * break_speed if block_to_break["progress"] >= block_to_break["breaktime"]: #remove the block breaking_blocks.remove(block_to_break) chunk.set_block_at(Convert.world_to_chunk(block_pos[0])[0], block_pos[1], World.get_block("water"), background) blockentity = None if block["entity"] != "": #remove the associated entity for entity in chunk.entities: if type(entity).__name__ == block["entity"] and [int(entity.pos[0]), int(entity.pos[1])] == block_pos: chunk.entities.remove(entity) blockentity = entity break chunk.entities.append(ItemDrop(block_pos, block["name"], blockentity)) def get_color(self, background): if background: return (192, 192, 192, 128) else: return (255, 255, 255, 128) def render_break_preview(self, background, world, block, block_pos, screen, viewport): chunk = world.loaded_chunks.get(Convert.world_to_chunk(block_pos[0])[1]) blockimg = world.get_block_render(World.get_block_id(block["name"]), block_pos, block["connectedTexture"], background, chunk, background).copy() mask = pygame.mask.from_surface(blockimg) olist = mask.outline() polysurface = pygame.Surface((Game.BLOCK_SIZE * Game.SCALE, Game.BLOCK_SIZE * Game.SCALE), pygame.SRCALPHA) color = self.get_color(background) pygame.draw.polygon(polysurface, color, olist, 0) screen.blit(polysurface, Convert.world_to_viewport(block_pos, viewport)) def render_block_preview(self, background, held_item, world, block_pos, screen, viewport): held_block = World.get_block(held_item.name) chunk = world.loaded_chunks.get(Convert.world_to_chunk(block_pos[0])[1]) blockimg = world.get_block_render(World.get_block_id(held_block["name"]), block_pos, held_block["connectedTexture"], background, chunk, background).copy() mask = pygame.mask.from_surface(blockimg) olist = mask.outline() polysurface = pygame.Surface((Game.BLOCK_SIZE * Game.SCALE, Game.BLOCK_SIZE * Game.SCALE), pygame.SRCALPHA) screen.blit(polysurface, Convert.world_to_viewport(block_pos, viewport)) collides = False entities = world.get_nearby_entities(self.get_chunk()) entities.append(self) for entity in entities: if entity.collides(block_pos) and entity.background == background: collides = True color = self.get_color(background) if collides and World.get_block(held_block["name"])["solid"]: color = (color[0], 0, 0, color[3]) pygame.draw.polygon(polysurface, color, olist, 0) blockimg.blit(polysurface, (0, 0), special_flags=pygame.BLEND_RGBA_MULT) screen.blit(blockimg, Convert.world_to_viewport(block_pos, viewport)) def draw_block_highlight(self, world, mouse_pos, viewport, screen, shift): #if player can break the block at the position, highlight it #if player is holding a block and can place it, render a preview block_pos = self.find_angle_pos(mouse_pos, viewport) held_item = self.get_held_item() if held_item is None: harvest_level = 0 else: harvest_level = held_item.get_harvest_level() block = World.get_block(world.get_block_at(block_pos, shift)) samewater = block["name"] == "water" fgwater = World.get_block(world.get_block_at(block_pos, False))["name"] == "water" if block["breakable"] and block["harvestlevel"] <= harvest_level and (not shift or fgwater): self.render_break_preview(shift, world, block, block_pos, screen, viewport) elif held_item is not None and held_item.can_place and samewater: self.render_block_preview(shift, held_item, world, block_pos, screen, viewport) def change_slot(self, direction): if direction: self.selected_slot += 1 if self.selected_slot >= len(self.inventory[0]): self.selected_slot -= len(self.inventory[0]) else: self.selected_slot -= 1 if self.selected_slot < 0: self.selected_slot += len(self.inventory[0]) def die(self, world): self.health = self.max_health #TODO: only create grave at nearest empty foreground space world.set_block_at([int(self.pos[0]), int(self.pos[1])], World.get_block("grave"), False) #TODO: fill it up with items and clear inventory #TODO: respawn
class Player(Entity): def __init__(self, pos, imageurl): super(Player, self).__init__(pos, imageurl) self.max_health = 20 self.health = 18 self.max_speed = 0.25 self.acceleration = 0.01 #fiddle with this until it seems good self.inventory = Inventory(5, 10) self.selected_slot = 0 #Temp items for testing self.inventory.insert(ItemStack.itemstack_from_name("magicStaff")) self.inventory.insert(ItemStack.itemstack_from_name("pickaxe")) def update(self, world): old_chunk = Convert.world_to_chunk(self.pos[0])[1] hspeed = min(abs(self.vel[0] + self.acceleration * self.dir[0]), self.max_speed) * self.dir[0] vspeed = min(abs(self.vel[1] + self.acceleration * self.dir[1]), self.max_speed) * self.dir[1] self.vel = [hspeed, vspeed] super(Player, self).update(world) new_chunk = Convert.world_to_chunk(self.pos[0])[1] if new_chunk != old_chunk: world.load_chunks(new_chunk) entities = self.get_nearby_entities(world) for entity in entities: if(self.bounding_box.colliderect(entity.bounding_box)): if isinstance(entity, ItemDrop): if self.inventory.insert(entity.get_itemstack()) == None: world.loaded_chunks.get(entity.get_chunk()).entities.remove(entity) def get_nearby_entities(self, world): entities = list(world.loaded_chunks.get(Convert.world_to_chunk(self.pos[0])[1]).entities) entities += world.loaded_chunks.get(Convert.world_to_chunk(self.pos[0])[1] - 1).entities entities += world.loaded_chunks.get(Convert.world_to_chunk(self.pos[0])[1] + 1).entities return entities def right_click_continuous(self, world, mouse_pos, viewport, background): item = self.inventory[0][self.selected_slot] block_pos = self.find_angle_pos(mouse_pos, viewport) if item is None: return item.use_continuous(world, self, mouse_pos, viewport) if item.can_place: #try to place the block #don't want to place a solid block over an entity if not background: entities = self.get_nearby_entities(world) entities.append(self) #check against player too for entity in entities: if entity.collides(block_pos) and entity.background == background and World.get_block(item.name)["solid"]: return if world.get_block_at(block_pos, False) == "water" and \ (not background or world.get_block_at(block_pos, True) == "water"): world.set_block_at(block_pos, World.get_block(item.name), background) blockentity = item.data if blockentity is not None: blockentity.load_image() blockentity.set_pos(block_pos) blockentity.background = background world.create_entity(blockentity) item.count -= 1 if item.count == 0: self.inventory[0][self.selected_slot] = None def right_click_discrete(self, world, mouse_pos, viewport, background): item = self.inventory[0][self.selected_slot] block_pos = self.find_angle_pos(mouse_pos, viewport) entities = self.get_nearby_entities(world) for entity in entities: if entity.collides(block_pos) and entity.background == background: if entity.interact(self, item): return if item is None: return item.use_discrete(world, self, mouse_pos, viewport) def get_break_distance(self): #extend with certain items? return BREAK_DIST def find_angle(self, mouse_pos, viewport): #find nearest breakable block based on angle from player pos to mouse pos (raycasting?) x_diff = Convert.viewport_to_pixel(mouse_pos[0], viewport, 0) - self.bounding_box.centerx y_diff = Convert.viewport_to_pixel(mouse_pos[1], viewport, 1) - self.bounding_box.centery angle = math.atan2(y_diff, x_diff) return angle def find_pos(self, angle, offset, close_pos, max_dist): #in pixels dist = math.hypot(close_pos[0] - offset[0], close_pos[1] - offset[1]) capped_dist = min(dist, max_dist) return [offset[0] + capped_dist * math.cos(angle), offset[1] + capped_dist * math.sin(angle)] def find_angle_pos(self, mouse_pos, viewport): angle = self.find_angle(mouse_pos, viewport) return Convert.pixels_to_world(self.find_pos(angle, self.pixel_pos(True), Convert.viewport_to_pixels(mouse_pos, viewport), self.get_break_distance())) def break_block(self, world, mouse_pos, viewport, background): block_pos = self.find_angle_pos(mouse_pos, viewport) chunk = world.loaded_chunks.get(Convert.world_to_chunk(block_pos[0])[1]) #if there's a foreground block covering the background, don't break anything if background and world.get_block_at(block_pos, False) != "water": return block = World.get_block(world.get_block_at(block_pos, background)) held_item = self.inventory[0][self.selected_slot] if held_item is None: harvest_level = 0 break_speed = 1 else: harvest_level = held_item.get_harvest_level() break_speed = held_item.get_break_speed() if (not block["breakable"]) or (block["harvestlevel"] > harvest_level): return block_to_break = None breaking_blocks = world.breaking_blocks[background] for breaking_block in breaking_blocks: if breaking_block["pos"] == block_pos: block_to_break = breaking_block if block_to_break is None: block_to_break = {"pos": block_pos, "name": block["name"], "progress": 0, "breaktime": block["breaktime"]} breaking_blocks.append(block_to_break) block_to_break["progress"] += 2 * break_speed if block_to_break["progress"] >= block_to_break["breaktime"]: #remove the block breaking_blocks.remove(block_to_break) chunk.set_block_at(Convert.world_to_chunk(block_pos[0])[0], block_pos[1], World.get_block("water"), background) blockentity = None if block["entity"] != "": #remove the associated entity for entity in chunk.entities: if type(entity).__name__ == block["entity"] and [int(entity.pos[0]), int(entity.pos[1])] == block_pos: chunk.entities.remove(entity) blockentity = entity break chunk.entities.append(ItemDrop(block_pos, block["name"], block["image"], blockentity)) def get_color(self, background): if background: return (192, 192, 192, 128) else: return (255, 255, 255, 128) def render_break_preview(self, background, world, block, block_pos, screen, viewport): blockimg = world.get_block_render(World.get_block_id(block["name"]), block_pos, block["connectedTexture"], background, background).copy() mask = pygame.mask.from_surface(blockimg) olist = mask.outline() polysurface = pygame.Surface((Game.BLOCK_SIZE * Game.SCALE, Game.BLOCK_SIZE * Game.SCALE), pygame.SRCALPHA) color = self.get_color(background) pygame.draw.polygon(polysurface, color, olist, 0) screen.blit(polysurface, Convert.world_to_viewport(block_pos, viewport)) def render_block_preview(self, background, held_item, world, block_pos, screen, viewport): held_block = World.get_block(held_item.name) blockimg = world.get_block_render(World.get_block_id(held_block["name"]), block_pos, held_block["connectedTexture"], background, background).copy() mask = pygame.mask.from_surface(blockimg) olist = mask.outline() polysurface = pygame.Surface((Game.BLOCK_SIZE * Game.SCALE, Game.BLOCK_SIZE * Game.SCALE), pygame.SRCALPHA) screen.blit(polysurface, Convert.world_to_viewport(block_pos, viewport)) collides = False entities = self.get_nearby_entities(world) entities.append(self) for entity in entities: if entity.collides(block_pos) and entity.background == background: collides = True color = self.get_color(background) if collides and World.get_block(held_block["name"])["solid"]: color = (color[0], 0, 0, color[3]) pygame.draw.polygon(polysurface, color, olist, 0) blockimg.blit(polysurface, (0, 0), special_flags=pygame.BLEND_RGBA_MULT) screen.blit(blockimg, Convert.world_to_viewport(block_pos, viewport)) def draw_block_highlight(self, world, mouse_pos, viewport, screen, shift): #if player can break the block at the position, highlight it #if player is holding a block and can place it, render a preview block_pos = self.find_angle_pos(mouse_pos, viewport) held_item = self.inventory[0][self.selected_slot] if held_item is None: harvest_level = 0 else: harvest_level = held_item.get_harvest_level() block = World.get_block(world.get_block_at(block_pos, shift)) samewater = block["name"] == "water" fgwater = World.get_block(world.get_block_at(block_pos, False))["name"] == "water" if block["breakable"] and block["harvestlevel"] <= harvest_level and (not shift or fgwater): self.render_break_preview(shift, world, block, block_pos, screen, viewport) elif held_item is not None and held_item.can_place and samewater: self.render_block_preview(shift, held_item, world, block_pos, screen, viewport) def render(self, screen, pos): #TODO: fancy animations here screen.blit(self.img, pos) item = self.inventory[0][self.selected_slot] if item is not None: screen.blit(item.img, [pos[0] - (Game.BLOCK_SIZE * Game.SCALE * 5 / 8), pos[1] + (Game.BLOCK_SIZE * Game.SCALE / 16)]) def change_slot(self, direction): if direction: self.selected_slot += 1 if self.selected_slot >= len(self.inventory[0]): self.selected_slot -= len(self.inventory[0]) else: self.selected_slot -= 1 if self.selected_slot < 0: self.selected_slot += len(self.inventory[0])