[SpriteKit] 고양이 퍼즐 게임 만들기 day.04

Emily·2025년 6월 8일
0

GridPopGame

목록 보기
4/8
post-thumbnail

누른 고양이가 주변의 같은 색깔 고양이들과 함께 사라지면, 그 자리를 위에 있는 고양이들을 내려 채우고 사라진 고양이 수만큼 새로 노드들을 생성하여 그리드를 꽉 채울 것이다.

01) 고양이들 내리기

우선, 고양이가 사라진 자리에 위에 있던 고양이들을 내리면서 빈자리를 채우도록 구현한다. 고양이 위치를 조절하기 위해서는 2차원배열인 columns의 index 값을 활용해야 하기 때문에, day.03에서 만들었던 removeMatches() 메소드에 columns에서도 item을 삭제하는 작업을 추가한다.

class GameScene: SKScene {

	private var columns: [[Item]] = []

    func removeMatches() {
        guard matchedItems.count > 1 else { return }

		// columns에서 item을 삭제하기 위해 row index가 큰 순으로 정렬한다. (앞에서부터 삭제하게 되면 index가 꼬이기 때문)
        let sortedMatches = matchedItems.sorted { $0.row > $1.row }

        for item in sortedMatches {
            columns[item.column].remove(at: item.row)
            item.removeFromParent()
        }
    }
}

columns[n]의 indexitem.row에 할당한 뒤 positionItem 메소드를 호출하여 노드의 위치를 변경한다. 이 때, SKAction을 사용하여 애니메이션을 적용한다.

func moveDown() {
	for (columnIndex, column) in columns.enumerated() {
    	for (rowIndex, item) in column.enumerated() {
        	// item에 바뀐 row index 적용
        	item.row = rowIndex
            
            // 바뀐 row로 이동하는 애니메이션 적용
            let downAction = SKAction.move(to: positionItem(for: item), duration: 0.3)
            item.run(downAction)
        }
    }
}

move down action이 적용된 모습

02) 새로운 고양이들 생성해서 자리 채우기

  1. 사라진 고양이만큼 새로운 노드를 생성
func moveDown() {
	for (columnIndex, column) in columns.enumerated() {
    	for (rowIndex, item) in column.enumerated() {
        	// ... //
        }
        
        // while 반복문을 통해 column의 count가 채워질 때까지 createItem
		while columns[columnIndex].count < itemsPerRow {
             let item = createItem(column: columnIndex, row: columns[columnIndex].count)
                
            columns[columnIndex].append(item)
        }
    }
}
  1. 화면 맨 위에서 내려오도록 애니메이션 적용 : createItemBool 타입의 매개변수를 추가하여 애니메이션이 필요한 경우와 아닌 경우를 분기한다.
  • before
func createItem(column: Int, row: Int) -> Item {
    let itemImages = Items.allCases.map { $0.imageName }
        
    let itemImage = itemImages[GKRandomSource.sharedRandom().nextInt(upperBound: itemImages.count)]
        
    let item = Item(imageNamed: itemImage, column: column, row: row)
        
    item.name = itemImage
    item.position = positionItem(for: item) // <<< 분기될 부분
    item.size = CGSize(width: itemSize, height: itemSize)
    addChild(item)
        
    return item
}
  • after
func createItem(column: Int, row: Int, startOffScreen: Bool = false) -> Item {
	let itemImages = Items.allCases.map { $0.imageName }
        
    let itemImage = itemImages[GKRandomSource.sharedRandom().nextInt(upperBound: itemImages.count)]
        
    let item = Item(imageNamed: itemImage, column: column, row: row)
        
    item.name = itemImage
    
    if startOffScreen {
    	// 고양이 보충 시
        let finalPosition = positionItem(for: item)
        item.position = finalPosition
        // 출발은 화면 맨 위에서 해야하기 때문에 y값 추가
        item.position.y += (itemSize * CGFloat(itemsPerColumn))
        // 애니메이션 적용
        let downAction = SKAction.move(to: finalPosition, duration: 0.4)
        item.run(downAction)    
    } else {
    	// grid 최초 생성 시 - no animation
        item.position = positionItem(for: item)
    }
    
    item.size = CGSize(width: itemSize, height: itemSize)
    addChild(item)
        
    return item
}

이 챕터를 통해 SpriteKit에서의 애니메이션인 SKAction을 경험할 수 있었다. 다음에는 SKLabelNode를 사용하여 점수와 이동 수 레이블을 추가할 것이다.

profile
iOS Junior Developer

0개의 댓글