Bu bölümde, proje için yeni bir GameMode sınıfı tanımlayacağız.
Projede oluşturacağımız tüm değerleri kaydetmek için,
1. "Content" dizini altında "_Game" adlı bir dizin oluşturalım.
2. "_Game" dizini altında "Blueprints" adlı bir dizin ve bu dizin altında aşağıdaki dizinleri oluşturalım.
1. Unreal Engine Editor'da, ana menüden "Tools - New C++ Class" seçeneği ile açılan "Add C++ Class" penceresinde "Game Mode Base" seçeneği seçili iken, "Next" butonuna tıklayalım.
2. Açılan pencerede "Name" satırına "MyGameGameMode" değerini girdikten sonra "Create Class" butonuna tıklayarak GameMode sınıfını oluşturalım.
3. Dosyaların içerikleri aşağıdaki şekilde olacaktır:
// MyGameGameMode.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "MyGameGameMode.generated.h"
/**
*
*/
UCLASS()
class MYGAME_API AMyGameGameMode : public AGameModeBase
{
GENERATED_BODY()
};
// MyGameGameMode.cpp
#include "MyGameGameMode.h"
4. Kodlar derlendikten sonra "C++ Classes" adlı bir dizin ve bu dizin altında "MyGame" adlı bir dizin ile bu dizin altında "MyGameGameMode" adlı bir dosya otomatik olarak oluşturulacaktır.
GameMode sınıfı kod dosyalarının içeriğini aşağıdaki şekilde düzenleyelim:
// MyGameGameMode.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "MyGameGameMode.generated.h"
/* MyGame projesi için özel GameMode sınıfı. Oyun kurallarını ve mantığını yönetir. */
UCLASS()
class MYGAME_API AMyGameGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
// Constructor
AMyGameGameMode();
protected:
//////////////////////////////////////////////////////////////////////////
// Oyuncu Bağlantısı ve Başlangıç Fonksiyonları
/**
* Oyuncu bağlandığında çağrılır
* @param NewPlayer - Yeni bağlanan oyuncunun PlayerController'ı
*/
virtual void PostLogin(APlayerController* NewPlayer) override;
/**
* Oyuncu ayrıldığında çağrılır
* @param ExitingPlayer - Oyundan ayrılan oyuncunun PlayerController'ı
*/
virtual void Logout(AController* ExitingPlayer) override;
/**
* Oyun başladığında çağrılır
*/
virtual void BeginPlay() override;
/**
* Oyuncu spawn edildiğinde çağrılır (varsayılan spawn işleminden sonra)
* @param NewPlayer - Oyuncunun PlayerController'ı
*/
virtual void HandleStartingNewPlayer_Implementation(APlayerController* NewPlayer) override;
//////////////////////////////////////////////////////////////////////////
// Spawn Ayarları
/**
* Yeni bir pawn spawn etmek için çağrılır
* @param NewPlayer - Spawn edilecek pawn'ın PlayerController'ı
* @return Spawn edilen pawn
*/
virtual APawn* SpawnDefaultPawnFor_Implementation(AController* NewPlayer, AActor* StartSpot) override;
public:
//////////////////////////////////////////////////////////////////////////
// Oyun Mantığı Fonksiyonları
/**
* Oyunu başlat
* Blueprint'lerden çağrılabilir
*/
UFUNCTION(BlueprintCallable, Category = "MyGame|Game Flow")
void StartGame();
/**
* Oyunu bitir
* @param bPlayerWon - Oyuncu kazandı mı?
*/
UFUNCTION(BlueprintCallable, Category = "MyGame|Game Flow")
void EndGame(bool bPlayerWon);
/**
* Oyun durumunu değiştir
* @param NewState - Yeni oyun durumu
*/
UFUNCTION(BlueprintCallable, Category = "MyGame|Game State")
void ChangeGameState(FName NewState);
/**
* Oyuncu skorunu güncelle
* @param PlayerController - Skoru güncellenecek oyuncu
* @param ScoreToAdd - Eklenecek skor miktarı
*/
UFUNCTION(BlueprintCallable, Category = "MyGame|Score")
void AddPlayerScore(APlayerController* PlayerController, int32 ScoreToAdd);
//////////////////////////////////////////////////////////////////////////
// Blueprint Implementable Events - Blueprint'te override edilebilir
/**
* Oyun durumu değiştiğinde çağrılır (Blueprint'te implemente edilecek)
* @param OldState - Eski durum
* @param NewState - Yeni durum
*/
UFUNCTION(BlueprintImplementableEvent, Category = "MyGame|Events")
void OnGameStateChanged(FName OldState, FName NewState);
/**
* Oyuncu skoru değiştiğinde çağrılır (Blueprint'te implemente edilecek)
* @param PlayerController - Skoru değişen oyuncu
* @param OldScore - Eski skor
* @param NewScore - Yeni skor
*/
UFUNCTION(BlueprintImplementableEvent, Category = "MyGame|Events")
void OnPlayerScoreChanged(APlayerController* PlayerController, float OldScore, float NewScore);
/**
* Timer güncellendiğinde çağrılır (Blueprint'te implemente edilecek)
* @param RemainingTimeSeconds - Kalan süre (saniye)
*/
UFUNCTION(BlueprintImplementableEvent, Category = "MyGame|Events")
void OnTimerUpdated(float RemainingTimeSeconds);
//////////////////////////////////////////////////////////////////////////
// Blueprint Ayarlanabilir Özellikler
/**
* Oyun başlangıç durumu
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "MyGame|Configuration")
FName InitialGameState;
/**
* Oyun süresi (saniye)
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "MyGame|Configuration", meta = (ClampMin = "0"))
float GameDuration;
/**
* Maksimum oyuncu sayısı
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "MyGame|Configuration", meta = (ClampMin = "1", ClampMax = "16"))
int32 MaxPlayers;
/**
* Oyun bitti mi?
*/
UPROPERTY(BlueprintReadOnly, Category = "MyGame|Game State")
bool bIsGameOver;
/**
* Oyun başladı mı?
*/
UPROPERTY(BlueprintReadOnly, Category = "MyGame|Game State")
bool bHasGameStarted;
/**
* Kalan süre
*/
UPROPERTY(BlueprintReadOnly, Category = "MyGame|Game State")
float RemainingTime;
protected:
//////////////////////////////////////////////////////////////////////////
// İç Değişkenler ve Yardımcı Fonksiyonlar
/**
* Süre sayacını güncelle
*/
void UpdateTimer();
/**
* Timer handle for game updates
*/
FTimerHandle GameTimerHandle;
/**
* Mevcut oyun durumu
*/
FName CurrentGameState;
/**
* Oyun durumlarının listesi
*/
TArray<FName> GameStates;
/**
* Aktif oyuncu sayısı
*/
int32 ActivePlayerCount;
};
// MyGameGameMode.cpp
#include "MyGameGameMode.h"
#include "Engine/World.h"
#include "TimerManager.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/PlayerState.h"
#include "Kismet/GameplayStatics.h"
// Log kategorisi tanımlama
DEFINE_LOG_CATEGORY_STATIC(LogMyGame, Log, All);
AMyGameGameMode::AMyGameGameMode()
{
// Varsayılan değerleri ayarla
InitialGameState = FName("Waiting");
GameDuration = 300.0f; // 5 dakika
MaxPlayers = 4;
// Başlangıç durumları
bIsGameOver = false;
bHasGameStarted = false;
RemainingTime = GameDuration;
ActivePlayerCount = 0;
// Oyun durumlarını başlat
GameStates.Add(FName("Waiting"));
GameStates.Add(FName("Playing"));
GameStates.Add(FName("Paused"));
GameStates.Add(FName("Finished"));
CurrentGameState = InitialGameState;
// Default sınıfları ayarla (Blueprint'ten override edilebilir)
// NOT: Bu yolları kendi projenize göre değiştirin veya tamamen kaldırın
// Eğer bu asset'ler yoksa, constructor'ı basitleştirebilirsiniz
// Eğer BP_MyGameCharacter blueprint'iniz varsa bu kodu kullanın
static ConstructorHelpers::FClassFinder<APawn> PlayerPawnClassFinder(TEXT("/Game/_Game/Blueprints/Pawns/BP_MyGameCharacter"));
if (PlayerPawnClassFinder.Class != nullptr)
{
DefaultPawnClass = PlayerPawnClassFinder.Class;
}
// Eğer BP_MyGamePlayerController blueprint'iniz varsa bu kodu kullanın
static ConstructorHelpers::FClassFinder<APlayerController> PlayerControllerClassFinder(TEXT("/Game/Blueprints/PlayerControllers/BP_MyGamePlayerController"));
if (PlayerControllerClassFinder.Class != nullptr)
{
PlayerControllerClass = PlayerControllerClassFinder.Class;
}
// Alternatif: Varsayılan Unreal sınıflarını kullan
// DefaultPawnClass = ADefaultPawn::StaticClass();
// PlayerControllerClass = APlayerController::StaticClass();
UE_LOG(LogMyGame, Log, TEXT("MyGameGameMode initialized"));
}
void AMyGameGameMode::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogMyGame, Log, TEXT("GameMode BeginPlay - Current State: %s"), *CurrentGameState.ToString());
// Başlangıçta timer'ı başlat
GetWorld()->GetTimerManager().SetTimer(
GameTimerHandle,
this,
&AMyGameGameMode::UpdateTimer,
1.0f, // Her saniye
true // Tekrarlı
);
}
void AMyGameGameMode::PostLogin(APlayerController* NewPlayer)
{
Super::PostLogin(NewPlayer);
ActivePlayerCount++;
if (NewPlayer && NewPlayer->PlayerState)
{
UE_LOG(LogMyGame, Log, TEXT("Player %s joined the game. Total players: %d"),
*NewPlayer->PlayerState->GetPlayerName(),
ActivePlayerCount);
// Yeni oyuncuya hoşgeldin mesajı gönder
if (GEngine)
{
FString WelcomeMessage = FString::Printf(TEXT("Welcome %s to MyGame!"),
*NewPlayer->PlayerState->GetPlayerName());
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, WelcomeMessage);
}
// Eğer yeterli oyuncu varsa ve oyun başlamadıysa, oyunu başlat
if (!bHasGameStarted && ActivePlayerCount >= 1) // Örnek: 1 oyuncuyla başlat
{
// 3 saniye bekle sonra başlat (oyuncunun hazırlanması için)
FTimerHandle StartTimerHandle;
GetWorld()->GetTimerManager().SetTimer(
StartTimerHandle,
[this]()
{
StartGame();
},
3.0f,
false
);
}
}
}
void AMyGameGameMode::Logout(AController* ExitingPlayer)
{
if (ExitingPlayer && ExitingPlayer->PlayerState)
{
UE_LOG(LogMyGame, Log, TEXT("Player %s left the game"),
*ExitingPlayer->PlayerState->GetPlayerName());
}
ActivePlayerCount = FMath::Max(0, ActivePlayerCount - 1);
Super::Logout(ExitingPlayer);
// Eğer hiç oyuncu kalmadıysa veya oyun bittiyse
if (ActivePlayerCount == 0 && bHasGameStarted)
{
EndGame(false); // Hiç kimse kazanmadı
}
}
void AMyGameGameMode::HandleStartingNewPlayer_Implementation(APlayerController* NewPlayer)
{
Super::HandleStartingNewPlayer_Implementation(NewPlayer);
UE_LOG(LogMyGame, Log, TEXT("Handling new player: %s"),
NewPlayer ? *NewPlayer->GetName() : TEXT("NULL"));
// Oyuncu başlangıç özelliklerini ayarla
if (NewPlayer && NewPlayer->PlayerState)
{
// Başlangıç skoru
NewPlayer->PlayerState->SetScore(0);
// Varsayılan isim ayarla
if (NewPlayer->PlayerState->GetPlayerName().IsEmpty())
{
NewPlayer->PlayerState->SetPlayerName(FString::Printf(TEXT("Player_%d"), ActivePlayerCount));
}
}
}
APawn* AMyGameGameMode::SpawnDefaultPawnFor_Implementation(AController* NewPlayer, AActor* StartSpot)
{
APawn* SpawnedPawn = Super::SpawnDefaultPawnFor_Implementation(NewPlayer, StartSpot);
if (SpawnedPawn)
{
UE_LOG(LogMyGame, Log, TEXT("Pawn spawned for player: %s"),
*SpawnedPawn->GetName());
// Pawn spawn edildiğinde yapılacak ek işlemler
// Örneğin: başlangıç ekipmanı verme, spawn efektleri, vb.
}
return SpawnedPawn;
}
void AMyGameGameMode::StartGame()
{
if (bHasGameStarted)
{
UE_LOG(LogMyGame, Warning, TEXT("Game already started!"));
return;
}
bHasGameStarted = true;
bIsGameOver = false;
RemainingTime = GameDuration;
ChangeGameState(FName("Playing"));
UE_LOG(LogMyGame, Log, TEXT("Game Started! Duration: %.0f seconds"), GameDuration);
// Tüm oyunculara mesaj gönder
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("GAME STARTED!"));
}
// Tüm player controller'lara oyunun başladığını bildir
for (FConstPlayerControllerIterator It = GetWorld()->GetPlayerControllerIterator(); It; ++It)
{
APlayerController* PC = It->Get();
if (PC)
{
// Burada oyuncuya özel başlangıç işlemleri yapılabilir
// Örneğin: UI güncellemesi, ses çalma vb.
}
}
}
void AMyGameGameMode::EndGame(bool bPlayerWon)
{
if (bIsGameOver)
return;
bIsGameOver = true;
bHasGameStarted = false;
ChangeGameState(FName("Finished"));
FString EndMessage;
if (bPlayerWon)
{
EndMessage = TEXT("VICTORY! You won the game!");
UE_LOG(LogMyGame, Log, TEXT("Game Ended: Player Won"));
}
else
{
EndMessage = TEXT("GAME OVER");
UE_LOG(LogMyGame, Log, TEXT("Game Ended: Player Lost"));
}
// Ekran mesajı göster
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 10.0f, bPlayerWon ? FColor::Green : FColor::Red, EndMessage);
}
// Timer'ı durdur
GetWorld()->GetTimerManager().ClearTimer(GameTimerHandle);
// 5 saniye sonra oyunu yeniden başlat
FTimerHandle RestartTimer;
GetWorld()->GetTimerManager().SetTimer(
RestartTimer,
[this]()
{
// Restart the level
UGameplayStatics::OpenLevel(this, FName(*GetWorld()->GetName()), false);
},
5.0f,
false
);
}
void AMyGameGameMode::ChangeGameState(FName NewState)
{
if (CurrentGameState == NewState)
return;
FName PreviousState = CurrentGameState;
CurrentGameState = NewState;
UE_LOG(LogMyGame, Log, TEXT("Game State Changed: %s -> %s"),
*PreviousState.ToString(),
*CurrentGameState.ToString());
// Blueprint implementable event'i çağır
// Bu fonksiyon sadece Blueprint'te override edilirse çalışır
// C++ tarafında otomatik olarak oluşturulur
OnGameStateChanged(PreviousState, CurrentGameState);
}
void AMyGameGameMode::AddPlayerScore(APlayerController* PlayerController, int32 ScoreToAdd)
{
if (!PlayerController || !PlayerController->PlayerState || ScoreToAdd <= 0)
return;
float OldScore = PlayerController->PlayerState->GetScore();
float NewScore = OldScore + ScoreToAdd;
PlayerController->PlayerState->SetScore(NewScore);
UE_LOG(LogMyGame, Log, TEXT("Player %s score: %.0f -> %.0f (+%d)"),
*PlayerController->PlayerState->GetPlayerName(),
OldScore,
NewScore,
ScoreToAdd);
// Blueprint implementable event'i çağır
OnPlayerScoreChanged(PlayerController, OldScore, NewScore);
}
void AMyGameGameMode::UpdateTimer()
{
if (!bHasGameStarted || bIsGameOver)
return;
RemainingTime -= 1.0f;
// Her 10 saniyede bir log
if (FMath::Fmod(RemainingTime, 10.0f) < 1.0f)
{
UE_LOG(LogMyGame, Log, TEXT("Remaining Time: %.0f seconds"), RemainingTime);
}
// Blueprint event'ini çağır
OnTimerUpdated(RemainingTime);
// Süre bitti
if (RemainingTime <= 0.0f)
{
RemainingTime = 0.0f;
EndGame(false); // Süre bitti, oyuncu kaybetti
}
}
1. "MyGameGameMode" sınıfına sağ tıkladığımızda açılan menüden, "Create Blueprint class based on MyGameGameMode" seçeneğine tıklayarak "Add Blueprint Class" penceresini açalım.
2. "Name" satırına "BP_MyGameGameMode" değerini girdikten ve "Path" bölümünde "Content\_Game\Blueprints\GameModes" dizinini seçtikten sonra "Create My Game Game Mode Class" butonuna tıklayarak Blueprint sınıfını oluşturalım.
3. İşlem tamamlandığında, "Content\_Game\Blueprints\GameModes" dizininde "BP_MyGameGameMode" sınıfı oluşturulur.
Unreal Engine Editor'ün "Edit - Project Settings" menü seçeneği ile erişilen "Project Settings" penceresinin "Maps & Modes" sekmesinde, "Default GameMode" değerini "BP_MyGameGameMode" olarak değiştirelim. "Default Pawn Class" ve "Player Controller Class" değerleri şimdilik aynı kalacaktır.
Projeyi çalıştırdığımızda,
1. "BP_MyGameGameMode" sınıfı aktif GameMode olarak devreye girer ve Outliner'a görünür.
⚠️ AMyGameGameMode::AMyGameGameMode() Constructor fonksiyonu içinde tanımlanan BP_MyGamePlayerController ve BP_MyGameCharacter değerleri henüz oluşturulmadığından, "Project Settings" içindeki "Default Pawn Class" ve "Player Controller Class" değerleri şimdilik aynı kalacaktır.
2. Aşağıdaki ifadeler sahne ekranında görünür ve bir süre sonra kaybolur.
Welcome .... to My Game! GAME STARTED
3. Aşağıdaki ifadeler Output Log ekranına yazılır:
LogLoad: Game class is 'BP_MyGameGameMode_C' LogMyGame: MyGameGameMode initialized LogMyGame: Pawn spawned for player: DefaultPawn_0 LogMyGame: Handling new player: PlayerController_0 LogMyGame: Player ... joined the game. Total players: 1 LogMyGame: GameMode BeginPlay - Current State: Waiting LogMyGame: Game State Changed: Waiting -> Playing LogMyGame: Game Started! Duration: 300 seconds LogMyGame: Player ... left the game LogMyGame: Game State Changed: Playing -> Finished LogMyGame: Game Ended: Player Lost