Compare commits

18 Commits
main ... Bullet

Author SHA1 Message Date
72e9caf2c1 Minor - Implémente la collision joueur-centipede - V3.5.0
Implémente la détection de collision entre le joueur et le centipede.

Le joueur perd une vie lors de la collision et devient temporairement invincible.

Ajoute la logique de fin de niveau lorsque tous les segments du centipede sont détruits.
2025-11-06 20:47:26 +01:00
0da3851dde Minor - Gère la mort des segments - V3.4.0
Modifie la logique de destruction des segments de centipède.

Au lieu de détruire immédiatement le segment, désactive la collision et le rend invisible. Des champignons sont générés à l'endroit de sa mort et le score du joueur est augmenté.

L'événement OnSegmentDestroyed est renommé en OnSegmentHit pour refléter la nouvelle logique.
2025-11-05 14:19:08 +01:00
NisemonoQ
469451e491 Minor - Mushroom/Projectile interaction
Ok, le reste de la fonction ne marchait pas à cause d'un BlockAll qui s'était infiltré dans le code du Mushroom
Je vais passer à l'interaction avec le centipede
2025-11-04 23:34:15 +01:00
064d4cd576 Minor - Ajoute interaction projectile/champignon - V3.2.0
Implémente la détection de collision entre les projectiles et les champignons.

Le champignon est détruit après avoir été touché le nombre de fois défini par sa durée de vie.

Le projectile est détruit après avoir touché un champignon.
2025-11-04 18:29:30 +01:00
NisemonoQ
c8f3f53a8f Minor - Mushroom function
J'ai ajouté une fonction au Mushroom pour enregistrer le hit de la balle lorsqu'il la touche, mais on dirait que ça ne veut pas marcher.
2025-11-04 17:02:24 +01:00
NisemonoQ
6305198eda Major - Comportement de la Balle quasiment complet
Il ne reste plus qu'à associer le GameMode et la reconnaissance de la collision, j'ai déjà la fonction OnHit sur laquelle on peut commencer à bosser
2025-11-01 13:05:52 +01:00
NisemonoQ
9ddc2fdbed Minor - Ajustement sur la balle
Le sprite devrait apparaitre et se déplacer avec tout l'objet + la balle.
2025-10-31 17:54:49 +01:00
NisemonoQ
7a9a6d257a Merge branch 'main' into Bullet 2025-10-31 16:31:56 +01:00
NisemonoQ
49685ed167 Minor - Nouveau comportement pour la Balle
La Balle devrait pouvoir directement se déplacer et avoir son mesh qui spawne aussi
2025-10-31 16:16:53 +01:00
NisemonoQ
ed5475299e Revert "Minor - Petit changement pour le spawn des balles"
This reverts commit 406bafff0a.
2025-10-30 22:44:26 +01:00
NisemonoQ
406bafff0a Minor - Petit changement pour le spawn des balles 2025-10-30 22:00:07 +01:00
NisemonoQ
d2968f0d36 Minor - Sprite du Projectile
Le modèle 3D du projectile apparait enfin, maintenant, il faut que je puisse donner au modèle la bonne position de départ.
2025-10-28 16:20:39 +01:00
NisemonoQ
365727aa4c Minor - Apparition du projectile dans la scène à partir du joueur
Le joueur peut enfin faire apparaître le projectile dans la scène après avoir appuyé sur la touche "Espace".
Cependant le Mesh n'apparait toujours pas pour l'instant mais j'ai presque fini.
2025-10-27 11:31:52 +01:00
NisemonoQ
c7702b9f64 Minor - Apparition du sprite du tir
Normalement, le spirte apparait bien lors de l'appui sur la touche espace
2025-10-20 18:00:41 +02:00
NisemonoQ
5624625eda Minor - Projectile Spawning logic done
En passant par une méthode similaire à la génération de la caméra, j'ai pu faire spawner les projectiles, maintenant à partir de leur classe, je vais ajouter leur déplacement et physique dès leur initiation.
2025-10-19 18:08:05 +02:00
NisemonoQ
17c6475397 Minor - Bullet Spawning Method
La méthode est quasiment finie, il reste juste un pb au niveau de l'objet/la classe à appeler.
2025-10-17 17:13:48 +02:00
NisemonoQ
f57f6b8832 Minor - Ajout de la logique de Projectile au PlayerPawn
Le playerPawn possède une fonction qui pourra appeler le script de projectile.
Prochaine étape, complétion du système de Projectile.
2025-10-17 15:27:19 +02:00
NisemonoQ
8733dfd87f Merge branch 'main' into Bullet 2025-10-17 14:02:35 +02:00
13 changed files with 356 additions and 61 deletions

View File

@@ -103,4 +103,62 @@ ManualIPAddress=
[CoreRedirects]
+ClassRedirects=(OldName="/Script/M4_CPP.M4_CentipedeController",NewName="/Script/M4_CPP.M4_CentipedeController")
+FunctionRedirects=(OldName="/Script/M4_CPP.M4_CentipedeController.OnSegmentDestroyed",NewName="/Script/M4_CPP.M4_CentipedeController.OnSegmentHit")
[/Script/Engine.CollisionProfile]
-Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision",bCanModify=False)
-Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
-Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
-Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
-Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
-Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ",bCanModify=False)
-Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ",bCanModify=False)
-Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic",Response=ECR_Block),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.",bCanModify=False)
-Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors",bCanModify=False)
-Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors",bCanModify=False)
-Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.",bCanModify=False)
-Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.",bCanModify=False)
-Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Block),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
+Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision")
+Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.")
+Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ")
+Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ")
+Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic"),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.")
+Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.")
+Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors")
+Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors")
+Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.")
+Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.")
+Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.")
+Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.")
+Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.")
+Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False,Name="Projectile")
-ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall")
-ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn")
-ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic")
-ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor")
-ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic")
+ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall")
+ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn")
+ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic")
+ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor")
+ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic")
-CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic")
-CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic")
-CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle")
-CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn")
+CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic")
+CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic")
+CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle")
+CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn")

Binary file not shown.

Binary file not shown.

View File

@@ -6,7 +6,7 @@
UM4_CentipedeController::UM4_CentipedeController()
{
SegmentRemainingCount = BodyCount;
}
void UM4_CentipedeController::Initialize(FSubsystemCollectionBase& Collection)
@@ -90,11 +90,11 @@ TStatId UM4_CentipedeController::GetStatId() const
void UM4_CentipedeController::SpawnCentipede()
{
AM4_Gamemode* GM = Cast<AM4_Gamemode>(GetWorld()->GetAuthGameMode());
if (!GM) return;
GM_REF_PTR = Cast<AM4_Gamemode>(GetWorld()->GetAuthGameMode());
if (!GM_REF_PTR) return;
FVector SpawnLocation = FVector(
GM->MushroomSpawnBounds.Max.X,
GM_REF_PTR->MushroomSpawnBounds.Max.X,
0.f,
0.f
);
@@ -201,13 +201,16 @@ bool UM4_CentipedeController::CheckCollision(AM4_CentipedeBody* Segment, FVector
FVector CurrentPos = Segment->GetActorLocation();
FVector NextPos = CurrentPos + FVector(0.f, Direction.Y * CellSize, 0.f);
AM4_Gamemode* GM = Cast<AM4_Gamemode>(GetWorld()->GetAuthGameMode());
if (!GM) return false;
if (!GM_REF_PTR)
{
GM_REF_PTR = Cast<AM4_Gamemode>(GetWorld()->GetAuthGameMode());
if (!GM_REF_PTR) return false;
}
const float LeftBound = GM->MushroomSpawnBounds.Min.Y;
const float RightBound = GM->MushroomSpawnBounds.Max.Y;
const float MinRows = GM->MushroomSpawnBounds.Min.X;
const float MaxRows = GM->MushroomSpawnBounds.Max.X;
const float LeftBound = GM_REF_PTR->MushroomSpawnBounds.Min.Y;
const float RightBound = GM_REF_PTR->MushroomSpawnBounds.Max.Y;
const float MinRows = GM_REF_PTR->MushroomSpawnBounds.Min.X;
const float MaxRows = GM_REF_PTR->MushroomSpawnBounds.Max.X;
if (NextPos.Y <= LeftBound || NextPos.Y >= RightBound)
{
@@ -290,7 +293,7 @@ void UM4_CentipedeController::UpdateHeadStatus()
}
}
void UM4_CentipedeController::OnSegmentDestroyed(AM4_CentipedeBody* DestroyedSegment)
void UM4_CentipedeController::OnSegmentHit(AM4_CentipedeBody* DestroyedSegment)
{
if (!DestroyedSegment) return;
@@ -312,7 +315,33 @@ void UM4_CentipedeController::OnSegmentDestroyed(AM4_CentipedeBody* DestroyedSeg
BodySegments[SegmentIndex - 1]->NextBody = nullptr;
}
BodySegments.RemoveAt(SegmentIndex);
SegmentHistory.RemoveAt(SegmentIndex);
SegmentDirections.Remove(DestroyedSegment);
// disable collision and hide the destroyed segment
DestroyedSegment->GetStaticMeshComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
DestroyedSegment->SetActorHiddenInGame(true);
// Increase player score
if (!GM_REF_PTR)
{
GM_REF_PTR = Cast<AM4_Gamemode>(GetWorld()->GetAuthGameMode());
if (!GM_REF_PTR) return;
}
GM_REF_PTR->AddScore(100);
SpawnMushroomsAtSegmentDeathPos(DestroyedSegment->GetActorLocation());
// Decresase the remaining segment count and check if all segments are destroyed
SegmentRemainingCount--;
if (SegmentRemainingCount <= 0)
{
// TODO: Trigger level complete or respawn centipede
UE_LOG(M4_CPP, Warning, TEXT("All centipede segments destroyed!"));
}
}
void UM4_CentipedeController::SpawnMushroomsAtSegmentDeathPos(FVector Location)
{
FVector Offset = FVector(0.f, FMath::RandRange(-CellSize, CellSize), 0.f);
FVector SpawnLocation = Location + Offset;
GetWorld()->SpawnActor<AM4_Mushroom>(
AM4_Mushroom::StaticClass(),
SpawnLocation,
FRotator::ZeroRotator
);
}

View File

@@ -6,6 +6,7 @@
#include "M4_CTP_Macros.h"
#include "Kismet/GameplayStatics.h"
#include "M4_Gamemode.h"
#include "M4_Projectile.h"
// Sets default values
@@ -31,12 +32,29 @@ AM4_Mushroom::AM4_Mushroom()
const FVector2D MushroomScale = FVector2D(0.3f, 0.25f);
GetStaticMeshComponent()->SetRelativeScale3D(FVector(1.f, 0.45f, 0.20f));
// Set collision profile to overlap all
// Set collision profile to block all
GetStaticMeshComponent()->SetCollisionProfileName(TEXT("OverlapAll"));
}
void AM4_Mushroom::BeginPlay()
{
MushLife = 2;
DestructionHit = 0;
Super::BeginPlay();
}
void AM4_Mushroom::OnHit(UPrimitiveComponent* HitComp,AActor* OtherActor,UPrimitiveComponent* OtherComp,FVector NormalImpulse,const FHitResult& Hit)
{
AM4_Projectile* Projectile = Cast<AM4_Projectile>(OtherActor);
if (!Projectile)
{
return;
}
if (DestructionHit++ == MushLife)
{
Destroy();
}
}

View File

@@ -1,8 +1,9 @@
#include "M4_PlayerPawn.h"
#include "EnhancedInputComponent.h"
#include "M4_Gamemode.h"
#include "M4_LOG.h"
#include "M4_Projectile.h"
#include "GameFramework/PlayerController.h"
#include "Camera/CameraComponent.h"
AM4_PlayerPawn::AM4_PlayerPawn()
{
@@ -16,10 +17,16 @@ AM4_PlayerPawn::AM4_PlayerPawn()
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(RootComponent);
MeshComponent->SetMobility(EComponentMobility::Movable);
MeshComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
MeshComponent->SetCollisionProfileName(UCollisionProfile::Pawn_ProfileName);
MeshComponent->SetRelativeScale3D(FVector(1.0f, MeshScale.Y, MeshScale.X));
MeshComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
MeshComponent->SetCollisionObjectType(ECC_Pawn);
MeshComponent->SetCollisionResponseToAllChannels(ECR_Block);
MeshComponent->SetGenerateOverlapEvents(true);
MeshComponent->OnComponentBeginOverlap.AddDynamic(this,&AM4_PlayerPawn::OnPlayerOverlap);
MeshComponent->SetRelativeScale3D(FVector(1.0f, MeshScale.Y, MeshScale.X));
static ConstructorHelpers::FObjectFinder<UStaticMesh> DefaultMeshRef(TEXT("/Game/CTP/04_Mesh/SM_Cube.SM_Cube"));
if (DefaultMeshRef.Succeeded())
@@ -32,12 +39,18 @@ AM4_PlayerPawn::AM4_PlayerPawn()
{
MoveAction = MoveActionRef.Object;
}
static ConstructorHelpers::FObjectFinder<UInputAction> ShootActionRef(TEXT("/Game/CTP/03_Input/IA_Shoot.IA_Shoot"));
if (ShootActionRef.Succeeded())
{
ShootAction = ShootActionRef.Object;
}
}
void AM4_PlayerPawn::BeginPlay()
{
Super::BeginPlay();
SetActorLocation(FVector(0.0f, 0.0f, -400.0f));
SetActorLocation(FVector(-400.0f, 0.0f, -400.0f));
}
void AM4_PlayerPawn::Tick(float DeltaTime)
@@ -51,8 +64,6 @@ void AM4_PlayerPawn::Tick(float DeltaTime)
NewLocation.Y = FMath::Clamp(NewLocation.Y, GM->Bounds.Min.Y, GM->Bounds.Max.Y);
SetActorLocation(NewLocation);
}
}
void AM4_PlayerPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
@@ -64,10 +75,71 @@ void AM4_PlayerPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputCompo
{
Input->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AM4_PlayerPawn::Move);
}
if (ShootAction)
{
Input->BindAction(ShootAction, ETriggerEvent::Triggered, this, &AM4_PlayerPawn::Shoot);
}
}
}
void AM4_PlayerPawn::Move(const FInputActionInstance& Instance)
{
LastMoveValue = Instance.GetValue().Get<FVector2D>().GetSafeNormal();
}
void AM4_PlayerPawn::Shoot(const FInputActionInstance& Inst)
{
if (Proj)
{
UWorld* World = GetWorld();
if (World)
{
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = this;
const FVector InitialLocation = FVector(-400.f, GetActorLocation().Y, GetActorLocation().Z);
const FRotator InitialRotation = FRotator(0.f);
AM4_Projectile* Projectile = World->SpawnActor<AM4_Projectile>(Proj, InitialLocation, InitialRotation, SpawnParams);
if (Projectile)
{
Projectile->FireInDir(InitialLocation);
}
}
}
};
void AM4_PlayerPawn::OnPlayerOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
if (!OtherActor || OtherActor == this || bIsInvincible)
{
return;
}
AM4_CentipedeBody* CentipedeSegment = Cast<AM4_CentipedeBody>(OtherActor);
if (CentipedeSegment)
{
UE_LOG(M4_CPP, Warning, TEXT("Player collided with Centipede Segment!"));
if (AM4_Gamemode* GM = Cast<AM4_Gamemode>(GetWorld()->GetAuthGameMode()))
{
GM->LoseLife();
UE_LOG(M4_CPP, Warning, TEXT("Player Lives Remaining: %d"), GM->GetLives());
bIsInvincible = true;
GetWorldTimerManager().SetTimer(InvincibleTimerHandle,this, &AM4_PlayerPawn::EndInvincibility, InvinciblityDuration, false);
}
}
}
void AM4_PlayerPawn::EndInvincibility()
{
bIsInvincible = false;
UE_LOG(M4_CPP, Warning, TEXT("Player invincibility ended."));
}

View File

@@ -1,35 +1,108 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "M4_Projectile.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "M4_Projectile.h"
#include "Components/MeshComponent.h"
#include "M4_Gamemode.h"
#include "M4_Mushroom.h"
#include "Components/SphereComponent.h"
// Sets default values
AM4_Projectile::AM4_Projectile()
{
MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComp"));
MeshComp-> SetRelativeScale3D(FVector(1.f, .1f,.1f));
MeshComp->BodyInstance.SetCollisionProfileName(TEXT("Projectile"));
MeshComp->OnComponentHit.AddDynamic(this, &AM4_Projectile::OnHit);
PrimaryActorTick.bCanEverTick = true;
// Crée d'abord le composant de collision comme root
CollisionComp = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));
CollisionComp->InitSphereRadius(15.0f);
CollisionComp->SetCollisionProfileName(TEXT("Projectile"));
CollisionComp->OnComponentBeginOverlap.AddDynamic(this, &AM4_Projectile::OnOverlap);
CollisionComp->SetGenerateOverlapEvents(true);
RootComponent = CollisionComp;
// Ensuite attache le mesh au composant de collision
ProjectileMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ProjectileMeshComponent"));
ProjectileMeshComponent->SetupAttachment(RootComponent);
ProjectileMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); // Le mesh ne gère pas la collision
static ConstructorHelpers::FObjectFinder<UStaticMesh> Mesh(TEXT("/Game/CTP/04_Mesh/SM_Projectile.SM_Projectile"));
if(Mesh.Succeeded())
{
ProjectileMeshComponent->SetStaticMesh(Mesh.Object);
}
static ConstructorHelpers::FObjectFinder<UMaterial> Material(TEXT("/Game/CTP/05_Material/M_Player.M_Player"));
if (Material.Succeeded())
{
ProjectileMat = UMaterialInstanceDynamic::Create(Material.Object, ProjectileMeshComponent);
}
ProjectileMeshComponent->SetMaterial(0, ProjectileMat);
ProjectileMeshComponent->SetRelativeScale3D(FVector(.3f, .3f, .35f));
ProjectileMeshComponent->SetMobility(EComponentMobility::Movable);
ProjectileMeshComponent->SetRelativeLocation(FVector::ZeroVector);
// Configure le ProjectileMovementComponent
ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovementComponent"));
ProjectileMovementComponent->SetUpdatedComponent(CollisionComp); // Maintenant CollisionComp existe
ProjectileMovementComponent->InitialSpeed = 380.f;
ProjectileMovementComponent->MaxSpeed = 380.f;
ProjectileMovementComponent->bRotationFollowsVelocity = false;
ProjectileMovementComponent->bShouldBounce = false;
ProjectileMovementComponent->ProjectileGravityScale = 0.0f;
InitialLifeSpan = 10.f;
}
///FAIRE SUPER GAFFE AUX INDENTATIONS ET LES FOR LOOPS sont à bien faire.
///Ce qui est critique dans notre code doit être vraiment bien mis en évidence sans être obscurci par la boucle.
///Gestion des pointeurs à revoir, lisibilité des fonctions critiques
void AM4_Projectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector Impulse, const FHitResult& Hit)
{
}
/* Called when the game starts or when spawned
void AM4_Projectile::BeginPlay()
{
Super::BeginPlay();
InitialLoc = GetActorLocation();
}
Called every frame
void AM4_Projectile::OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
UE_LOG(LogTemp, Warning, TEXT("Projectile OVERLAP: %s"), *OtherActor->GetName());
if (!OtherActor || OtherActor == this || !OtherComp)
{
return;
}
AM4_Mushroom* Mushroom = Cast<AM4_Mushroom>(OtherActor);
if (Mushroom)
{
UE_LOG(LogTemp, Warning, TEXT("OVERLAP MUSHROOM!"));
FVector NormalImpulse = FVector::ZeroVector;
Mushroom->OnHit(OverlappedComponent, this, OtherComp, NormalImpulse, SweepResult);
Destroy();
return;
}
AM4_CentipedeBody* CentipedeBody = Cast<AM4_CentipedeBody>(OtherActor);
if (CentipedeBody)
{
UE_LOG(LogTemp, Warning, TEXT("OVERLAP CENTIPEDE BODY!"));
UM4_CentipedeController* CentipedeController = GetWorld()->GetSubsystem<UM4_CentipedeController>();
if (CentipedeController)
{
CentipedeController->OnSegmentHit(CentipedeBody);
}
Destroy();
}
}
void AM4_Projectile::FireInDir(const FVector& ShootDir)
{
SetActorLocation(InitialLoc);
ProjectileMovementComponent->Velocity.Z = -1 * ((ShootDir.Z + 380.f) * ProjectileMovementComponent->InitialSpeed);
ProjectileMovementComponent->Velocity.X = 0.f;
}
// Called every frame
void AM4_Projectile::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}*/
Super::Tick( DeltaTime);
}

View File

@@ -31,13 +31,14 @@ public:
float MoveInterval = 0.1f;
UFUNCTION(BlueprintCallable, Category = "Centipede")
void OnSegmentDestroyed(AM4_CentipedeBody* DestroyedSegment);
void OnSegmentHit(AM4_CentipedeBody* DestroyedSegment);
private:
UPROPERTY()
TArray<AM4_CentipedeBody*> BodySegments;
TArray<TArray<FVector>> SegmentHistory; // Historique pour chaque segment
int32 MaxHistorySize = 200;
int8 SegmentRemainingCount = 0;
UPROPERTY(EditAnywhere, Category = "Centipede")
int32 SegmentSpacing = 15; // Distance en nombre de frames entre segments
@@ -52,9 +53,13 @@ private:
void SpawnCentipede();
void UpdateHeadStatus();
void SpawnMushroomsAtSegmentDeathPos(FVector Location);
bool CheckCollision(AM4_CentipedeBody* Segment, FVector2D Direction);
FVector2D GetSegmentDirection(AM4_CentipedeBody* Segment);
void SetSegmentDirection(AM4_CentipedeBody* Segment, FVector2D Direction);
UPROPERTY()
class AM4_Gamemode* GM_REF_PTR;
};

View File

@@ -13,9 +13,14 @@ class M4_CPP_API AM4_Mushroom : public AStaticMeshActor
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AM4_Mushroom();
int MushLife;
int DestructionHit = 0;
UFUNCTION()
void OnHit(UPrimitiveComponent* HitComp,AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse,const FHitResult& Hit);
protected:
virtual void BeginPlay() override;
};

View File

@@ -1,5 +1,6 @@
#pragma once
#include "M4_Projectile.h"
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "InputAction.h"
@@ -11,6 +12,7 @@ UCLASS()
class AM4_PlayerPawn : public APawn
{
GENERATED_BODY()
public:
AM4_PlayerPawn();
@@ -18,6 +20,19 @@ public:
virtual void Tick(float DeltaTime) override;
virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
void Move(const FInputActionInstance& Instance);
void Shoot(const FInputActionInstance& Inst);
UPROPERTY(VisibleAnywhere)
TSubclassOf<AM4_Projectile> Proj = AM4_Projectile::StaticClass();
UFUNCTION()
void OnPlayerOverlap(
UPrimitiveComponent* OverlappedComponent,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult);
protected:
@@ -27,7 +42,19 @@ protected:
UPROPERTY()
UInputAction* MoveAction;
UPROPERTY()
UInputAction* ShootAction;
float MoveSpeed = 500.f;
FVector2D MeshScale = FVector2D(0.6f, 0.5f);
FVector2D LastMoveValue = FVector2D::ZeroVector;
UPROPERTY()
bool bIsInvincible = false;
UPROPERTY()
float InvinciblityDuration = 2.0f;
FTimerHandle InvincibleTimerHandle;
void EndInvincibility();
};

View File

@@ -1,4 +1,4 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "GameFramework/ProjectileMovementComponent.h"
#pragma once
@@ -6,31 +6,39 @@
#include "GameFramework/Actor.h"
#include "M4_Projectile.generated.h"
class UProjectileMovementComponent;
class USphereComponent;
class UMeshComponent;
UCLASS()
class M4_CPP_API AM4_Projectile : public AActor
{
GENERATED_BODY()
UPROPERTY(VisibleDefaultsOnly, Category = Projectile)
UMeshComponent* MeshComp;
UPROPERTY(VisibleAnywhere,BlueprintReadOnly, Category = Movement, meta = (AllowPrivateAccess = "true"))
UProjectileMovementComponent* ProjectileMovem;
public:
AM4_Projectile();
protected:
float bullSpeed = 50.f;
float lifeTime = 3.f;
virtual void Tick( float DeltaTime ) override;
virtual void BeginPlay() override;
bool CollisionCheck = false;
FVector InitialLoc;
FVector NewLoc;
UPROPERTY(VisibleDefaultsOnly, Category = Projectile)
USphereComponent* CollisionComp;
UPROPERTY(VisibleAnywhere, Category = Movement)
UProjectileMovementComponent* ProjectileMovementComponent;
public:
UPROPERTY(VisibleDefaultsOnly, Category = Projectile)
UStaticMeshComponent* ProjectileMeshComponent;
UPROPERTY(VisibleDefaultsOnly, Category = Projectile)
UMaterialInstanceDynamic* ProjectileMat;
UFUNCTION()
void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp,FVector Impulse, const FHitResult& Hit);
UMeshComponent* GetCollisionComp() const { return MeshComp; }
UProjectileMovementComponent* GetMovementComp() const { return ProjectileMovem; }
UFUNCTION()
void OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
void FireInDir(const FVector& ShootDir);
};