Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • AI
  • feat/gameplay
  • feat/landscape
  • feat/rendering
  • master
5 results

Target

Select target project
  • saegame/drivesafe
1 result
Select Git revision
  • AI
  • feat/gameplay
  • feat/landscape
  • feat/rendering
  • master
5 results
Show changes

Commits on Source 5

Showing
with 329 additions and 27 deletions
File added
File added
No preview for this file type
......@@ -16,6 +16,9 @@ ACustomGameMode::ACustomGameMode()
// Create empy array of road obstacles
TrafficVehicles = TArray<ATrafficVehicle*>();
// Create empty array of ADiamondSquare
DiamondSquares = TArray<TObjectPtr<ADiamondSquare>>();
}
void ACustomGameMode::BeginPlay()
......@@ -36,6 +39,7 @@ void ACustomGameMode::BeginPlay()
PlaceUnspawnCollisionBox(i);
PlaceScoreCollisionBox(i);
CreateInitialRoadTiles();
CreateInitialDiamondSquare();
if(i > 0)
PlacePlayerCar(i);
PlaceTrafficVehicle(i);
......@@ -57,6 +61,17 @@ void ACustomGameMode::Tick(float DeltaTime)
}
fSpawnElapsedTime = 0.0f;
}
// Add DiamondSquare if number of DiamondSquare is less than iNumberOfInitHills
int iNumberOfHills = DiamondSquares.Num();
if (iNumberOfHills < iNumberOfInitHills)
{
for (int i = 0; i < iNumberOfInitHills - iNumberOfHills; i++)
{
NextHillSpawnPoint = DiamondSquares.Last()->GetAttachTransform();
AddDiamondSquare();
}
}
}
void ACustomGameMode::PlacePlayerCar(int player)
......@@ -88,6 +103,11 @@ void ACustomGameMode::PlaceTrafficVehicle(int player)
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
FVector SpawnPosition = FVector(10000.0f, StartingY, 100000.0f * player);
// Choose a random traffic vehicle class
int TrafficVehicleIndex = FMath::RandRange(0, TrafficVehiclesClasses.Num() - 1);
TSubclassOf<ATrafficVehicle> TrafficVehicleClass = TrafficVehiclesClasses[TrafficVehicleIndex];
ATrafficVehicle* TrafficVehicle = World->SpawnActor<ATrafficVehicle>(TrafficVehicleClass, FTransform(FRotator(), SpawnPosition), SpawnParams);
if (TrafficVehicle)
{
......@@ -104,7 +124,7 @@ void ACustomGameMode::PlaceUnspawnCollisionBox(int player)
{
ACustomGameState* CustomGameState = GetGameState<ACustomGameState>();
// Size of the box
float fHeight = 500.0f;
float fHeight = 1000.0;
float fDepth = 10.0f;
float fWidth = CustomGameState->iNumberOfLane * 2 * fTileSize;
FVector BoxExtent = FVector(fDepth / 2.0f, fWidth / 2.0f, fHeight / 2.0f);
......@@ -112,7 +132,7 @@ void ACustomGameMode::PlaceUnspawnCollisionBox(int player)
// Spawn Position of box
float fSpawnPositionX = -iNumberOfBackwardTiles * fTileSize - fDepth / 2.0f - fTileSize / 2;
float fSpawnpositionY = fWidth / 2.0f - fTileSize / 2;
float fSpawnPositionZ = fHeight / 2.0f + 100000.0f * player;
float fSpawnPositionZ = 0.0f;
FVector SpawnPosition = FVector(fSpawnPositionX, fSpawnpositionY, fSpawnPositionZ);
FTransform SpawnTransform = FTransform(FRotator(), SpawnPosition);
......@@ -191,6 +211,46 @@ void ACustomGameMode::CreateInitialRoadTiles()
}
}
void ACustomGameMode::CreateInitialDiamondSquare()
{
ACustomGameState* CustomGameState = GetGameState<ACustomGameState>();
// Spawn Position of box
float fSpawnPositionX = -2 * fTileSize - fTileSize / 2.0f;
float fSpawnPositionY = (CustomGameState->iNumberOfLane * fTileSize) - fTileSize / 2.0f;
float fSpawnPositionZ = 0.0f;
FVector SpawnPosition = FVector(fSpawnPositionX, fSpawnPositionY, fSpawnPositionZ);
NextHillSpawnPoint = FTransform(FRotator(), SpawnPosition);
for (int i = 0; i < 30; i++)
{
AddDiamondSquare();
}
}
void ACustomGameMode::AddDiamondSquare()
{
ACustomGameState* CustomGameState = GetGameState<ACustomGameState>();
UWorld* World = GetWorld();
if (World)
{
auto DeferredDiamondSquare = Cast<ADiamondSquare>(UGameplayStatics::BeginDeferredActorSpawnFromClass(this, DiamondSquareClass, NextHillSpawnPoint));
if (DeferredDiamondSquare != nullptr)
{
DeferredDiamondSquare->startX = fHillStartX;
fHillStartX += DeferredDiamondSquare->XSize;
UGameplayStatics::FinishSpawningActor(DeferredDiamondSquare, NextHillSpawnPoint);
NextHillSpawnPoint = DeferredDiamondSquare->GetAttachTransform();
DeferredDiamondSquare->fSpeed = CustomGameState->fSpeed;
DiamondSquares.Add(DeferredDiamondSquare);
}
}
}
void ACustomGameMode::AddRoadTileRow()
{
ACustomGameState* CustomGameState = GetGameState<ACustomGameState>();
......@@ -237,6 +297,16 @@ void ACustomGameMode::OnUnspawnCollisionBoxOverlap(UPrimitiveComponent* Overlapp
// Destroy the actor
TrafficVehicle->Destroy();
}
// Try cast to DiamondSquare
ADiamondSquare* DiamondSquare = Cast<ADiamondSquare>(OtherActor);
if (DiamondSquare)
{
// Remove the DiamondSquare from the array
DiamondSquares.Remove(DiamondSquare);
// Destroy the actor
DiamondSquare->Destroy();
}
}
void ACustomGameMode::OnScoreCollisionBoxEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
......@@ -249,5 +319,11 @@ void ACustomGameMode::OnScoreCollisionBoxEndOverlap(UPrimitiveComponent* Overlap
// Get the game state
ACustomGameState* CustomGameState = GetGameState<ACustomGameState>();
CustomGameState->fSpeed *= 1.05;
// Update the speed of all DiamonSquares
for (auto DiamondSquare : DiamondSquares)
{
DiamondSquare->fSpeed = CustomGameState->fSpeed;
}
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "DiamondSquare.h"
#include "ProceduralMeshComponent.h"
#include "KismetProceduralMeshLibrary.h"
// Sets default values
ADiamondSquare::ADiamondSquare()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
RootComp = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
SetRootComponent(RootComp);
ProceduralMesh = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("ProceduralMesh"));
ProceduralMesh->SetupAttachment(RootComp);
AttachPoint = CreateDefaultSubobject<UArrowComponent>(TEXT("AttachPoint"));
AttachPoint->SetupAttachment(ProceduralMesh);
}
// Called when the game starts or when spawned
void ADiamondSquare::BeginPlay()
{
Super::BeginPlay();
}
void ADiamondSquare::OnConstruction(const FTransform& Transform)
{
Super::OnConstruction(Transform);
Vertices.Reset();
Triangles.Reset();
UV0.Reset();
CreateVertices();
CreateTriangles();
UKismetProceduralMeshLibrary::CalculateTangentsForMesh(Vertices, Triangles, UV0, Normals, Tangents);
ProceduralMesh->CreateMeshSection(0, Vertices, Triangles, Normals, UV0, TArray<FColor>(), TArray<FProcMeshTangent>(), false);
ProceduralMesh->SetMaterial(0, Material);
AttachPoint->SetRelativeLocation(FVector(XSize * Scale, 0.0f, 0));
}
// Called every frame
void ADiamondSquare::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
Move(DeltaTime);
}
void ADiamondSquare::CreateVertices()
{
float centerY = (Scale * YSize) / 2.0f; // Milieu de la carte
float N = (Scale * YSize) * flatRatio; // Largeur de la zone plate
float M = (Scale * YSize) * slopeRatio; // Largeur de la transition
float k = 6.0f / M; // Contrle la pente de la sigmode
float actorX = GetActorLocation().X;
float actorY = GetActorLocation().Y;
float actorZ = GetActorLocation().Z;
for (int y = 0; y <= YSize; y++)
{
float distance = FMath::Abs(y * Scale - centerY);
float sigmoidFactor = 0.0f;
if (distance > N / 2.0f && distance < (N / 2.0f + M))
{
float x0 = N / 2.0f;
float x1 = N / 2.0f + M;
float yy = distance - N / 2.0f;
sigmoidFactor = yy / (x1 - x0);
}
else if (distance >= (N / 2.0f + M))
{
sigmoidFactor = 1.0f;
}
for (int x = 0; x <= XSize; x++)
{
// Gnration du bruit de Perlin
float noise = (FMath::PerlinNoise2D(FVector2D((startX + x) * NoiseScale, y * NoiseScale)) + 1.0f) * ZMultiplier;
// Modulation par la courbe de Gauss
float z = noise * sigmoidFactor;
Vertices.Add(FVector((x - XSize / 2.0f) * Scale, (y - YSize / 2.0f) * Scale, z));
UV0.Add(FVector2D((x - XSize / 2.0f) * UVScale, (y - YSize / 2.0f) * UVScale));
}
}
}
void ADiamondSquare::CreateTriangles()
{
int vertex = 0;
for (int y = 0; y < YSize; y++)
{
for (int x = 0; x < XSize; x++)
{
Triangles.Add(vertex); // Bottom left
Triangles.Add(vertex + XSize + 1); // Top left
Triangles.Add(vertex + 1); // Bottom right
Triangles.Add(vertex + 1); // Bottom right
Triangles.Add(vertex + XSize + 1); // Top left
Triangles.Add(vertex + XSize + 2); // Top right
vertex++;
}
vertex++;
}
}
void ADiamondSquare::Move(float DeltaTime)
{
FVector NewLocation = GetActorLocation();
NewLocation.X -= fSpeed * DeltaTime;
SetActorLocation(NewLocation);
}
......@@ -119,11 +119,25 @@ void ATrafficVehicle::FrontCollisionCheck()
fSpeed = TrafficVehicle->fSpeed;
fWheelSpeed = TrafficVehicle->fWheelSpeed;
OnSpeedChanged(fSpeed, fWheelSpeed);
float fDirection = -GetActorRightVector().Y;
float fTargetLane = LaneChangeComponent->fCurrentLane + fDirection;
// If the vehicle is not already changing lane
if (!LaneChangeComponent->bIsMoving)
{
// If the vehicle is in the opposite direction and will not go in the opposite lane
// Or if the vehicle is in the same direction and will not go in the opposite lane
if ((fDirection > 0 && fTargetLane < CustomGameState->iNumberOfLane) ||
(fDirection < 0 && fTargetLane >= CustomGameState->iNumberOfLane))
{
bIsBlinking = true;
LaneChangeCheck();
}
}
}
}
}
}
void ATrafficVehicle::LaneChangeCheck()
{
......@@ -140,21 +154,7 @@ void ATrafficVehicle::LaneChangeCheck()
// If we don't hit a subclass of TrafficVehicle or a subclass of PlayerCar
if (!GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECollisionChannel::ECC_Visibility, CollisionParams))
{
float fDirection = -GetActorRightVector().Y;
float fTargetLane = LaneChangeComponent->fCurrentLane + fDirection;
// If the vehicle is not already changing lane
if (!LaneChangeComponent->bIsMoving)
{
// If the vehicle is in the opposite direction and will not go in the opposite lane
// Or if the vehicle is in the same direction and will not go in the opposite lane
if ((fDirection > 0 && fTargetLane < CustomGameState->iNumberOfLane) ||
(fDirection < 0 && fTargetLane >= CustomGameState->iNumberOfLane))
{
// call a lambda after Timerhandle of 1 second
bIsBlinking = true;
GetWorld()->GetTimerManager().SetTimer(ChangeLaneTimerHandle, [this, fDirection]() { ChangeLaneCallback(fDirection); }, 1.0f, false);
}
}
ChangeLaneCallback(-GetActorRightVector().Y);
}
}
......@@ -177,12 +177,10 @@ void ATrafficVehicle::Move_Implementation(float DeltaTime)
void ATrafficVehicle::ChangeLaneCallback(float fDirection)
{
LaneChangeComponent->ChangeLane(fDirection, 300);
bIsBlinking = false;
fSpeed = fTargetSpeed;
fWheelSpeed = fTargetWheelSpeed;
OnSpeedChanged(fSpeed, fWheelSpeed);
RearLeftBlinker->SetVisibility(false);
LaneChangeComponent->ChangeLane(fDirection, 300);
}
void ATrafficVehicle::BlinkLeft(float DeltaTime)
......@@ -195,6 +193,12 @@ void ATrafficVehicle::BlinkLeft(float DeltaTime)
RearLeftBlinker->SetVisibility(!RearLeftBlinker->IsVisible());
fBlinkElapsedTime = 0.0f;
}
if (LaneChangeComponent->bIsMoving)
{
bIsBlinking = false;
RearLeftBlinker->SetVisibility(false);
}
}
}
......
......@@ -5,6 +5,7 @@
#include "CustomGameState.h"
#include "RoadTile.h"
#include "PlayerCar.h"
#include "DiamondSquare.h"
#include "TrafficVehicle.h"
#include "CoreMinimal.h"
......@@ -35,8 +36,11 @@ public:
UPROPERTY(EditAnywhere, Category = "Spawnable Class")
TSubclassOf<APlayerCar> PlayerCarClass;
UPROPERTY(EditAnywhere, Category = "Spawnable Class")
TSubclassOf<ADiamondSquare> DiamondSquareClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawnable Class")
TSubclassOf<ATrafficVehicle> TrafficVehicleClass;
TArray<TSubclassOf<ATrafficVehicle>> TrafficVehiclesClasses;
UPROPERTY(EditAnywhere, Category = "Spawnable Class")
TSubclassOf<AActor> UnspawnCollisionBoxClass;
......@@ -54,6 +58,9 @@ public:
UPROPERTY(EditAnywhere, Category = "Config")
int32 iNumberOfBackwardTiles = 3;
UPROPERTY(EditAnywhere, Category = "Config")
int32 iNumberOfInitHills = 50;
// ********** Runtime **********
UPROPERTY(VisibleInstanceOnly, Category = "Runtime")
FTransform NextSpawnPoint;
......@@ -61,9 +68,14 @@ public:
UPROPERTY(VisibleInstanceOnly, Category = "Runtime")
FTransform NextRowSpawnPoint;
UPROPERTY(VisibleInstanceOnly, Category = "Runtime")
FTransform NextHillSpawnPoint;
UPROPERTY(VisibleInstanceOnly, Category = "Runtime", BlueprintReadWrite)
float fSpeed = 100.0f;
float fHillStartX = 0.0f;
public:
TArray<ATrafficVehicle*> GetTrafficVehicles();
......@@ -73,6 +85,8 @@ private:
private:
void CreateInitialRoadTiles();
void CreateInitialDiamondSquare();
void AddDiamondSquare();
ARoadTile* AddRoadTile(TSubclassOf<ARoadTile> RoadTileClass);
void AddRoadTileRow();
void PlacePlayerCar(int player);
......@@ -80,6 +94,9 @@ private:
void PlaceUnspawnCollisionBox(int player);
void PlaceScoreCollisionBox(int player);
TArray<TObjectPtr<ADiamondSquare>> DiamondSquares;
// On collision with the unspawn box
UFUNCTION()
void OnUnspawnCollisionBoxOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
......@@ -91,7 +108,4 @@ private:
protected:
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
};
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ProceduralMeshComponent.h"
#include <Components/ArrowComponent.h>
#include "DiamondSquare.generated.h"
class UProceduralMeshComponent;
class UMaterialInterface;
UCLASS()
class DRIVESAFE_API ADiamondSquare : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ADiamondSquare();
UPROPERTY(VisibleAnywhere)
USceneComponent* RootComp;
UPROPERTY(VisibleAnywhere)
UProceduralMeshComponent* ProceduralMesh;
UPROPERTY(VisibleAnywhere)
UArrowComponent* AttachPoint;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0))
int XSize = 100;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0))
int YSize = 100;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0))
float ZMultiplier = 250.0f;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0))
float NoiseScale = 0.1f;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0.000000001))
float Scale = 100;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0.000000001))
float UVScale = 1.0f;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0))
float flatRatio = 0.1;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0))
float slopeRatio = 0.3;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0))
int startX = 0;
float fSpeed = 0.0f;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, Category = "Diamond Square")
UMaterialInterface* Material;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
virtual void OnConstruction(const FTransform& Transform) override;
FORCEINLINE const FTransform& GetAttachTransform() const { return AttachPoint->GetComponentTransform(); }
private:
TArray<FVector> Vertices;
TArray<int> Triangles;
TArray<FVector2D> UV0;
TArray<FVector> Normals;
TArray<struct FProcMeshTangent> Tangents;
void CreateVertices();
void CreateTriangles();
void Move(float DeltaTime);
};
......@@ -95,7 +95,6 @@ private:
float fMeshLength;
float fMeshWidth;
FTimerHandle ChangeLaneTimerHandle;
void ChangeLaneCallback(float fDirection);
float fBlinkElapsedTime = 0.0f;
bool bIsBlinking = false;
......
......@@ -10,7 +10,7 @@ public class drivesafe : ModuleRules
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "LearningAgents", "LearningAgentsTraining", "LearningTraining" });
PrivateDependencyModuleNames.AddRange(new string[] { "LearningAgents", "LearningAgentsTraining", "LearningTraining" });
PrivateDependencyModuleNames.AddRange(new string[] { "LearningAgents", "LearningAgentsTraining", "LearningTraining", "ProceduralMeshComponent" });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
......