본문 바로가기
-----ETC-----/C++ 게임 개발 시리즈

[C++ 게임 개발 시리즈] Day 6: 첫 번째 게임 프로젝트: 간단한 2D 게임 만들기 (3)

by cogito21_cpp 2024. 8. 1.
반응형

점수 시스템과 여러 적 추가

이번 단계에서는 점수 시스템을 추가하고, 여러 적이 등장하도록 구현하겠습니다. 이를 통해 게임이 좀 더 도전적이고 흥미로워질 것입니다.

점수 시스템 추가

  1. 점수 변수 정의:
    • main.cpp 파일에 점수 변수를 정의합니다.
int score = 0;
sf::Font font;
sf::Text scoreText;
  1. 폰트 로드 및 점수 텍스트 설정:
    • 폰트를 로드하고, 점수를 표시할 텍스트를 설정합니다.
// 메인 함수 내부에 추가 (창 생성 아래)
if (!font.loadFromFile("arial.ttf")) {
    std::cerr << "Error loading font" << std::endl;
    return -1;
}
scoreText.setFont(font);
scoreText.setCharacterSize(24);
scoreText.setFillColor(sf::Color::White);
scoreText.setPosition(10.0f, 10.0f);
  1. 점수 업데이트 및 표시:
    • 게임 루프 내에서 점수를 업데이트하고, 화면에 표시합니다.
// 메인 함수의 게임 루프 내에 추가 (충돌 처리 아래)
score++;
scoreText.setString("Score: " + std::to_string(score));
window.draw(scoreText);

여러 적 추가

  1. 적 리스트 정의:
    • 여러 적을 관리하기 위해 std::vector를 사용합니다.
std::vector<sf::RectangleShape> enemies;
const int numberOfEnemies = 5;
  1. 여러 적 생성:
    • 적 리스트에 여러 적을 추가합니다.
// 메인 함수 내부에 추가 (플레이어 캐릭터 정의 아래)
for (int i = 0; i < numberOfEnemies; i++) {
    sf::RectangleShape enemy(sf::Vector2f(50.0f, 50.0f));
    enemy.setFillColor(sf::Color::Red);
    enemy.setPosition(rand() % 750, rand() % 550); // 임의의 위치에 배치
    enemies.push_back(enemy);
}
  1. 적 이동 및 충돌 처리:
    • 각 적이 플레이어를 향해 이동하고, 충돌 여부를 확인합니다.
// 메인 함수의 게임 루프 내에 추가 (플레이어 이동 처리 아래)
for (auto& enemy : enemies) {
    sf::Vector2f enemyDirection = player.getPosition() - enemy.getPosition();
    float enemyDistance = std::sqrt(enemyDirection.x * enemyDirection.x + enemyDirection.y * enemyDirection.y);
    enemyDirection /= enemyDistance; // 방향 벡터 정규화
    enemy.move(enemyDirection * enemySpeed * deltaTime);

    if (isColliding(player, enemy)) {
        // 충돌 시 게임 종료
        window.close();
        std::cout << "Game Over!" << std::endl;
    }
}
  1. 적 그래픽 렌더링:
    • 각 적을 화면에 렌더링합니다.
// 메인 함수의 게임 루프 내에 추가 (플레이어 렌더링 아래)
for (const auto& enemy : enemies) {
    window.draw(enemy);
}

 

 

완성된 main.cpp 파일

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <ctime>

bool isColliding(const sf::RectangleShape& rect1, const sf::RectangleShape& rect2) {
    return rect1.getGlobalBounds().intersects(rect2.getGlobalBounds());
}

int main() {
    // 랜덤 시드 설정
    std::srand(static_cast<unsigned>(std::time(nullptr)));

    // 창 생성
    sf::RenderWindow window(sf::VideoMode(800, 600), "Simple 2D Game");

    // 플레이어 캐릭터 생성
    sf::RectangleShape player(sf::Vector2f(50.0f, 50.0f));
    player.setFillColor(sf::Color::Green);
    player.setPosition(375.0f, 275.0f); // 창 중앙에 위치

    // 적 캐릭터 생성
    std::vector<sf::RectangleShape> enemies;
    const int numberOfEnemies = 5;
    for (int i = 0; i < numberOfEnemies; i++) {
        sf::RectangleShape enemy(sf::Vector2f(50.0f, 50.0f));
        enemy.setFillColor(sf::Color::Red);
        enemy.setPosition(rand() % 750, rand() % 550); // 임의의 위치에 배치
        enemies.push_back(enemy);
    }

    // 점수 시스템
    int score = 0;
    sf::Font font;
    if (!font.loadFromFile("arial.ttf")) {
        std::cerr << "Error loading font" << std::endl;
        return -1;
    }
    sf::Text scoreText;
    scoreText.setFont(font);
    scoreText.setCharacterSize(24);
    scoreText.setFillColor(sf::Color::White);
    scoreText.setPosition(10.0f, 10.0f);

    // 게임 루프
    sf::Clock clock;
    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        // deltaTime 계산
        float deltaTime = clock.restart().asSeconds();

        // 플레이어 이동
        const float playerSpeed = 200.0f;
        sf::Vector2f movement(0.0f, 0.0f);

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
            movement.y -= playerSpeed * deltaTime;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
            movement.y += playerSpeed * deltaTime;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
            movement.x -= playerSpeed * deltaTime;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
            movement.x += playerSpeed * deltaTime;
        }

        player.move(movement);

        // 적 이동 및 충돌 처리
        const float enemySpeed = 100.0f;
        for (auto& enemy : enemies) {
            sf::Vector2f enemyDirection = player.getPosition() - enemy.getPosition();
            float enemyDistance = std::sqrt(enemyDirection.x * enemyDirection.x + enemyDirection.y * enemyDirection.y);
            enemyDirection /= enemyDistance; // 방향 벡터 정규화
            enemy.move(enemyDirection * enemySpeed * deltaTime);

            if (isColliding(player, enemy)) {
                // 충돌 시 게임 종료
                window.close();
                std::cout << "Game Over!" << std::endl;
            }
        }

        // 점수 업데이트
        score++;
        scoreText.setString("Score: " + std::to_string(score));

        // 화면 지우기
        window.clear();

        // 그래픽 렌더링
        window.draw(player);
        for (const auto& enemy : enemies) {
            window.draw(enemy);
        }
        window.draw(scoreText);

        // 화면에 그리기
        window.display();
    }

    return 0;
}

결론

세 번째 단계에서는 점수 시스템을 추가하고, 여러 적이 등장하도록 구현했습니다. 이제 게임이 더 흥미롭고 도전적인 형태가 되었습니다. 질문이나 추가적인 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "Day 7: 게임 루프와 기본 게임 구조"에 대해 학습하겠습니다.

반응형