장비를 바꾸면 공격력이 안 맞을 때가 있었다.
Table of contents
Open Table of contents
두 값을 따로 고치고 있었다
장비를 끼는 함수는 장비와 공격력을 같이 고쳤다.
void Player::equip(const Item& item) {
m_equipped = item;
m_attack = m_baseAttack + item.attack;
}
한 함수 안에 있으니 괜찮아 보였는데 벗는 쪽은 달랐다. 장비만 비우고 공격력을 안 고쳤다. 두 값이 함께 움직여야 하는데 함께 바꾸는 자리가 한 곳뿐이었다.
계산해서 쓰게 바꿨다
값을 둘 두는 대신 필요할 때 계산하게 했다.
int Player::getAttack() const {
return m_baseAttack + m_equipped.attack;
}
m_attack 이라는 저장 값을 아예 없애니 고칠 자리가 하나로 줄었다. 계산이 무거우면 이렇게 못 하지만 더하기 하나라 상관없었다.
바꾸는 자리를 하나로 모았다
계산이 무거운 것도 있었다. 그건 표시만 켜 두고 나중에 계산하게 했다. 문제는 표시를 켜는 것을 빠뜨리면 옛 값이 나온다는 점이다.
void Player::setEquipped(const Item& item) {
m_equipped = item;
m_statDirty = true;
}
값을 바꾸는 자리를 이 함수 하나로 모았다. 밖에서 못 건드리게 CC_PROPERTY_READONLY 로 바꿔 setter 를 없애고, 안에서 직접 대입하던 자리는 grep 으로 찾아 전부 고쳤다. 대입이 이 함수 안에만 남은 것을 확인하고 끝냈다.
같이 움직이는 것을 전부 찾아보니 더 있었다. 레벨과 최대 체력, 버프와 속도가 같은 모양이었다. 대부분 계산해서 쓰는 쪽으로 바꿨는데 체력만 따로 다뤘다. 최대치가 줄면 현재 값도 줄여야 하기 때문이다.
반대 방향의 확인
이 버그는 벗을 때만 났다. 끼는 것만 확인하고 넘어갔기 때문이다.
끼기와 벗기와 바꿔 끼기 셋 중 확인한 것이 하나였다. 바꿔 끼기는 벗기와 끼기가 연달아 일어난다. 그 순서에서 또 다른 것이 날 수 있었다. 한쪽 방향만 확인하면 반대 방향에서 난다.
화면이 옛 값을 그리는 것도 같이 봤다. 값이 맞아도 화면이 안 바뀌면 사용자에게는 같다. scheduleUpdate() 를 걸어 update() 에서 매 프레임 읽어 갔다. 달라졌을 때만 CCLabelTTF 의 setString() 을 부르게 뒀다. 알려 주는 방식으로 하면 알려 주는 자리를 또 빠뜨린다.
정리
- 함께 움직여야 하는 값을 따로 고치면 한쪽만 고치는 자리가 생긴다
- 계산이 가벼우면 값을 두지 말고 계산해서 쓴다
- 무거우면 표시만 켜 두되 값을 바꾸는 자리를 하나로 모은다
CC_PROPERTY_READONLY로 밖에서 못 고치게 하고 안쪽은grep으로 찾는다- 같이 움직이는 것을 전부 찾는다
- 최대치가 줄면 현재 값도 줄여야 하는 것이 있다
update()에서 읽어 간다. 알려 주는 방식은 자리를 빠뜨린다- 한쪽 방향만 확인하면 반대 방향에서 난다