클리커에서 집·일꾼 방치형 구조로 전환
거품은 이제 클릭이 아니라 바다에 있는 생물이 시간에 따라 번다. 화면 가장자리에
깔아 두는 위젯인데 클릭이 주된 수입원이면 연타가 최적 플레이가 되어 형태와
어긋난다. 클릭 수익과 클릭 업그레이드를 걷어내고 업그레이드는 전부 생산 배율로
바꿨다. 물을 만지면 거품이 퍼지지만 얻는 것은 없다.
격자 칸을 차지하는 것은 집뿐이고, 생물은 칸이 아니라 집에 산다(한 채당 3마리).
칸 → 집 → 생물 → 거품으로 한계가 두 겹 걸린다. 예전에는 생물과 장식이 같은
자원(칸)을 놓고 경쟁해서 최적 플레이가 늘 "장식을 사지 말 것"이었는데, 집과
일꾼으로 나누니 그 경쟁이 의존으로 바뀐다. 집은 같은 종류도 여러 채 지을 수 있고
거품을 벌지 않는다 — 정원과 생산을 한 물건이 주면 곱연산이 두 번 걸린다.
어느 생물이 어느 집에 사는지는 저장하지 않는다. 집은 정원만 주므로 어디 살든
결과가 같고, 저장하면 재배정과 인덱스 관리만 붙는다. 그릴 때 구역마다 배정한다.
그래서 저장 형식에서 생물은 위치 없이 {id: 마리 수}다. 옛 저장본은 그때의
장식을 집으로, 생물을 마릿수로 옮겨오고 정원이 모자라면 집을 세워 메운다.
수입이 생물에서만 나오므로 막다른 길을 두 곳에서 막았다. 마지막 생물은 내보낼 수
없고, 살던 생물이 갈 곳이 없어지는 집은 헐 수 없다.
집과 생물의 그림 형태를 갈랐다. 집 10채 중 8채가 생물과 같은 rock이어서 항아리와
거품돌이 색만 다른 같은 덩어리로 보였다. 집은 vessel/wreck/pillar만, 생물은
plant/rock/fish/glow만 쓴다. 헤엄치는 생물은 집을 도는 타원 궤도에 올라가고,
원점이 궤도를 따라 움직이므로 Y 정렬이 앞뒤를 알아서 바꿔준다 — 뒤로 돌면 집에
가렸다가 앞으로 나온다. 얕은 바다 생물이 거품돌과 해초뿐이라 이 움직임을 볼 수
없어서 구피를 넣었다.
실행해 보고 잡은 버그 셋:
- 저장본이 없으면 load_game이 그냥 반환해 빈 바다로 시작했다. 집도 생물도 없어
아무 일도 일어나지 않는다. 이제 새 게임을 시작한다.
- 창 높이·도킹·모니터 설정이 복원되지 않고 기본값으로 덮어써지고 있었다.
window_state에 미리 있던 키만 복사하던 것을 저장본에 있는 것을 전부 싣도록 고쳤다.
- 정보 바가 격자 첫 줄을 덮어 왼쪽 위에 놓인 것이 보이지 않았다. GRID_TOP 상수를
버리고 HUD가 잰 실제 바 높이를 받아 쓴다.
- main.gd가 초기화할 때 존재하지 않는 aquarium.rebuild()를 부르고 있었다.
스모크 테스트 159개.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uze4mF1NAGfFRio77cMFqg
This commit is contained in:
+11
-11
@@ -16,13 +16,10 @@ const OFFLINE_RATE := 0.5
|
||||
## 이보다 짧게 비운 건 "오프라인"으로 안 친다(창을 잠깐 껐다 켠 경우).
|
||||
const OFFLINE_MIN_SECONDS := 60
|
||||
|
||||
## 창 위치·표시 옵션. main.gd가 읽고 쓴다.
|
||||
var window_state := {
|
||||
"x": -1,
|
||||
"y": -1,
|
||||
"always_on_top": true,
|
||||
"click_through": false,
|
||||
}
|
||||
## 창 표시 옵션. main.gd가 _remember_window()로 채우고 _ready()에서 읽는다.
|
||||
## 기본값은 여기가 아니라 main.gd의 get(키, 기본값)에만 둔다. 두 군데 두면 어긋난다.
|
||||
## 지금 들어오는 키: always_on_top / click_through / edge_bottom / height / screen
|
||||
var window_state := {}
|
||||
|
||||
## 테스트처럼 실제 저장 파일을 건드리면 안 되는 상황에서 끈다.
|
||||
## 끄지 않으면 스모크 테스트가 종료될 때 초기화된 상태를 저장해 진행도를 날린다.
|
||||
@@ -86,14 +83,17 @@ func load_game() -> void:
|
||||
if data.is_empty():
|
||||
data = _read(BACKUP_PATH)
|
||||
if data.is_empty():
|
||||
# 저장본이 없다 = 이 컴퓨터에서 처음 켰다. 시작 집과 생물을 놓아준다.
|
||||
# 이게 없으면 빈 바다에서 시작해 아무 일도 일어나지 않는다.
|
||||
GameState.reset()
|
||||
return
|
||||
|
||||
GameState.from_dict(data.get("state", {}))
|
||||
|
||||
var win: Dictionary = data.get("window", {})
|
||||
for key in window_state:
|
||||
if win.has(key):
|
||||
window_state[key] = win[key]
|
||||
# 저장본에 있는 창 설정을 전부 실어 온다. 예전에는 window_state에 미리
|
||||
# 들어 있던 키만 복사해서, 높이·도킹·모니터 설정이 조용히 사라졌다.
|
||||
for key in data.get("window", {}):
|
||||
window_state[key] = data["window"][key]
|
||||
|
||||
_grant_offline(int(data.get("saved_at", 0)))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user