FishKing Internal Docs

🎣 힘겨루기 알고리즘

1 게임 상태 흐름 (State Machine)
💤IDLE대기
🎯CASTING캐스팅
🌊WAITING기다림
BITING힘겨루기
🔄REELING끌어올리기
🏆RESULT결과
💤
IDLE → CASTING
화면을 아래로 드래그 후 위로 플릭 (vy < -1.5) 시 캐스팅. 드래그 중 캐스팅 게이지 표시. 동시에 미끼·아이템 소모 처리.
🌊
CASTING → WAITING
찌 착수 애니메이션 완료 후 자동 전환. 대기 시간은 2,000 ~ 5,000ms (랜덤).
WAITING → BITING (힘겨루기 시작)
상자 스폰 확인 → 없으면 가중치 랜덤으로 물고기 선택 → startFishMovement() 호출하여 힘겨루기 시작.
🔄
BITING → REELING (성공 조건)
물고기 스태미나가 0 이하가 되면 REELING으로 전환.
💥
BITING → RESULT:실패 (줄 끊김)
텐션이 ±100을 초과하면 즉시 실패.
🏆
REELING → RESULT
릴링 진행도 100 도달 시 성공 / 0 도달 시 물고기 탈출(실패).
2 힘겨루기 핵심 알고리즘 (BITING)
2-1 · 물고기 힘 생성 — 매 1,500ms 갱신
fishForce = (random > 0.5 ? +1 : -1) × (random() × fish.force + fish.force × 0.5) × weightMultiplier
ℹ️
weightMultiplier는 실제 무게 결정 시 같이 계산되며 0.5 ~ 2.0 범위입니다. 무거운 물고기일수록 힘도 세집니다. 힘의 방향(±)은 왼쪽/오른쪽으로 텐션을 밀어붙이는 방향을 의미합니다.
2-2 · 텐션 업데이트 루프 — 매 50ms
absorbedFishForce = fishForce × (1 - forceAbsorption) netForce = absorbedFishForce + userForce tension += netForce if (tension >= 100 || tension <= -100) → 줄 끊김 (실패)

텐션은 절댓값 기준으로 ±100 범위를 넘지 않아야 합니다. 아래 바에서 초록 구간(안전지대)을 유지하는 것이 목표입니다.

-100 +100 -30 +30 0
위험 (줄 끊김) 안전지대 |tension| < 30 위험 (줄 끊김)
2-3 · 물고기 스태미나 감소
안전지대 |tension| < 30
drain = (100 / fish.stamina) × staminaDrainMulti
위험지대 |tension| ≥ 30
drain = (100 / fish.stamina) × staminaDrainMulti / 20
텐션을 안전지대(|tension| < 30)에 유지할수록 스태미나가 최대 20배 빠르게 감소합니다. 즉, 사용자는 물고기 힘에 맞서 텐션을 0 근처로 유지하는 것이 전략입니다. 스태미나 0이 되면 REELING 페이즈로 진입합니다.
⚠️
아이템 fishStaminaPenalty가 있으면 물고기 최초 스태미나가 감소된 상태로 시작합니다.
startStamina = max(1, 100 - fishStaminaPenalty × 100)
2-4 · 사용자 입력 (수평 스와이프)
delta = moveX - lastMoveX userForce = clamp(delta × 0.4, -4, +4) userForce = userForce × 0.75
  • 물고기가 오른쪽으로 힘을 가하면 왼쪽으로 스와이프해 상쇄할 수 있습니다.
  • 스와이프를 멈추면 힘이 0.75 감쇠율로 빠르게 0에 수렴합니다.
  • 최대 힘은 ±4이며, 물고기 힘(보통 1~10+ 범위)보다 상당히 작습니다.
3 유효 스탯 합산 공식
effectiveForceAbsorption = rod.forceAbsorption + bait.forceAbsorptionBonus + item.forceAbsorptionBonus + costume.forceAbsorptionBonus effectiveStaminaDrain = rod.staminaDrainMultiplier + bait.staminaDrainBonus + item.staminaDrainBonus + costume.staminaDrainBonus

두 수치 모두 낚싯대 + 미끼 + 아이템 + 코스튬의 합산으로 결정됩니다. 각 항목은 독립적으로 더해집니다.

4 낚싯대 스탯 데이터
# 이름 힘 흡수율 스태미나 소모 희귀 물고기 가격 (실버)
rod00대나무 낚싯대 0.00 0.56 0
rod01카본 낚싯대 0.06 0.64 2,000
rod02스피닝 낚싯대 0.12 0.68 10,000
rod03티타늄 낚싯대 0.24 0.80 10,000
rod04크리스탈 낚싯대 0.40 0.96 100,000
rod05네온 사이버펑크 0.47 1.01 250,000
rod06고대 마법 낚싯대 0.50 1.08 ×0.8800,000
rod07몬스터 뼈 낚싯대 0.54 1.15 ×1.61,500,000
rod08산호초 낚싯대 0.58 1.26 ×2.42,000,000
rod09황금 낚싯대 0.62 1.37 ×4.04,000,000
rod10은하성 낚싯대 ⭐ 0.67 1.44 ×8.07,000,000
5 미끼 & 코스튬 보너스
미끼 (Bait)
이름 힘흡수 스태미나 가격
떡밥+0.01+0.0010
작은 새우+0.01+0.0530
큰 새우+0.02+0.1070
고깃덩어리+0.04+0.15200
환상적인 미끼 ⭐+0.10+0.305,000

환상적인 미끼는 크리스탈급 이상 낚싯대에서만 사용 가능. 대나무 낚싯대는 떡밥만 사용 가능.

코스튬 (Costume)
코스튬 힘흡수 스태미나
school+0.02+0.20
military+0.03+0.15
priest+0.02+0.35
wizard+0.03+0.40
king ⭐+0.05+0.50

코스튬은 스태미나 소모 보너스 위주. king 코스튬이 가장 강력.

아이템 (Item)
이름 힘흡수 스태미나 시작 체력 가격
카운터펀치 🥊+0.07+0.201,000
어퍼컷 👊-20%3,000

아이템은 낚시 시작 전 장착. 낚싯대·미끼·코스튬에 추가로 합산됩니다.

💡
최강 조합 예시 (은하성 + 환상적인 미끼 + king 코스튬):
힘 흡수율: 0.67 + 0.10 + 0.05 = 0.82 (물고기 힘의 82%를 차단)
스태미나 소모: 1.44 + 0.30 + 0.50 = 2.24× (기본 대나무 0.56 대비 4배)
6 릴링 (REELING) 페이즈
progress = 30 progress -= 2 progress += 15
  • 아무것도 안 하면 30 → 0까지 1,500ms 소요 (자동 실패)
  • 버튼을 5번 누르면 30 + 75 = 105 → 즉시 성공 (초기 상태 기준)
  • 빠르게 연타할수록 유리합니다.
7 캐스팅 게이지 & 몬스터 판정
캐스팅 정확도 → 몬스터 임계값
등급 정확도 monsterThreshold 효과
PERFECTacc > 0.701.25±25%가 몬스터
EXCELLENTacc > 0.351.40±40%가 몬스터
GOODacc > 01.45±45%가 몬스터
MISS밴드 이탈1.50기본값
몬스터 판정 & 실제 무게
multiplier = random(0.5, 2.0) actualGrams = baseGrams × multiplier isMonster = multiplier >= monsterThreshold && baseGrams > 500

밴드 폭 0.22 / 밴드 중심: 랜덤(0.12 ~ 0.88). 게이지 인디케이터는 0 → 1 → 0 왕복 (900ms).

8 물고기 스폰 알고리즘
effectiveRate(fish) = fish.is_rare ? fish.spawn_rate × rod.specialFishRateMultiplier : fish.spawn_rate totalWeight = sum(effectiveRate(f) for all f) rand = random() × totalWeight for (each fish) { rand -= effectiveRate(fish) if (rand <= 0) → 이 물고기 선택 }

spawn_rate가 높을수록 자주 등장합니다. 희귀 물고기(is_rare)는 낚싯대의 specialFishRateMultiplier에 의해 가중치가 조정됩니다.

9 XP & 레벨 시스템
물고기 획득 XP 공식
cappedForce = min(fish.force, 1.0) divisor = isRare ? 1 : 10 baseXP = ceil( (weightGrams + fish.stamina) × cappedForce / divisor ) bonusXP = ceil(baseXP × zzi.xpBonusPct / 100) totalXP = baseXP + bonusXP
희귀(is_rare) 물고기는 divisor=1로 10배 XP를 획득합니다. force가 1.0 초과여도 1.0으로 cap됩니다.
레벨업 필요 XP 공식
xpNeeded(level) = ceil( 50 × level² × 1.03^level )
레벨 필요 XP
Lv.1 → 252
Lv.2 → 3212
Lv.3 → 4477
Lv.5 → 61,381
Lv.10 → 116,727
10 알고리즘 요약 & 핵심 포인트
  • 힘겨루기의 핵심: 텐션을 ±30 이내 안전지대에 유지해 스태미나를 20배 빠르게 소모시키는 것.
  • 낚싯대가 가장 큰 영향: 힘 흡수율이 0 → 0.67로 올라가면 물고기 힘의 67%를 차단. 체감 난이도가 크게 낮아짐.
  • 미끼 + 코스튬 보너스 합산: 특히 스태미나 소모율은 최대 +0.80 (환상적 미끼+king)로 힘겨루기 시간을 크게 단축.
  • 물고기 힘은 1,500ms마다 랜덤 전환: 방향이 갑자기 바뀌므로 스와이프 반응이 중요.
  • 릴링은 빠른 연타: 자동 감소(-2/100ms)가 있으므로 빠르게 탭해야 안전.
  • 캐스팅 정확도: PERFECT 시 monsterThreshold 1.25 → 무게의 25% 초과만 몬스터로 인정. 더 자주 몬스터 등장.
  • 희귀 물고기: XP 10배 + spawn_rate에 rod.specialFishRateMultiplier 곱함. 은하성 ×8배가 최고.

Generated from source · FishingGame.tsx · rods.ts · baits.ts · costumes.ts · levelUtils.ts · weightUtils.ts