Modify the behavior of the template to implement a 2 player tic-tac-toe game. When player1 clicks a
Question:
TicTacToe2PlayerPlayerController.cpp
#include \"TicTacToe2PlayerPlayerController.h\"
ATicTacToe2PlayerPlayerController::ATicTacToe2PlayerPlayerController() { bShowMouseCursor = true; bEnableClickEvents = true; bEnableTouchEvents = true; DefaultMouseCursor = EMouseCursor::Crosshairs; }
TicTacToe2PlayerGameMode.cpp
#include \"TicTacToe2PlayerGameMode.h\" #include \"TicTacToe2PlayerPlayerController.h\" #include \"TicTacToe2PlayerPawn.h\"
ATicTacToe2PlayerGameMode::ATicTacToe2PlayerGameMode() { // no pawn by default DefaultPawnClass = ATicTacToe2PlayerPawn::StaticClass(); // use our own player controller class PlayerControllerClass = ATicTacToe2PlayerPlayerController::StaticClass(); }
TicTacToe2PlayerBlock.cpp
#include \"TicTacToe2PlayerBlock.h\" #include \"TicTacToe2PlayerBlockGrid.h\" #include \"UObject/ConstructorHelpers.h\" #include \"Components/StaticMeshComponent.h\" #include \"Engine/StaticMesh.h\" #include \"Materials/MaterialInstance.h\"
ATicTacToe2PlayerBlock::ATicTacToe2PlayerBlock() { // Structure to hold one-time initialization struct FConstructorStatics { ConstructorHelpers::FObjectFinderOptional PlaneMesh; ConstructorHelpers::FObjectFinderOptional BaseMaterial; ConstructorHelpers::FObjectFinderOptional BlueMaterial; ConstructorHelpers::FObjectFinderOptional OrangeMaterial; FConstructorStatics() : PlaneMesh(TEXT(\"/Game/Puzzle/Meshes/PuzzleCube.PuzzleCube\")) , BaseMaterial(TEXT(\"/Game/Puzzle/Meshes/BaseMaterial.BaseMaterial\")) , BlueMaterial(TEXT(\"/Game/Puzzle/Meshes/BlueMaterial.BlueMaterial\")) , OrangeMaterial(TEXT(\"/Game/Puzzle/Meshes/OrangeMaterial.OrangeMaterial\")) { } }; static FConstructorStatics ConstructorStatics;
// Create dummy root scene component DummyRoot = CreateDefaultSubobject(TEXT(\"Dummy0\")); RootComponent = DummyRoot;
// Create static mesh component BlockMesh = CreateDefaultSubobject(TEXT(\"BlockMesh0\")); BlockMesh->SetStaticMesh(ConstructorStatics.PlaneMesh.Get()); BlockMesh->SetRelativeScale3D(FVector(1.f,1.f,0.25f)); BlockMesh->SetRelativeLocation(FVector(0.f,0.f,25.f)); BlockMesh->SetMaterial(0, ConstructorStatics.BlueMaterial.Get()); BlockMesh->SetupAttachment(DummyRoot); BlockMesh->OnClicked.AddDynamic(this, &ATicTacToe2PlayerBlock::BlockClicked); BlockMesh->OnInputTouchBegin.AddDynamic(this, &ATicTacToe2PlayerBlock::OnFingerPressedBlock);
// Save a pointer to the orange material BaseMaterial = ConstructorStatics.BaseMaterial.Get(); BlueMaterial = ConstructorStatics.BlueMaterial.Get(); OrangeMaterial = ConstructorStatics.OrangeMaterial.Get(); }
void ATicTacToe2PlayerBlock::BlockClicked(UPrimitiveComponent* ClickedComp, FKey ButtonClicked) { HandleClicked(); }
void ATicTacToe2PlayerBlock::OnFingerPressedBlock(ETouchIndex::Type FingerIndex, UPrimitiveComponent* TouchedComponent) { HandleClicked(); }
void ATicTacToe2PlayerBlock::HandleClicked() { // Check we are not already active if (!bIsActive) { bIsActive = true;
// Change material BlockMesh->SetMaterial(0, OrangeMaterial);
// Tell the Grid if (OwningGrid != nullptr) { OwningGrid->AddScore(); } } }
void ATicTacToe2PlayerBlock::Highlight(bool bOn) { // Do not highlight if the block has already been activated. if (bIsActive) { return; }
if (bOn) { BlockMesh->SetMaterial(0, BaseMaterial); } else { BlockMesh->SetMaterial(0, BlueMaterial); } }
TicTacToe2PlayerBlockGrid.cpp
#include \"TicTacToe2PlayerBlockGrid.h\" #include \"TicTacToe2PlayerBlock.h\" #include \"Components/TextRenderComponent.h\" #include \"Engine/World.h\"
#define LOCTEXT_NAMESPACE \"PuzzleBlockGrid\"
ATicTacToe2PlayerBlockGrid::ATicTacToe2PlayerBlockGrid() { // Create dummy root scene component DummyRoot = CreateDefaultSubobject(TEXT(\"Dummy0\")); RootComponent = DummyRoot;
// Create static mesh component ScoreText = CreateDefaultSubobject(TEXT(\"ScoreText0\")); ScoreText->SetRelativeLocation(FVector(200.f,0.f,0.f)); ScoreText->SetRelativeRotation(FRotator(90.f,0.f,0.f)); ScoreText->SetText(FText::Format(LOCTEXT(\"ScoreFmt\", \"Score: {0}\"), FText::AsNumber(0))); ScoreText->SetupAttachment(DummyRoot);
// Set defaults Size = 3; BlockSpacing = 300.f; }
void ATicTacToe2PlayerBlockGrid::BeginPlay() { Super::BeginPlay();
// Number of blocks const int32 NumBlocks = Size * Size;
// Loop to spawn each block for(int32 BlockIndex=0; BlockIndex;> { const float XOffset = (BlockIndex/Size) * BlockSpacing; // Divide by dimension const float YOffset = (BlockIndex%Size) * BlockSpacing; // Modulo gives remainder
// Make position vector, offset from Grid location const FVector BlockLocation = FVector(XOffset, YOffset, 0.f) + GetActorLocation();
// Spawn a block ATicTacToe2PlayerBlock* NewBlock = GetWorld()->SpawnActor(BlockLocation, FRotator(0,0,0));
// Tell the block about its owner if (NewBlock != nullptr) { NewBlock->OwningGrid = this; } } }
void ATicTacToe2PlayerBlockGrid::AddScore() { // Increment score Score++;
// Update text ScoreText->SetText(FText::Format(LOCTEXT(\"ScoreFmt\", \"Score: {0}\"), FText::AsNumber(Score))); }
#undef LOCTEXT_NAMESPACE