Distinct icons for wheat / corn / potato / strawberry harvests
Wheat + corn both produce TYPE_GRAIN; potato + strawberry both produce TYPE_VEGETABLE. Until now they rendered identically (yellow stalks for both grains, green-leafed root for both vegetables) since shape was driven by item_type alone. Added an Item.subtype field that carries the origin crop_kind through harvest. draw_item_shape dispatches on subtype FIRST then falls back to item_type — so storage filters (which match on item_type) still treat wheat+corn as one Grain category and potato+strawberry as one Vegetable category, but the visuals are now distinct. New procedural shapes: - wheat: 3 yellow stalks with grain-heads (same as existing grain) - corn: yellow cob with kernel dots wrapped in green husk leaves - potato: 2 brown overlapping lumps with sprout-eye dots - strawberry: red heart-shape body with green calyx + yellow seeds Crop.on_harvest_tick assigns subtype = crop_kind on spawn. SaveSystem._spawn_item now round-trips subtype through saves. Pawn carry indicator + Item._draw both pass subtype to draw_item_shape.
This commit is contained in:
parent
c7f97e2c7a
commit
413054157a
4 changed files with 97 additions and 3 deletions
|
|
@ -407,6 +407,8 @@ func _spawn_item(world_scene: Node, d: Dictionary) -> void:
|
|||
Vector2i(int(d.get("tile_x", 0)), int(d.get("tile_y", 0)))
|
||||
)
|
||||
ent.quality = int(d.get("quality", 1)) as Item.Quality
|
||||
ent.subtype = StringName(d.get("subtype", ""))
|
||||
ent.queue_redraw()
|
||||
|
||||
|
||||
func _spawn_wall(world_scene: Node, d: Dictionary) -> void:
|
||||
|
|
|
|||
|
|
@ -109,6 +109,11 @@ func on_harvest_tick() -> void:
|
|||
var it: Item = ITEM_SCENE.instantiate()
|
||||
get_parent().add_child(it)
|
||||
it.setup(item_type, 1, tile)
|
||||
# Carry the crop_kind through as a visual subtype so wheat / corn /
|
||||
# potato / strawberry each render distinctly, while item_type stays
|
||||
# generic (TYPE_GRAIN / TYPE_VEGETABLE) for stockpile filter purposes.
|
||||
it.subtype = crop_kind
|
||||
it.queue_redraw()
|
||||
stage = Stage.TILLED
|
||||
stage_progress = 0
|
||||
_refresh_sprite_region()
|
||||
|
|
|
|||
|
|
@ -84,6 +84,13 @@ enum Quality { SHODDY, NORMAL, EXCELLENT, MASTERWORK, LEGENDARY }
|
|||
@export var stack_size: int = 1
|
||||
@export var quality: Quality = Quality.NORMAL
|
||||
|
||||
## Visual subtype within the broader item_type. Lets multiple harvested produce
|
||||
## share one storage-filter category (TYPE_GRAIN matches both wheat AND corn)
|
||||
## while still rendering distinctly. Empty string = use item_type's default
|
||||
## shape. Set by the spawning code (Crop.on_harvest_tick assigns "wheat"/"corn"
|
||||
## /"potato"/"strawberry" based on crop_kind).
|
||||
@export var subtype: StringName = &""
|
||||
|
||||
var tile: Vector2i = Vector2i.ZERO
|
||||
|
||||
## When true the on-floor visual is suppressed; the carrying pawn renders the
|
||||
|
|
@ -154,6 +161,7 @@ func to_dict() -> Dictionary:
|
|||
return {
|
||||
"class_id": &"item",
|
||||
"type": String(item_type),
|
||||
"subtype": String(subtype),
|
||||
"stack_size": stack_size,
|
||||
"tile_x": tile.x,
|
||||
"tile_y": tile.y,
|
||||
|
|
@ -167,6 +175,7 @@ func to_dict() -> Dictionary:
|
|||
static func from_dict(d: Dictionary) -> Dictionary:
|
||||
return {
|
||||
"type": StringName(d.get("type", "wood")),
|
||||
"subtype": StringName(d.get("subtype", "")),
|
||||
"stack_size": int(d.get("stack_size", 1)),
|
||||
"tile_x": int(d.get("tile_x", 0)),
|
||||
"tile_y": int(d.get("tile_y", 0)),
|
||||
|
|
@ -187,8 +196,86 @@ static func from_dict(d: Dictionary) -> Dictionary:
|
|||
## etc. Atlas-backed types (wood / stone / plank / iron_ore / gold) also have
|
||||
## a shape here so the carry indicator works for them — the on-floor visual
|
||||
## still uses the bundle icon via the Sprite2D child path.
|
||||
static func draw_item_shape(target: CanvasItem, t: StringName) -> bool:
|
||||
static func draw_item_shape(target: CanvasItem, t: StringName, sub: StringName = &"") -> bool:
|
||||
var dark := Color(0.10, 0.07, 0.05, 0.85) # shared outline
|
||||
# Subtype dispatch — lets wheat / corn / potato / strawberry render
|
||||
# distinctly even though they share TYPE_GRAIN or TYPE_VEGETABLE for
|
||||
# storage-filter purposes. Falls through to the type dispatch if subtype
|
||||
# is unrecognised so existing items don't blank out.
|
||||
match sub:
|
||||
&"wheat":
|
||||
# Yellow stalks with grain heads — same as default TYPE_GRAIN shape.
|
||||
var stalk := Color(0.85, 0.70, 0.20)
|
||||
var tie := Color(0.55, 0.35, 0.10)
|
||||
target.draw_rect(Rect2(-4.0, -6.0, 1.5, 12.0), stalk)
|
||||
target.draw_rect(Rect2(-0.75, -6.0, 1.5, 12.0), stalk)
|
||||
target.draw_rect(Rect2(2.5, -6.0, 1.5, 12.0), stalk)
|
||||
target.draw_circle(Vector2(-3.2, -5.0), 1.2, Color(0.95, 0.78, 0.25))
|
||||
target.draw_circle(Vector2(0.0, -5.5), 1.2, Color(0.95, 0.78, 0.25))
|
||||
target.draw_circle(Vector2(3.2, -5.0), 1.2, Color(0.95, 0.78, 0.25))
|
||||
target.draw_rect(Rect2(-5.0, 0.0, 10.0, 2.0), tie)
|
||||
return true
|
||||
&"corn":
|
||||
# Corn cob — yellow body with rows of kernel dots + green husk.
|
||||
var husk := Color(0.30, 0.65, 0.20)
|
||||
var cob := Color(0.95, 0.82, 0.30)
|
||||
var kernel_dark := Color(0.70, 0.55, 0.15)
|
||||
# Husk leaves splayed out at the top.
|
||||
var husk_l: PackedVector2Array = PackedVector2Array([Vector2(-4.0, -5.0), Vector2(-2.0, -2.0), Vector2(-5.0, -1.0)])
|
||||
var husk_r: PackedVector2Array = PackedVector2Array([Vector2(4.0, -5.0), Vector2(2.0, -2.0), Vector2(5.0, -1.0)])
|
||||
target.draw_colored_polygon(husk_l, husk)
|
||||
target.draw_colored_polygon(husk_r, husk)
|
||||
# Cob body — vertical oval/rect with rounded corners.
|
||||
target.draw_rect(Rect2(-3.0, -4.0, 6.0, 10.0), cob)
|
||||
target.draw_circle(Vector2(0.0, 5.5), 3.0, cob)
|
||||
# Kernel dots — 2 columns × 3 rows for texture.
|
||||
for y in [-2.0, 0.0, 2.0, 4.0]:
|
||||
target.draw_rect(Rect2(-2.0, y, 1.5, 1.5), kernel_dark)
|
||||
target.draw_rect(Rect2(0.5, y, 1.5, 1.5), kernel_dark)
|
||||
# Cob outline (open at top because of husk).
|
||||
target.draw_arc(Vector2(0.0, 5.5), 3.0, 0.0, PI, 12, dark, 1.0)
|
||||
return true
|
||||
&"potato":
|
||||
# Two brown lumps with sprout-eye dots — pile of potatoes.
|
||||
var skin := Color(0.62, 0.45, 0.25)
|
||||
var skin_dark := Color(0.42, 0.28, 0.15)
|
||||
var eye := Color(0.25, 0.15, 0.05)
|
||||
# Two overlapping potato ovals.
|
||||
target.draw_circle(Vector2(-2.0, 1.0), 4.0, skin)
|
||||
target.draw_circle(Vector2(2.5, -0.5), 3.5, skin)
|
||||
# Outline.
|
||||
target.draw_arc(Vector2(-2.0, 1.0), 4.0, 0.0, TAU, 16, skin_dark, 1.0)
|
||||
target.draw_arc(Vector2(2.5, -0.5), 3.5, 0.0, TAU, 12, skin_dark, 1.0)
|
||||
# Eye dots.
|
||||
target.draw_circle(Vector2(-3.0, 0.0), 0.7, eye)
|
||||
target.draw_circle(Vector2(-0.5, 2.0), 0.6, eye)
|
||||
target.draw_circle(Vector2(3.5, -1.5), 0.7, eye)
|
||||
return true
|
||||
&"strawberry":
|
||||
# Classic red strawberry — heart-shape body with green calyx on top
|
||||
# and tiny yellow seed dots scattered on the surface.
|
||||
var berry := Color(0.88, 0.18, 0.20)
|
||||
var berry_dark := Color(0.62, 0.10, 0.10)
|
||||
var leaf := Color(0.25, 0.60, 0.20)
|
||||
var seed := Color(0.95, 0.85, 0.30)
|
||||
# Body — wider top tapering to a point at the bottom.
|
||||
var body: PackedVector2Array = PackedVector2Array([
|
||||
Vector2(-5.0, -1.0), Vector2(-3.5, -3.0), Vector2(3.5, -3.0),
|
||||
Vector2(5.0, -1.0), Vector2(3.0, 4.0), Vector2(0.0, 6.0), Vector2(-3.0, 4.0),
|
||||
])
|
||||
target.draw_colored_polygon(body, berry)
|
||||
# Body outline.
|
||||
target.draw_polyline(body + PackedVector2Array([body[0]]), berry_dark, 1.0)
|
||||
# Green calyx (leaves) on top.
|
||||
target.draw_rect(Rect2(-3.0, -5.0, 6.0, 2.0), leaf)
|
||||
var leaf_top: PackedVector2Array = PackedVector2Array([Vector2(-2.0, -5.0), Vector2(0.0, -7.0), Vector2(2.0, -5.0)])
|
||||
target.draw_colored_polygon(leaf_top, leaf)
|
||||
# Seed speckles.
|
||||
target.draw_circle(Vector2(-2.0, 1.0), 0.5, seed)
|
||||
target.draw_circle(Vector2(2.0, 1.0), 0.5, seed)
|
||||
target.draw_circle(Vector2(0.0, 3.0), 0.5, seed)
|
||||
return true
|
||||
# Fall through to type dispatch.
|
||||
match t:
|
||||
TYPE_BREAD:
|
||||
var crust := Color(0.62, 0.40, 0.18)
|
||||
|
|
@ -375,7 +462,7 @@ func _draw() -> void:
|
|||
var square := Rect2(Vector2(-half, -half), Vector2(half * 2, half * 2))
|
||||
|
||||
if not has_sprite:
|
||||
if not Item.draw_item_shape(self, item_type):
|
||||
if not Item.draw_item_shape(self, item_type, subtype):
|
||||
var hue := float(item_type.hash() % 360) / 360.0
|
||||
var fill := Color.from_hsv(hue, 0.6, 0.85)
|
||||
draw_rect(square, fill)
|
||||
|
|
|
|||
|
|
@ -1184,7 +1184,7 @@ func _draw() -> void:
|
|||
var ci_center := Vector2(7.0, -12.0)
|
||||
var ci_scale := 0.55
|
||||
draw_set_transform(ci_center, 0.0, Vector2(ci_scale, ci_scale))
|
||||
if not Item.draw_item_shape(self, carried_item.item_type):
|
||||
if not Item.draw_item_shape(self, carried_item.item_type, carried_item.subtype):
|
||||
var ci_hue := float(carried_item.item_type.hash() % 360) / 360.0
|
||||
var ci_color := Color.from_hsv(ci_hue, 0.6, 0.85)
|
||||
draw_rect(Rect2(-6, -6, 12, 12), ci_color)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue