[25.06.10] :: 가디언 앤 시커 프로젝트 11

chooha·2025년 6월 11일

가디언앤시커

목록 보기
11/25

📝 개발일지 - 룬 시스템 배치 검증 로직 업데이트

👨‍💻 오늘의 개발 작업

오늘은 룬 시스템에서 복잡한 모양의 룬을 배치할 때 UX가 직관적이지 않은 문제를 해결했음
처음엔 단순히 마우스 좌표를 기준점으로 사용했는데, 사용자가 빈 공간 어디를 클릭하든 예상한 대로 배치되도록 로직을 수정했음


💡 오늘의 5분 기록

1. 문제 확인 - 직관적이지 않은 룬 배치 UX

예를 들어 룬이 [0,0], [0,1] 모양일 때 사용자 경험에 문제가 있었음

기존 방식의 문제점
[0,0], [0,1] 모양의 룬이라면 세로로 2칸이 비어있으면 그 공간의 어디를 클릭하던 배치가 되는게 맞는데 현재 로직으로는 윗칸에 마우스가 올라올 때만 배치가 가능

사용자 입장에서는 룬이 차지할 빈 공간 어디든 클릭하면 같은 결과를 기대하는데, 실제로는 클릭 위치에 따라 배치 결과가 달라져서 혼란스러운 UX를 만들고 있었음

2. 원인 파악 - 마우스 좌표 = 룬 기준점 방식의 한계

기존 배치 로직

// 클릭한 위치를 그대로 룬의 기준점으로 사용
FIntPoint CellPos = TargetCell->GetCellPos();
bool bPlaceSuccess = BoardManager->PlaceRune(SelectedRuneID, CellPos);

3. 해결 설계

핵심 아이디어
클릭한 셀을 포함할 수 있는 모든 가능한 배치 위치를 계산하고, 그 중 가장 직관적인 위치를 자동 선택

우선순위 규칙

  • 클릭한 셀이 룬의 좌상단에 오는 배치를 우선 선택
  • 사용자가 빈 공간을 클릭했을 때 그 지점이 룬의 시작점이 되도록

4. 로직 구현

배치가능 검증 로직

// 룬의 각 셀에 대해 클릭한 셀이 해당 위치에 올 수 있는지 확인
for (const FIntPoint& ShapeOffset : RuneShape)
{
    // 클릭한 셀이 ShapeOffset 위치에 올 때의 기준점 계산
    FIntPoint CandidatePosition = ClickedCell - ShapeOffset;
    
    // 배치 가능한지 확인
    if (PreviewRunePlacement(RuneID, CandidatePosition, AffectedCells))
    {
        ValidPositions.Add(CandidatePosition);
    }
}

우선순위 선택 로직

// 첫 번째 후보를 초기값으로 설정
OutBestPosition = ValidPositions[0];
FIntPoint BestShapeOffset = ClickedCell - ValidPositions[0];

for (int32 i = 1; i < ValidPositions.Num(); ++i) // 인덱스 1부터 시작
{
    FIntPoint Position = ValidPositions[i];
    // 이 배치에서 클릭한 셀이 룬의 어느 부분에 해당하는지 계산
    FIntPoint ShapeOffset = ClickedCell - Position;
    
    // 룬의 좌상단([0,0])에 가까운 순서로 우선순위 결정
    bool bIsBetter = false;
    
    if (ShapeOffset.Y < BestShapeOffset.Y)
    {
        bIsBetter = true; // 룬의 더 위쪽 행
    }
    else if (ShapeOffset.Y == BestShapeOffset.Y && ShapeOffset.X < BestShapeOffset.X)
    {
        bIsBetter = true; // 같은 행에서 더 왼쪽 열
    }
    
    if (bIsBetter)
    {
        OutBestPosition = Position;
        BestShapeOffset = ShapeOffset;
    }
}

5. 추가 개선 - 배치 실패 시 빨간색 프리뷰

구현 후 새로운 UX 이슈 발견

문제: 배치 불가능한 위치에서는 아무 프리뷰도 표시되지 않아 사용자가 혼란스러워함

해결: 실패 시에도 시각적 피드백 제공

if (BoardManager->FindOptimalPlacementPosition(RuneID, GridPos, OptimalPosition))
{
    // 배치 가능 → 초록색 프리뷰
}
else
{
    // 배치 불가능 → 클릭 위치 기준으로 빨간색 프리뷰
    BoardManager->PreviewRunePlacement(RuneID, GridPos, AffectedCells);
    // 항상 Invalid (빨간색)로 표시
}

6. 성과와 깨달은 점

Before & After

  • 기존: 룬의 어느 부분을 클릭하느냐에 따라 배치 결과가 달라짐
  • 개선: 룬이 차지할 영역 어디를 클릭하든 예측 가능한 위치에 배치

핵심 깨달음

  • 기존 코드를 최대한 재활용하면서도 UX를 크게 개선할 수 있었음
  • 음수 좌표가 포함된 룬 모양도 동일한 로직으로 처리 가능

0개의 댓글