Skip to content
isdnetworks
Go back

두 규칙이 서로 다른 말을 했다

cocos2d-1.0.1-x-0.11.0 으로 만드는 iOS·Android 클라이언트에서 아이템 능력치 계산을 맡았다. 반지는 공격력을 고정값으로 올리고 목걸이는 비율로 올린다.

Table of contents

Open Table of contents

두 규칙이 서로 다른 값을 냈다

둘을 같이 끼면 화면마다 숫자가 달랐다. InventoryScene 에서는 125 인데 BattleScene 에서는 124 로 나왔다.

// 인벤토리
atk = (base + ring.flat) * (1 + neck.rate);
// 전투
atk = base * (1 + neck.rate) + ring.flat;

같은 값을 InventorySceneBattleScene 두 곳에서 따로 계산하고 있었다. 순서가 달라 결과가 갈렸다.

원인이 갈린 조합

하나만 끼면 인벤토리와 전투 두 화면이 같았다. 반지만, 목걸이만 끼웠을 때는 차이가 없었다.

둘을 같이 끼운 경우에만 벌어졌다. 비율이 곱해지는 대상에 고정값이 들어가느냐 마느냐의 차이였다.

계산 순서를 따라가 봤다

두 곳의 C++ 코드를 나란히 놓고 값을 손으로 계산해 봤다. base 100 에 반지 20, 목걸이 5% 면 인벤토리는 126 이고 전투는 125 여야 한다.

그런데 화면은 125 와 124 였다. 둘 다 1 이 모자랐다.

짧은 코드로 찍어 보니 이유가 나왔다.

(100 + 20) * (1 + 0.05f) = 125.999992
(int)125.999992           = 125

0.05f 가 딱 떨어지지 않는다. (int) 는 반올림이 아니라 0 쪽으로 자른다. 그래서 126 이 125 가 됐다.

SVN 에 있는 기획서를 다시 읽어 보니 어느 쪽이 맞는지 적혀 있지 않았다. 고정값을 먼저 더한다는 말도, 나중에 더한다는 말도 없었다.

기획 쪽에 물어보니 고정값을 먼저 더하는 쪽이 의도였다. 적혀 있지 않아서 구현하는 사람마다 다르게 짠 것이다.

순서가 필요한 자리를 다 찾았다

같은 형태가 또 있는지 작업 사본에서 grep -rn "rate" 로 뒤졌다. 방어력과 이동속도에도 고정값과 비율이 함께 있었다.

C++ 쪽 방어력은 두 곳이 같은 순서였고 이동속도는 갈려 있었다. 세 군데 중 두 군데가 어긋나 있었던 셈이다.

계산을 StatCalc::attack() 하나로 모으고 두 CCScene 이 그것을 부르게 했다. 자르는 것도 (int) 대신 floorf(x + 0.5f) 로 바꿨다. 순서를 고칠 일이 생기면 한 곳만 고친다.

상한과 확인 자리

이동속도에는 상한이 있었는데 그 처리도 화면마다 달랐다. 한쪽은 곱하기 전에 자르고 한쪽은 자른 뒤에 곱했다.

상한도 같은 함수 안으로 넣었다. 자르는 시점을 마지막으로 통일했다.

Cocos2d-x 쪽 화면 코드에서는 그 함수만 부르고 계산은 하지 않게 했다.

값이 맞는지 확인하는 자리는 아직 없다. 지금은 화면을 열어 눈으로 보는 것 말고는 방법을 모르겠다.

정리


Share this post on:

Previous Post
밸런스 수치가 코드 곳곳에 박혀 있었다
Next Post
처음 켜자마자 전부 한꺼번에 일어났다