🎉
This commit is contained in:
commit
94bfe2754e
107 changed files with 2557 additions and 0 deletions
141
ConveyorBelt.gd
Normal file
141
ConveyorBelt.gd
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
extends Building
|
||||
class_name ConveyorBelt
|
||||
|
||||
@export var belt_speed_tiles_per_second: float = 1.0
|
||||
@export var num_slots: int = 2
|
||||
|
||||
var items_on_belt: Array[Dictionary] = [] # [{ "item": ItemNode, "progress": float }]
|
||||
|
||||
@onready var belt_sprite: AnimatedSprite2D = $Sprite2D
|
||||
|
||||
|
||||
func _ready():
|
||||
super()
|
||||
_on_direction_changed()
|
||||
|
||||
if belt_sprite:
|
||||
belt_sprite.speed_scale = belt_speed_tiles_per_second
|
||||
belt_sprite.play("default")
|
||||
|
||||
|
||||
func _on_grid_position_changed():
|
||||
super()
|
||||
name = "ConveyorBelt_%s,%s" % [current_grid_pos.x, current_grid_pos.y]
|
||||
|
||||
|
||||
func _on_direction_changed():
|
||||
if belt_sprite:
|
||||
belt_sprite.rotation_degrees = calculate_rotation_degrees(direction)
|
||||
|
||||
|
||||
func can_accept_item() -> bool:
|
||||
if items_on_belt.is_empty():
|
||||
return true
|
||||
|
||||
if items_on_belt.size() >= num_slots:
|
||||
return false
|
||||
|
||||
var item_length_on_belt = 1.0 / float(num_slots)
|
||||
return items_on_belt.back().progress > item_length_on_belt
|
||||
|
||||
|
||||
func handle_item_entry(item: Item, initial_progress: float = 0.0):
|
||||
if not can_accept_item():
|
||||
print("Belt at %s received item but cannot accept. Item freed." % current_grid_pos)
|
||||
#item.queue_free()
|
||||
return
|
||||
|
||||
items_on_belt.append({"item": item, "progress": initial_progress})
|
||||
|
||||
var world_start_point = game_grid.tile_map.map_to_local(current_grid_pos) + (Vector2.ONE * game_grid.tile_map.rendering_quadrant_size) / 2
|
||||
|
||||
var world_end_point = game_grid.tile_map.map_to_local(current_grid_pos + direction) + (Vector2.ONE * game_grid.tile_map.rendering_quadrant_size) / 2
|
||||
|
||||
item.global_position = world_start_point.lerp(world_end_point, initial_progress)
|
||||
|
||||
|
||||
const dir_to_rotation: Dictionary = {
|
||||
Vector2i.RIGHT: 0.0, Vector2i.DOWN: 90.0, Vector2i.LEFT: 180.0, Vector2i.UP: 270.0
|
||||
}
|
||||
|
||||
|
||||
func calculate_rotation_degrees(dir: Vector2i) -> float:
|
||||
return dir_to_rotation.get(dir, 0.0)
|
||||
|
||||
|
||||
func _physics_process(delta: float):
|
||||
if items_on_belt.is_empty():
|
||||
return
|
||||
|
||||
_process_belt_movement(delta)
|
||||
_hand_off_items_if_ready()
|
||||
|
||||
|
||||
func _process_belt_movement(mut_delta: float):
|
||||
var world_start_point = game_grid.tile_map.map_to_local(current_grid_pos) + (Vector2.ONE * game_grid.tile_map.rendering_quadrant_size) / 2
|
||||
var world_end_point = game_grid.tile_map.map_to_local(current_grid_pos + direction) + (Vector2.ONE * game_grid.tile_map.rendering_quadrant_size) / 2
|
||||
|
||||
var segment_length_pixels = game_grid.tile_map.rendering_quadrant_size
|
||||
var current_pixel_speed = belt_speed_tiles_per_second * segment_length_pixels
|
||||
var item_length_on_belt = 1.0 / float(num_slots)
|
||||
|
||||
for i: int in items_on_belt.size():
|
||||
var item_data = items_on_belt[i]
|
||||
var item: Item = item_data.item
|
||||
var item_current_progress: float = item_data.progress
|
||||
|
||||
var distance_this_frame_progress = (current_pixel_speed * mut_delta) / segment_length_pixels
|
||||
var potential_new_progress = item_current_progress + distance_this_frame_progress
|
||||
|
||||
var target_progress_for_this_item = potential_new_progress
|
||||
|
||||
if i > 0:
|
||||
var prev_item_data = items_on_belt[i - 1]
|
||||
var prev_item = prev_item_data.item
|
||||
|
||||
var prev_item_progress = prev_item_data.progress
|
||||
|
||||
var max_allowed_front_progress = prev_item_progress - item_length_on_belt
|
||||
|
||||
target_progress_for_this_item = min(potential_new_progress, max_allowed_front_progress)
|
||||
|
||||
target_progress_for_this_item = max(item_current_progress, target_progress_for_this_item)
|
||||
|
||||
item_data.progress = max(0.0, target_progress_for_this_item)
|
||||
item.global_position = world_start_point.lerp(world_end_point, item_data.progress)
|
||||
|
||||
|
||||
func _hand_off_items_if_ready():
|
||||
if items_on_belt.is_empty():
|
||||
return
|
||||
#
|
||||
var items_to_remove_indices = []
|
||||
|
||||
for i in items_on_belt.size():
|
||||
var item_data = items_on_belt[i]
|
||||
var item_to_hand_off = item_data.item
|
||||
|
||||
if item_data.progress < 1.0:
|
||||
continue
|
||||
|
||||
var next_grid_cell_pos = current_grid_pos + direction
|
||||
var next_entity: Building = game_grid.get_content_at_grid(next_grid_cell_pos)
|
||||
|
||||
if next_entity:
|
||||
if next_entity.can_accept_item():
|
||||
item_data.progress -= 1.0
|
||||
#var overshoot_progress_on_old_belt = item_data.progress - 1.0
|
||||
next_entity.handle_item_entry(item_to_hand_off, item_data.progress)
|
||||
items_to_remove_indices.push_back(i)
|
||||
else:
|
||||
item_data.progress = 1.0
|
||||
item_to_hand_off.global_position = game_grid.tile_map.map_to_local(current_grid_pos + direction) + (Vector2.ONE * game_grid.tile_map.rendering_quadrant_size) / 2
|
||||
break
|
||||
else:
|
||||
item_data.progress = 1.0
|
||||
item_to_hand_off.global_position = game_grid.tile_map.map_to_local(current_grid_pos + direction) + (Vector2.ONE * game_grid.tile_map.rendering_quadrant_size) / 2
|
||||
break
|
||||
|
||||
for i_to_remove in range(items_to_remove_indices.size() - 1, -1, -1):
|
||||
var index_to_remove = items_to_remove_indices[i_to_remove]
|
||||
items_on_belt.remove_at(index_to_remove)
|
||||
Loading…
Add table
Add a link
Reference in a new issue