고착생물을 집으로, 생물은 해양동물만
거품돌·해초·산호·켈프·관벌레는 물고기가 깃드는 자리지 그 자체가 일꾼이 아니다. 실제로 물고기는 바위 틈과 해초 사이를 보금자리로 삼는다. 전부 집으로 옮기고, 생물에는 움직이는 해양동물만 남겼다. - 집이 자연 서식지(rock/plant)와 지어 올린 것(vessel/wreck/pillar) 두 갈래가 되면서 정원에 폭이 생겼다. 거품돌 1, 해초·산호 2, 켈프·관벌레 4, 지어 올린 것은 표준 3. - 빈 자리를 메우려 게·해마·새우를 넣어 층마다 생물 둘을 맞췄다. 소라게·해마·열수구 새우. 형태도 셋 새로 그렸다. - 형태 계통이 그대로 경계가 된다. 생물 fish/glow/crab/seahorse/shrimp, 집 rock/plant/vessel/wreck/pillar. 겹치지 않는 것을 테스트가 지킨다. - 예전에 생물로 사 둔 돌·해초는 같은 id의 집으로 그만큼 지어 준다. 그냥 버리면 사 둔 것이 조용히 사라진다. 버그 둘 _fish_area/_orbit_center가 생물 자리를 grid_rect(화면 테두리)로 잘랐다. 가로로 이어 스크롤하던 시절에는 화면 = 바다여서 맞았지만, 층이 옆으로 늘어선 지금은 뒤쪽 층 생물이 전부 첫 층 오른쪽 끝으로 끌려와 제 층에서 사라졌다. _home_bounds()가 그 집이 속한 층의 테두리를 돌려준다. _make_fish가 fish와 glow만 궤도에 올려, 새로 넣은 게·해마·새우가 제자리에 굳어 있었다. 고착생물이 전부 집으로 갔으므로 가드를 걷어냈다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -463,10 +463,8 @@ func _make_fish(entry: Dictionary) -> void:
|
||||
items.add_child(node)
|
||||
node.setup(d, "producer", -1, _fish_area(home, cell, slot), cell, _rng)
|
||||
|
||||
# 헤엄치는 것만 집 둘레를 돈다. 해초나 거품돌은 제자리에 붙어 있어야 한다.
|
||||
var shape := String(d.get("shape", "rock"))
|
||||
if shape != "fish" and shape != "glow":
|
||||
return
|
||||
# 생물은 모두 집 둘레를 돈다. 고착생물(해초·거품돌)은 이제 집 쪽으로 옮겼으므로
|
||||
# 여기 들어오는 것은 전부 헤엄치거나 걷는 해양동물이다.
|
||||
var house_index := int(entry.house)
|
||||
var cap: int = maxi(Catalog.capacity_of(String(GameState.houses[house_index].id)), 1)
|
||||
# 집마다 도는 방향을 바꿔 여러 채가 한 화면에 있어도 단조롭지 않게 한다.
|
||||
@@ -525,13 +523,23 @@ func _orbit_radius(home: Rect2, cell: Vector2) -> Vector2:
|
||||
## 중심을 옮기지 않고 매 프레임 위치만 자르면 물고기가 벽에 붙어 멈춘 것처럼 보인다.
|
||||
func _orbit_center(home: Rect2, cell: Vector2) -> Vector2:
|
||||
var r := _orbit_radius(home, cell)
|
||||
var g := grid_rect()
|
||||
var g := _home_bounds(home, cell)
|
||||
return Vector2(
|
||||
_squeeze(home.position.x + home.size.x * 0.5, g.position.x + r.x, g.end.x - r.x),
|
||||
_squeeze(home.end.y - cell.y * 0.10,
|
||||
g.position.y + cell.y * 0.9 + r.y, g.end.y - r.y))
|
||||
|
||||
|
||||
## 그 집이 속한 층의 테두리. 생물을 여기 안에 가둔다.
|
||||
## 예전에는 화면(grid_rect)에 맞춰 잘랐는데, 층이 옆으로 늘어선 지금 그렇게 하면
|
||||
## 뒤쪽 층의 생물이 전부 첫 층 오른쪽 끝으로 끌려와 제 층에서 사라진다.
|
||||
func _home_bounds(home: Rect2, cell: Vector2) -> Rect2:
|
||||
var z := Catalog.zone_of_column(int(floor(home.position.x / maxf(cell.x, 1.0))))
|
||||
var g := grid_rect()
|
||||
var width := Catalog.ZONE_COLUMNS * cell.x
|
||||
return Rect2(Vector2(z * width, g.position.y), Vector2(width, g.size.y))
|
||||
|
||||
|
||||
## 범위가 뒤집힐 만큼 좁으면(작은 창) 가운데로 보낸다. clampf는 그때 엉뚱한 값을 준다.
|
||||
func _squeeze(value: float, lo: float, hi: float) -> float:
|
||||
if lo > hi:
|
||||
@@ -552,8 +560,8 @@ func _fish_area(home: Rect2, cell: Vector2, slot: int) -> Rect2:
|
||||
var x := cx + spot.x * (home.size.x + cell.x * 0.9) + ring * cell.x * 0.28
|
||||
var base := home.end.y + spot.y * cell.y + ring * cell.y * 0.22
|
||||
|
||||
# 바다 밖으로 새어 나가지 않게 잡아둔다.
|
||||
var g := grid_rect()
|
||||
# 제 층 밖으로 새어 나가지 않게 잡아둔다.
|
||||
var g := _home_bounds(home, cell)
|
||||
x = clampf(x, g.position.x + cell.x * 0.5, g.end.x - cell.x * 0.5)
|
||||
base = clampf(base, g.position.y + cell.y * 0.6, g.end.y)
|
||||
return Rect2(Vector2(x - cell.x * 0.5, base - cell.y), cell)
|
||||
|
||||
@@ -142,6 +142,9 @@ func _draw() -> void:
|
||||
"plant": _draw_plant()
|
||||
"fish": _draw_fish()
|
||||
"glow": _draw_glow()
|
||||
"crab": _draw_crab()
|
||||
"seahorse": _draw_seahorse()
|
||||
"shrimp": _draw_shrimp()
|
||||
"vessel": _draw_vessel()
|
||||
"wreck": _draw_wreck()
|
||||
"pillar": _draw_pillar()
|
||||
@@ -416,3 +419,124 @@ func _draw_pillar() -> void:
|
||||
draw_set_transform(Vector2(0, -h), 0.0, Vector2(1.0, 0.34))
|
||||
draw_circle(Vector2.ZERO, w * 1.02, color.lightened(0.18))
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2.ONE)
|
||||
|
||||
|
||||
## 바닥을 걷는 게. 옆으로 벌어진 몸에 다리가 뻗고 집게가 앞을 짚는다.
|
||||
## 물고기와 실루엣이 확실히 달라야 한눈에 갈린다.
|
||||
func _draw_crab() -> void:
|
||||
var r := span.x * 0.26
|
||||
var step := sin(_t * 3.0 + _phase)
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2(_facing, 1.0))
|
||||
|
||||
# 다리. 좌우 세 쌍이 번갈아 짚는다.
|
||||
for side: float in [-1.0, 1.0]:
|
||||
for i in 3:
|
||||
var a := -0.35 + i * 0.42
|
||||
var lift := 0.12 if i % 2 == 0 else -0.12
|
||||
var swing := step * lift * side
|
||||
var knee := Vector2(cos(a + swing) * r * 1.05, side * r * (0.55 + i * 0.06))
|
||||
var foot := knee + Vector2(cos(a + swing) * r * 0.5, side * r * 0.55)
|
||||
draw_polyline(PackedVector2Array([Vector2(0, side * r * 0.25), knee, foot]),
|
||||
color.darkened(0.34), maxf(r * 0.14, 1.2), true)
|
||||
|
||||
# 집게 둘.
|
||||
for side: float in [-1.0, 1.0]:
|
||||
var base := Vector2(r * 0.85, side * r * 0.5)
|
||||
var tip := base + Vector2(r * 0.62, side * r * 0.18 + step * r * 0.1)
|
||||
draw_polyline(PackedVector2Array([Vector2(r * 0.3, side * r * 0.3), base, tip]),
|
||||
color.darkened(0.2), maxf(r * 0.18, 1.4), true)
|
||||
_fill(PackedVector2Array([
|
||||
tip + Vector2(-r * 0.1, -r * 0.22),
|
||||
tip + Vector2(r * 0.34, -r * 0.05),
|
||||
tip + Vector2(-r * 0.05, r * 0.22),
|
||||
]), color.lightened(0.1))
|
||||
|
||||
# 등딱지. 가로로 넓은 타원.
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2(_facing * 1.35, 0.92))
|
||||
draw_circle(Vector2.ZERO, r, color)
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2(_facing, 1.0))
|
||||
draw_circle(Vector2(-r * 0.1, -r * 0.22), r * 0.55, color.lightened(0.16))
|
||||
for side: float in [-1.0, 1.0]:
|
||||
draw_circle(Vector2(r * 0.5, side * r * 0.34), maxf(r * 0.12, 1.2),
|
||||
Color(0.06, 0.07, 0.09))
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2.ONE)
|
||||
|
||||
|
||||
## 선 채로 흔들리는 해마. 세로로 긴 S자가 곧 실루엣이다.
|
||||
func _draw_seahorse() -> void:
|
||||
var h := body_height * 0.9
|
||||
var w := span.x * 0.16
|
||||
var sway := sin(_t * 1.3 + _phase) * 0.22
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2(_facing, 1.0))
|
||||
|
||||
# 몸통. 아래로 갈수록 가늘어지며 꼬리가 안으로 말린다.
|
||||
var left := PackedVector2Array()
|
||||
var right := PackedVector2Array()
|
||||
var steps := 8
|
||||
for i in steps + 1:
|
||||
var f := float(i) / steps
|
||||
var bend := sin(f * PI * 1.15 + sway) * w * 1.5
|
||||
var p := Vector2(bend, -h * f)
|
||||
var half := w * (0.45 + sin(f * PI) * 0.75)
|
||||
left.append(p + Vector2(half, 0))
|
||||
right.append(p - Vector2(half, 0))
|
||||
right.reverse()
|
||||
_fill(left + right, color)
|
||||
|
||||
# 등지느러미와 주둥이, 눈.
|
||||
var head := Vector2(sin(PI * 1.15 + sway) * w * 1.5, -h)
|
||||
_fill(PackedVector2Array([
|
||||
head + Vector2(w * 0.4, w * 0.2),
|
||||
head + Vector2(w * 2.1, w * 0.05),
|
||||
head + Vector2(w * 0.5, -w * 0.5),
|
||||
]), color.darkened(0.15))
|
||||
draw_circle(head + Vector2(w * 0.35, -w * 0.15), maxf(w * 0.42, 1.2),
|
||||
Color(0.06, 0.07, 0.09))
|
||||
for i in 3:
|
||||
var f := 0.25 + i * 0.2
|
||||
var bend := sin(f * PI * 1.15 + sway) * w * 1.5
|
||||
_fill(PackedVector2Array([
|
||||
Vector2(bend - w * 0.8, -h * f),
|
||||
Vector2(bend - w * 2.0, -h * (f + 0.06)),
|
||||
Vector2(bend - w * 0.8, -h * (f + 0.12)),
|
||||
]), color.darkened(0.3))
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2.ONE)
|
||||
|
||||
|
||||
## 새우. 등이 굽고 더듬이가 길다. 꼬리를 튕겨 조금씩 물러난다.
|
||||
func _draw_shrimp() -> void:
|
||||
var l := span.x * 0.3
|
||||
var flick := sin(_t * 4.5 + _phase)
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2(_facing, 1.0))
|
||||
|
||||
# 더듬이. 실루엣의 절반을 차지한다.
|
||||
for side: float in [-0.35, 0.15]:
|
||||
draw_polyline(PackedVector2Array([
|
||||
Vector2(l * 0.6, side * l),
|
||||
Vector2(l * 1.3, side * l - l * 0.25 + flick * l * 0.06),
|
||||
Vector2(l * 1.9, side * l - l * 0.55 + flick * l * 0.12),
|
||||
]), Color(color.r, color.g, color.b, 0.7), maxf(l * 0.07, 1.0), true)
|
||||
|
||||
# 굽은 몸통.
|
||||
var body := PackedVector2Array()
|
||||
var steps := 7
|
||||
for i in steps + 1:
|
||||
var f := float(i) / steps
|
||||
var a := PI * 0.15 + f * PI * 0.75
|
||||
body.append(Vector2(cos(a) * l * 0.95, -sin(a) * l * 0.5 + l * 0.1))
|
||||
for i in range(steps, -1, -1):
|
||||
var f := float(i) / steps
|
||||
var a := PI * 0.15 + f * PI * 0.75
|
||||
body.append(Vector2(cos(a) * l * 0.62, -sin(a) * l * 0.16 + l * 0.1))
|
||||
_fill(body, color)
|
||||
|
||||
# 부채꼴 꼬리.
|
||||
var tail := Vector2(-l * 0.9, l * 0.05 + flick * l * 0.12)
|
||||
_fill(PackedVector2Array([
|
||||
Vector2(-l * 0.6, l * 0.08),
|
||||
tail + Vector2(-l * 0.4, -l * 0.3),
|
||||
tail + Vector2(-l * 0.5, l * 0.05),
|
||||
tail + Vector2(-l * 0.35, l * 0.35),
|
||||
]), color.darkened(0.25))
|
||||
draw_circle(Vector2(l * 0.68, -l * 0.12), maxf(l * 0.1, 1.2), Color(0.06, 0.07, 0.09))
|
||||
draw_set_transform(Vector2.ZERO, 0.0, Vector2.ONE)
|
||||
|
||||
Reference in New Issue
Block a user