Compare commits
27 Commits
d20171032f
...
Bullet
| Author | SHA1 | Date | |
|---|---|---|---|
| 72e9caf2c1 | |||
| 0da3851dde | |||
|
|
469451e491 | ||
| 064d4cd576 | |||
|
|
c8f3f53a8f | ||
|
|
6305198eda | ||
|
|
9ddc2fdbed | ||
|
|
7a9a6d257a | ||
|
|
49685ed167 | ||
| fc97901cdc | |||
|
|
ed5475299e | ||
|
|
406bafff0a | ||
|
|
d2968f0d36 | ||
|
|
365727aa4c | ||
|
|
c7702b9f64 | ||
|
|
5624625eda | ||
| 600897b905 | |||
| 17c60a72e3 | |||
| a85c596e23 | |||
|
|
17c6475397 | ||
| 7e3424d0f6 | |||
| 987856ca09 | |||
|
|
f57f6b8832 | ||
|
|
8733dfd87f | ||
|
|
df25b61b8f | ||
|
|
c844a8a896 | ||
|
|
f65171d5c2 |
@@ -10,9 +10,9 @@ r.AllowStaticLighting=False
|
|||||||
|
|
||||||
r.GenerateMeshDistanceFields=True
|
r.GenerateMeshDistanceFields=True
|
||||||
|
|
||||||
r.DynamicGlobalIlluminationMethod=1
|
r.DynamicGlobalIlluminationMethod=0
|
||||||
|
|
||||||
r.ReflectionMethod=1
|
r.ReflectionMethod=0
|
||||||
|
|
||||||
r.SkinCache.CompileShaders=True
|
r.SkinCache.CompileShaders=True
|
||||||
|
|
||||||
@@ -27,6 +27,12 @@ r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True
|
|||||||
r.DefaultFeature.LocalExposure.HighlightContrastScale=0.8
|
r.DefaultFeature.LocalExposure.HighlightContrastScale=0.8
|
||||||
|
|
||||||
r.DefaultFeature.LocalExposure.ShadowContrastScale=0.8
|
r.DefaultFeature.LocalExposure.ShadowContrastScale=0.8
|
||||||
|
r.Lumen.HardwareRayTracing=False
|
||||||
|
r.Lumen.Reflections.HardwareRayTracing.Translucent.Refraction.EnableForProject=False
|
||||||
|
r.Mobile.SupportsGen4TAA=False
|
||||||
|
r.CustomDepthTemporalAAJitter=False
|
||||||
|
r.AntiAliasingMethod=1
|
||||||
|
r.DefaultFeature.MotionBlur=False
|
||||||
|
|
||||||
[/Script/WindowsTargetPlatform.WindowsTargetSettings]
|
[/Script/WindowsTargetPlatform.WindowsTargetSettings]
|
||||||
DefaultGraphicsRHI=DefaultGraphicsRHI_DX12
|
DefaultGraphicsRHI=DefaultGraphicsRHI_DX12
|
||||||
@@ -94,3 +100,65 @@ ConnectionType=USBOnly
|
|||||||
bUseManualIPAddress=False
|
bUseManualIPAddress=False
|
||||||
ManualIPAddress=
|
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.
BIN
Content/CTP/03_Input/IA_Shoot.uasset
Normal file
BIN
Content/CTP/03_Input/IA_Shoot.uasset
Normal file
Binary file not shown.
Binary file not shown.
BIN
Content/CTP/04_Mesh/SM_Projectile.uasset
Normal file
BIN
Content/CTP/04_Mesh/SM_Projectile.uasset
Normal file
Binary file not shown.
BIN
Content/CTP/05_Material/MI_Body.uasset
Normal file
BIN
Content/CTP/05_Material/MI_Body.uasset
Normal file
Binary file not shown.
BIN
Content/CTP/05_Material/MI_Head.uasset
Normal file
BIN
Content/CTP/05_Material/MI_Head.uasset
Normal file
Binary file not shown.
Binary file not shown.
@@ -10,21 +10,42 @@ AM4_CentipedeBody::AM4_CentipedeBody()
|
|||||||
GetStaticMeshComponent()->SetStaticMesh(MeshRef.Object);
|
GetStaticMeshComponent()->SetStaticMesh(MeshRef.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ConstructorHelpers::FObjectFinder<UMaterialInterface> HeadMatRef(TEXT("/Game/CTP/05_Material/MI_Head.MI_Head"));
|
||||||
|
if (HeadMatRef.Succeeded())
|
||||||
|
{
|
||||||
|
HeadMaterial = HeadMatRef.Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConstructorHelpers::FObjectFinder<UMaterialInterface> BodyMatRef(TEXT("/Game/CTP/05_Material/MI_Body.MI_Body"));
|
||||||
|
if (BodyMatRef.Succeeded())
|
||||||
|
{
|
||||||
|
BodyMaterial = BodyMatRef.Object;
|
||||||
|
}
|
||||||
|
|
||||||
GetStaticMeshComponent()->SetRelativeScale3D(FVector(1.f, 0.4f, 0.4f));
|
GetStaticMeshComponent()->SetRelativeScale3D(FVector(1.f, 0.4f, 0.4f));
|
||||||
GetStaticMeshComponent()->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
|
||||||
GetStaticMeshComponent()->SetGenerateOverlapEvents(true);
|
|
||||||
GetStaticMeshComponent()->SetMobility(EComponentMobility::Movable);
|
GetStaticMeshComponent()->SetMobility(EComponentMobility::Movable);
|
||||||
|
GetStaticMeshComponent()->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);
|
||||||
|
GetStaticMeshComponent()->SetGenerateOverlapEvents(true);
|
||||||
|
GetStaticMeshComponent()->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
||||||
|
GetStaticMeshComponent()->SetCollisionProfileName(TEXT("OverlapAll"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AM4_CentipedeBody::SetAsHead(bool bHead)
|
void AM4_CentipedeBody::SetAsHead(bool bHead)
|
||||||
{
|
{
|
||||||
bIsHead = bHead;
|
bIsHead = bHead;
|
||||||
if (bIsHead)
|
|
||||||
{
|
if (bIsHead)
|
||||||
GetStaticMeshComponent()->SetDefaultCustomPrimitiveDataVector4(0, FVector4(1.0, 0.0, 0.0, 1.0));
|
{
|
||||||
}
|
if (HeadMaterial)
|
||||||
else
|
{
|
||||||
{
|
GetStaticMeshComponent()->SetMaterial(0, HeadMaterial);
|
||||||
GetStaticMeshComponent()->SetDefaultCustomPrimitiveDataVector4(0, FVector4(0.0, 1.0, 0.0, 1.0));
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
if (BodyMaterial)
|
||||||
|
{
|
||||||
|
GetStaticMeshComponent()->SetMaterial(0, BodyMaterial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,40 +1,110 @@
|
|||||||
#include "M4_CentipedeController.h"
|
#include "M4_CentipedeController.h"
|
||||||
|
#include "M4_LOG.h"
|
||||||
#include "M4_Gamemode.h"
|
#include "M4_Gamemode.h"
|
||||||
|
#include "M4_Mushroom.h"
|
||||||
|
#include "Kismet/GameplayStatics.h"
|
||||||
|
|
||||||
AM4_CentipedeController::AM4_CentipedeController()
|
UM4_CentipedeController::UM4_CentipedeController()
|
||||||
{
|
{
|
||||||
PrimaryActorTick.bCanEverTick = true;
|
SegmentRemainingCount = BodyCount;
|
||||||
Root = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
|
|
||||||
RootComponent = Root;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AM4_CentipedeController::BeginPlay()
|
void UM4_CentipedeController::Initialize(FSubsystemCollectionBase& Collection)
|
||||||
{
|
{
|
||||||
Super::BeginPlay();
|
Super::Initialize(Collection);
|
||||||
SpawnCentipede();
|
|
||||||
|
|
||||||
PreviousPositions.SetNum(BodyCount);
|
UE_LOG(M4_CPP, Warning, TEXT("Centipede Controller Initialized"));
|
||||||
for (int i = 0; i < BodyCount; ++i)
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void UM4_CentipedeController::Deinitialize()
|
||||||
|
{
|
||||||
|
UE_LOG(M4_CPP, Warning, TEXT("Centipede Controller Deinitialized"));
|
||||||
|
|
||||||
|
BodySegments.Empty();
|
||||||
|
PreviousPositions.Empty();
|
||||||
|
SegmentDirections.Empty();
|
||||||
|
|
||||||
|
Super::Deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UM4_CentipedeController::StartCentipede(FVector SpawnLocation)
|
||||||
|
{
|
||||||
|
if (BodySegments.Num() > 0)
|
||||||
{
|
{
|
||||||
PreviousPositions[i] = BodySegments[i]->GetActorLocation();
|
UE_LOG(M4_CPP, Warning, TEXT("Centipede already spawned"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32 i = 0; i < BodyCount; ++i)
|
||||||
|
{
|
||||||
|
FVector SegmentLocation = SpawnLocation - FVector(0.f, i * CellSize, 0.f);
|
||||||
|
|
||||||
|
AM4_CentipedeBody* Body = GetWorld()->SpawnActor<AM4_CentipedeBody>(
|
||||||
|
AM4_CentipedeBody::StaticClass(),
|
||||||
|
SegmentLocation,
|
||||||
|
FRotator::ZeroRotator
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Body)
|
||||||
|
{
|
||||||
|
BodySegments.Add(Body);
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
Body->PreviousBody = BodySegments[i - 1];
|
||||||
|
BodySegments[i - 1]->NextBody = Body;
|
||||||
|
}
|
||||||
|
|
||||||
|
Body->SetAsHead(i == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SegmentHistory.SetNum(BodyCount);
|
||||||
|
for (int32 i = 0; i < BodyCount; ++i)
|
||||||
|
{
|
||||||
|
if (BodySegments.IsValidIndex(i) && BodySegments[i])
|
||||||
|
{
|
||||||
|
FVector InitialPos = BodySegments[i]->GetActorLocation();
|
||||||
|
|
||||||
|
int32 InitialHistorySize = SegmentSpacing * (i + 1) + MaxHistorySize;
|
||||||
|
for (int32 j = 0; j < InitialHistorySize; ++j)
|
||||||
|
{
|
||||||
|
SegmentHistory[i].Add(InitialPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (AM4_CentipedeBody* Segment : BodySegments)
|
for (AM4_CentipedeBody* Segment : BodySegments)
|
||||||
{
|
{
|
||||||
SegmentDirections.Add(Segment, FVector2D(0.f, 1.f));
|
SegmentDirections.Add(Segment, FVector2D(0.f, 1.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UE_LOG(M4_CPP, Warning, TEXT("Centipede spawned with %d segments"), BodySegments.Num());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AM4_CentipedeController::SpawnCentipede()
|
TStatId UM4_CentipedeController::GetStatId() const
|
||||||
{
|
{
|
||||||
FVector SpawnLocation = GetActorLocation();
|
RETURN_QUICK_DECLARE_CYCLE_STAT(UM4_CentipedeController, STATGROUP_Tickables);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UM4_CentipedeController::SpawnCentipede()
|
||||||
|
{
|
||||||
|
GM_REF_PTR = Cast<AM4_Gamemode>(GetWorld()->GetAuthGameMode());
|
||||||
|
if (!GM_REF_PTR) return;
|
||||||
|
|
||||||
UE_LOG(LogTemp, Warning, TEXT("Controller spawn location: X=%.2f, Y=%.2f, Z=%.2f"),
|
FVector SpawnLocation = FVector(
|
||||||
|
GM_REF_PTR->MushroomSpawnBounds.Max.X,
|
||||||
|
0.f,
|
||||||
|
0.f
|
||||||
|
);
|
||||||
|
|
||||||
|
UE_LOG(M4_CPP, Warning, TEXT("Controller spawn location: X=%.2f, Y=%.2f, Z=%.2f"),
|
||||||
SpawnLocation.X, SpawnLocation.Y, SpawnLocation.Z);
|
SpawnLocation.X, SpawnLocation.Y, SpawnLocation.Z);
|
||||||
|
|
||||||
if (SpawnLocation.IsZero())
|
if (SpawnLocation.IsZero())
|
||||||
{
|
{
|
||||||
UE_LOG(LogTemp, Error, TEXT("Controller position is zero! Check spawn parameters."));
|
UE_LOG(M4_CPP, Error, TEXT("Controller position is zero! Check spawn parameters."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,104 +133,134 @@ void AM4_CentipedeController::SpawnCentipede()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AM4_CentipedeController::Tick(float DeltaTime)
|
void UM4_CentipedeController::Tick(float DeltaTime)
|
||||||
{
|
{
|
||||||
Super::Tick(DeltaTime);
|
Super::Tick(DeltaTime);
|
||||||
|
|
||||||
if (BodySegments.Num() == 0) return;
|
if (BodySegments.Num() == 0) return;
|
||||||
|
|
||||||
TimeSinceLastMove += DeltaTime;
|
AM4_CentipedeBody* Head = BodySegments[0];
|
||||||
|
if (Head && Head->bIsHead)
|
||||||
if (TimeSinceLastMove >= MoveInterval)
|
|
||||||
{
|
{
|
||||||
TimeSinceLastMove = 0.f;
|
FVector CurrentPos = Head->GetActorLocation();
|
||||||
|
FVector2D SegmentDirection = GetSegmentDirection(Head);
|
||||||
TArray<FVector> TempPositions;
|
|
||||||
TempPositions.SetNum(BodySegments.Num());
|
|
||||||
|
|
||||||
for (int32 i = 0; i < BodySegments.Num(); ++i)
|
|
||||||
{
|
|
||||||
TempPositions[i] = BodySegments[i]->GetActorLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32 i = 0; i < BodySegments.Num(); ++i)
|
|
||||||
{
|
|
||||||
AM4_CentipedeBody* Segment = BodySegments[i];
|
|
||||||
|
|
||||||
if (!Segment) continue;
|
|
||||||
|
|
||||||
if (Segment->bIsHead)
|
|
||||||
{
|
|
||||||
FVector CurrentPos = Segment->GetActorLocation();
|
|
||||||
FVector2D SegmentDirection = GetSegmentDirection(Segment);
|
|
||||||
|
|
||||||
bool bShouldDescend = CheckCollision(Segment, SegmentDirection);
|
|
||||||
|
|
||||||
if (bShouldDescend)
|
|
||||||
{
|
|
||||||
FVector NewPos = CurrentPos - FVector(0.f, 0.f, CellSize);
|
|
||||||
Segment->SetActorLocation(NewPos);
|
|
||||||
|
|
||||||
SegmentDirection.Y *= -1.f;
|
|
||||||
SetSegmentDirection(Segment, SegmentDirection);
|
|
||||||
|
|
||||||
UE_LOG(LogTemp, Warning, TEXT("Head at index %d descending"), i);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FVector NewPos = CurrentPos + FVector(0.f, SegmentDirection.Y * CellSize, 0.f);
|
|
||||||
Segment->SetActorLocation(NewPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
{
|
|
||||||
Segment->SetActorLocation(PreviousPositions[i - 1]);
|
|
||||||
|
|
||||||
if (BodySegments[i - 1])
|
|
||||||
{
|
|
||||||
FVector2D PrevDirection = GetSegmentDirection(BodySegments[i - 1]);
|
|
||||||
SetSegmentDirection(Segment, PrevDirection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32 i = 0; i < BodySegments.Num(); ++i)
|
|
||||||
{
|
|
||||||
PreviousPositions[i] = BodySegments[i]->GetActorLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateHeadStatus();
|
bool bRowChanged = CheckCollision(Head, SegmentDirection);
|
||||||
|
|
||||||
|
if (bRowChanged)
|
||||||
|
{
|
||||||
|
FVector NewPos = CurrentPos - FVector(0.f, 0.f, CellSize);
|
||||||
|
Head->SetActorLocation(NewPos);
|
||||||
|
|
||||||
|
SegmentDirection.Y *= -1.f;
|
||||||
|
SetSegmentDirection(Head, SegmentDirection);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FVector NewPos = CurrentPos + FVector(0.f, SegmentDirection.Y * CentipedeSpeed * DeltaTime, 0.f);
|
||||||
|
Head->SetActorLocation(NewPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
SegmentHistory[0].Add(Head->GetActorLocation());
|
||||||
|
if (SegmentHistory[0].Num() > MaxHistorySize)
|
||||||
|
{
|
||||||
|
SegmentHistory[0].RemoveAt(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int32 i = 1; i < BodySegments.Num(); ++i)
|
||||||
|
{
|
||||||
|
AM4_CentipedeBody* Segment = BodySegments[i];
|
||||||
|
if (!Segment) continue;
|
||||||
|
|
||||||
|
int32 PrevIndex = i - 1;
|
||||||
|
int32 HistoryLookback = SegmentSpacing;
|
||||||
|
|
||||||
|
if (SegmentHistory[PrevIndex].Num() > HistoryLookback)
|
||||||
|
{
|
||||||
|
int32 HistoryIndex = SegmentHistory[PrevIndex].Num() - HistoryLookback - 1;
|
||||||
|
FVector TargetPos = SegmentHistory[PrevIndex][HistoryIndex];
|
||||||
|
|
||||||
|
Segment->SetActorLocation(TargetPos);
|
||||||
|
|
||||||
|
SegmentHistory[i].Add(Segment->GetActorLocation());
|
||||||
|
if (SegmentHistory[i].Num() > MaxHistorySize)
|
||||||
|
{
|
||||||
|
SegmentHistory[i].RemoveAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateHeadStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AM4_CentipedeController::CheckCollision(AM4_CentipedeBody* Segment, FVector2D Direction)
|
bool UM4_CentipedeController::CheckCollision(AM4_CentipedeBody* Segment, FVector2D Direction)
|
||||||
{
|
{
|
||||||
if (!Segment) return false;
|
if (!Segment) return false;
|
||||||
|
|
||||||
FVector CurrentPos = Segment->GetActorLocation();
|
FVector CurrentPos = Segment->GetActorLocation();
|
||||||
FVector NextPos = CurrentPos + FVector(0.f, Direction.Y * CellSize, 0.f);
|
FVector NextPos = CurrentPos + FVector(0.f, Direction.Y * CellSize, 0.f);
|
||||||
|
|
||||||
AM4_Gamemode* GM = Cast<AM4_Gamemode>(GetWorld()->GetAuthGameMode());
|
if (!GM_REF_PTR)
|
||||||
if (!GM) return false;
|
{
|
||||||
|
GM_REF_PTR = Cast<AM4_Gamemode>(GetWorld()->GetAuthGameMode());
|
||||||
|
if (!GM_REF_PTR) return false;
|
||||||
|
}
|
||||||
|
|
||||||
const float LeftBound = GM->MushroomSpawnBounds.Min.Y;
|
const float LeftBound = GM_REF_PTR->MushroomSpawnBounds.Min.Y;
|
||||||
const float RightBound = GM->MushroomSpawnBounds.Max.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)
|
if (NextPos.Y <= LeftBound || NextPos.Y >= RightBound)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CurrentPos.Z > MinRows && NextPos.Z <= MinRows)
|
||||||
|
{
|
||||||
|
// On inverse la direction de descente pour remonter
|
||||||
|
FVector2D CurrentDirection = GetSegmentDirection(Segment);
|
||||||
|
CurrentDirection.Y *= -1.f;
|
||||||
|
SetSegmentDirection(Segment, CurrentDirection);
|
||||||
|
return true; // Collision détectée, le centipede descendra à la prochaine itération
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Ajouter vérification collision avec mushroom
|
// Vérification si on atteint la limite haute
|
||||||
// if (IsMushroomAt(NextPos)) return true;
|
if (CurrentPos.Z < MaxRows && NextPos.Z >= MaxRows)
|
||||||
|
{
|
||||||
|
// On inverse la direction de montée pour descendre
|
||||||
|
FVector2D CurrentDirection = GetSegmentDirection(Segment);
|
||||||
|
CurrentDirection.Y *= -1.f;
|
||||||
|
SetSegmentDirection(Segment, CurrentDirection);
|
||||||
|
return true; // Collision détectée, le centipede remontera à la prochaine itération
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 NextGridZ = FMath::RoundToInt(NextPos.Z / CellSize);
|
||||||
|
int32 NextGridY = FMath::RoundToInt(NextPos.Y / CellSize);
|
||||||
|
|
||||||
|
TArray<AActor*> FoundMushrooms;
|
||||||
|
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AM4_Mushroom::StaticClass(), FoundMushrooms);
|
||||||
|
|
||||||
|
for (AActor* Actor : FoundMushrooms)
|
||||||
|
{
|
||||||
|
FVector MushroomPos = Actor->GetActorLocation();
|
||||||
|
|
||||||
|
// Conversion de la position du mushroom en coordonnées de grille (Z, Y)
|
||||||
|
int32 MushroomGridZ = FMath::RoundToInt(MushroomPos.Z / CellSize);
|
||||||
|
int32 MushroomGridY = FMath::RoundToInt(MushroomPos.Y / CellSize);
|
||||||
|
|
||||||
|
// Vérification si c'est la même cellule de grille
|
||||||
|
if (NextGridZ == MushroomGridZ && NextGridY == MushroomGridY)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FVector2D AM4_CentipedeController::GetSegmentDirection(AM4_CentipedeBody* Segment)
|
FVector2D UM4_CentipedeController::GetSegmentDirection(AM4_CentipedeBody* Segment)
|
||||||
{
|
{
|
||||||
if (SegmentDirections.Contains(Segment))
|
if (SegmentDirections.Contains(Segment))
|
||||||
{
|
{
|
||||||
@@ -169,7 +269,7 @@ FVector2D AM4_CentipedeController::GetSegmentDirection(AM4_CentipedeBody* Segmen
|
|||||||
return FVector2D(0.f, 1.f);
|
return FVector2D(0.f, 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AM4_CentipedeController::SetSegmentDirection(AM4_CentipedeBody* Segment, FVector2D Direction)
|
void UM4_CentipedeController::SetSegmentDirection(AM4_CentipedeBody* Segment, FVector2D Direction)
|
||||||
{
|
{
|
||||||
if (Segment)
|
if (Segment)
|
||||||
{
|
{
|
||||||
@@ -177,7 +277,7 @@ void AM4_CentipedeController::SetSegmentDirection(AM4_CentipedeBody* Segment, FV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AM4_CentipedeController::UpdateHeadStatus()
|
void UM4_CentipedeController::UpdateHeadStatus()
|
||||||
{
|
{
|
||||||
for (int32 i = 0; i < BodySegments.Num(); ++i)
|
for (int32 i = 0; i < BodySegments.Num(); ++i)
|
||||||
{
|
{
|
||||||
@@ -193,37 +293,55 @@ void AM4_CentipedeController::UpdateHeadStatus()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AM4_CentipedeController::OnSegmentDestroyed(AM4_CentipedeBody* DestroyedSegment)
|
void UM4_CentipedeController::OnSegmentHit(AM4_CentipedeBody* DestroyedSegment)
|
||||||
{
|
{
|
||||||
if (!DestroyedSegment) return;
|
if (!DestroyedSegment) return;
|
||||||
|
|
||||||
int32 SegmentIndex = BodySegments.Find(DestroyedSegment);
|
int32 SegmentIndex = BodySegments.Find(DestroyedSegment);
|
||||||
|
|
||||||
if (SegmentIndex == INDEX_NONE) return;
|
if (SegmentIndex == INDEX_NONE) return;
|
||||||
|
|
||||||
UE_LOG(LogTemp, Warning, TEXT("Segment %d destroyed"), SegmentIndex);
|
|
||||||
|
|
||||||
if (SegmentIndex + 1 < BodySegments.Num())
|
if (SegmentIndex + 1 < BodySegments.Num())
|
||||||
{
|
{
|
||||||
AM4_CentipedeBody* NewHead = BodySegments[SegmentIndex + 1];
|
AM4_CentipedeBody* NewHead = BodySegments[SegmentIndex + 1];
|
||||||
if (NewHead)
|
if (NewHead)
|
||||||
{
|
{
|
||||||
NewHead->SetAsHead(true);
|
NewHead->SetAsHead(true);
|
||||||
NewHead->PreviousBody = nullptr;
|
NewHead->PreviousBody = nullptr;
|
||||||
|
|
||||||
UE_LOG(LogTemp, Warning, TEXT("New head created at index %d"), SegmentIndex + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SegmentIndex > 0 && BodySegments[SegmentIndex - 1])
|
if (SegmentIndex > 0 && BodySegments[SegmentIndex - 1])
|
||||||
{
|
{
|
||||||
BodySegments[SegmentIndex - 1]->NextBody = nullptr;
|
BodySegments[SegmentIndex - 1]->NextBody = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BodySegments.RemoveAt(SegmentIndex);
|
|
||||||
PreviousPositions.RemoveAt(SegmentIndex);
|
|
||||||
SegmentDirections.Remove(DestroyedSegment);
|
|
||||||
|
|
||||||
// TODO: Spawner un mushroom à la position du segment détruit
|
// disable collision and hide the destroyed segment
|
||||||
// SpawnMushroomAt(DestroyedSegment->GetActorLocation());
|
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -85,8 +85,7 @@ void AM4_Gamemode::BeginPlay()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn centipede controller
|
|
||||||
PRINT_SCREEN(TEXT("Spawning Centipede Controller"), FColor::Green);
|
PRINT_SCREEN(TEXT("Spawning Centipede Controller"), FColor::Green);
|
||||||
|
|
||||||
FVector CentipedeSpawnLocation = FVector(
|
FVector CentipedeSpawnLocation = FVector(
|
||||||
@@ -98,16 +97,13 @@ void AM4_Gamemode::BeginPlay()
|
|||||||
// PRINT SCREEN Max.X value
|
// PRINT SCREEN Max.X value
|
||||||
PRINT_SCREEN(*FString::Printf(TEXT("Mushroom Spawn Bounds Max.X: %.2f"), MushroomSpawnBounds.Max.X), FColor::Green);
|
PRINT_SCREEN(*FString::Printf(TEXT("Mushroom Spawn Bounds Max.X: %.2f"), MushroomSpawnBounds.Max.X), FColor::Green);
|
||||||
|
|
||||||
CentipedeController = GetWorld()->SpawnActor<AM4_CentipedeController>(
|
UM4_CentipedeController* Controller = GetWorld()->GetSubsystem<UM4_CentipedeController>();
|
||||||
AM4_CentipedeController::StaticClass(),
|
if (Controller)
|
||||||
CentipedeSpawnLocation,
|
|
||||||
FRotator::ZeroRotator
|
|
||||||
);
|
|
||||||
|
|
||||||
if (CentipedeController)
|
|
||||||
{
|
{
|
||||||
CentipedeController->BodyCount = CentipedeBodyCount;
|
Controller->BodyCount = CentipedeBodyCount;
|
||||||
CentipedeController->CellSize = CellSize;
|
Controller->CellSize = CellSize;
|
||||||
|
|
||||||
|
Controller->StartCentipede(CentipedeSpawnLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "M4_CTP_Macros.h"
|
#include "M4_CTP_Macros.h"
|
||||||
#include "Kismet/GameplayStatics.h"
|
#include "Kismet/GameplayStatics.h"
|
||||||
#include "M4_Gamemode.h"
|
#include "M4_Gamemode.h"
|
||||||
|
#include "M4_Projectile.h"
|
||||||
|
|
||||||
|
|
||||||
// Sets default values
|
// Sets default values
|
||||||
@@ -31,13 +32,29 @@ AM4_Mushroom::AM4_Mushroom()
|
|||||||
const FVector2D MushroomScale = FVector2D(0.3f, 0.25f);
|
const FVector2D MushroomScale = FVector2D(0.3f, 0.25f);
|
||||||
GetStaticMeshComponent()->SetRelativeScale3D(FVector(1.f, 0.45f, 0.20f));
|
GetStaticMeshComponent()->SetRelativeScale3D(FVector(1.f, 0.45f, 0.20f));
|
||||||
|
|
||||||
// Custom preset for more advanced collision configuration
|
// Set collision profile to block all
|
||||||
GetStaticMeshComponent()->SetCollisionProfileName(UCollisionProfile::CustomCollisionProfileName);
|
GetStaticMeshComponent()->SetCollisionProfileName(TEXT("OverlapAll"));
|
||||||
GetStaticMeshComponent()->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AM4_Mushroom::BeginPlay()
|
void AM4_Mushroom::BeginPlay()
|
||||||
{
|
{
|
||||||
|
MushLife = 2;
|
||||||
|
DestructionHit = 0;
|
||||||
Super::BeginPlay();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
#include "M4_PlayerPawn.h"
|
#include "M4_PlayerPawn.h"
|
||||||
#include "EnhancedInputComponent.h"
|
#include "EnhancedInputComponent.h"
|
||||||
#include "M4_Gamemode.h"
|
#include "M4_Gamemode.h"
|
||||||
|
#include "M4_LOG.h"
|
||||||
|
#include "M4_Projectile.h"
|
||||||
#include "GameFramework/PlayerController.h"
|
#include "GameFramework/PlayerController.h"
|
||||||
#include "Camera/CameraComponent.h"
|
|
||||||
|
|
||||||
AM4_PlayerPawn::AM4_PlayerPawn()
|
AM4_PlayerPawn::AM4_PlayerPawn()
|
||||||
{
|
{
|
||||||
@@ -16,10 +17,16 @@ AM4_PlayerPawn::AM4_PlayerPawn()
|
|||||||
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
|
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
|
||||||
MeshComponent->SetupAttachment(RootComponent);
|
MeshComponent->SetupAttachment(RootComponent);
|
||||||
MeshComponent->SetMobility(EComponentMobility::Movable);
|
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"));
|
static ConstructorHelpers::FObjectFinder<UStaticMesh> DefaultMeshRef(TEXT("/Game/CTP/04_Mesh/SM_Cube.SM_Cube"));
|
||||||
if (DefaultMeshRef.Succeeded())
|
if (DefaultMeshRef.Succeeded())
|
||||||
@@ -32,12 +39,18 @@ AM4_PlayerPawn::AM4_PlayerPawn()
|
|||||||
{
|
{
|
||||||
MoveAction = MoveActionRef.Object;
|
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()
|
void AM4_PlayerPawn::BeginPlay()
|
||||||
{
|
{
|
||||||
Super::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)
|
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);
|
NewLocation.Y = FMath::Clamp(NewLocation.Y, GM->Bounds.Min.Y, GM->Bounds.Max.Y);
|
||||||
SetActorLocation(NewLocation);
|
SetActorLocation(NewLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AM4_PlayerPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
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);
|
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)
|
void AM4_PlayerPawn::Move(const FInputActionInstance& Instance)
|
||||||
{
|
{
|
||||||
LastMoveValue = Instance.GetValue().Get<FVector2D>().GetSafeNormal();
|
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."));
|
||||||
}
|
}
|
||||||
108
Source/M4_CPP/private/M4_Projectile.cpp
Normal file
108
Source/M4_CPP/private/M4_Projectile.cpp
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
#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()
|
||||||
|
{
|
||||||
|
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::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
InitialLoc = GetActorLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -22,4 +22,10 @@ public:
|
|||||||
bool bIsHead = false;
|
bool bIsHead = false;
|
||||||
|
|
||||||
void SetAsHead(bool bHead);
|
void SetAsHead(bool bHead);
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Materials")
|
||||||
|
UMaterialInterface* HeadMaterial;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Materials")
|
||||||
|
UMaterialInterface* BodyMaterial;
|
||||||
};
|
};
|
||||||
@@ -1,50 +1,65 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "GameFramework/Actor.h"
|
|
||||||
#include "M4_CentipedeBody.h"
|
#include "M4_CentipedeBody.h"
|
||||||
|
#include "Subsystems/WorldSubsystem.h"
|
||||||
#include "M4_CentipedeController.generated.h"
|
#include "M4_CentipedeController.generated.h"
|
||||||
|
|
||||||
UCLASS()
|
UCLASS()
|
||||||
class M4_CPP_API AM4_CentipedeController : public AActor
|
class M4_CPP_API UM4_CentipedeController : public UTickableWorldSubsystem
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AM4_CentipedeController();
|
UM4_CentipedeController();
|
||||||
|
|
||||||
|
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||||
|
virtual void Deinitialize() override;
|
||||||
|
void StartCentipede(FVector SpawnLocation);
|
||||||
|
|
||||||
virtual void BeginPlay() override;
|
|
||||||
virtual void Tick(float DeltaTime) override;
|
virtual void Tick(float DeltaTime) override;
|
||||||
|
|
||||||
|
virtual TStatId GetStatId() const override;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Centipede")
|
||||||
int32 BodyCount = 10;
|
int32 BodyCount = 10;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Centipede")
|
||||||
float CellSize = 50.f;
|
float CellSize = 50.f;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Centipede")
|
||||||
float MoveInterval = 0.1f;
|
float MoveInterval = 0.1f;
|
||||||
|
|
||||||
void OnSegmentDestroyed(AM4_CentipedeBody* DestroyedSegment);
|
UFUNCTION(BlueprintCallable, Category = "Centipede")
|
||||||
|
void OnSegmentHit(AM4_CentipedeBody* DestroyedSegment);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
TArray<AM4_CentipedeBody*> BodySegments;
|
TArray<AM4_CentipedeBody*> BodySegments;
|
||||||
|
TArray<TArray<FVector>> SegmentHistory; // Historique pour chaque segment
|
||||||
UPROPERTY()
|
int32 MaxHistorySize = 200;
|
||||||
USceneComponent* Root;
|
int8 SegmentRemainingCount = 0;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, Category = "Centipede")
|
||||||
|
int32 SegmentSpacing = 15; // Distance en nombre de frames entre segments
|
||||||
|
|
||||||
float TimeSinceLastMove = 0.f;
|
float TimeSinceLastMove = 0.f;
|
||||||
|
float CentipedeSpeed = 400.f;
|
||||||
|
bool bFirstTick = true;
|
||||||
|
|
||||||
TArray<FVector> PreviousPositions;
|
TArray<FVector> PreviousPositions;
|
||||||
|
|
||||||
TMap<AM4_CentipedeBody*, FVector2D> SegmentDirections;
|
TMap<AM4_CentipedeBody*, FVector2D> SegmentDirections;
|
||||||
|
|
||||||
void SpawnCentipede();
|
void SpawnCentipede();
|
||||||
void UpdateHeadStatus();
|
void UpdateHeadStatus();
|
||||||
|
void SpawnMushroomsAtSegmentDeathPos(FVector Location);
|
||||||
|
|
||||||
bool CheckCollision(AM4_CentipedeBody* Segment, FVector2D Direction);
|
bool CheckCollision(AM4_CentipedeBody* Segment, FVector2D Direction);
|
||||||
|
|
||||||
FVector2D GetSegmentDirection(AM4_CentipedeBody* Segment);
|
FVector2D GetSegmentDirection(AM4_CentipedeBody* Segment);
|
||||||
void SetSegmentDirection(AM4_CentipedeBody* Segment, FVector2D Direction);
|
void SetSegmentDirection(AM4_CentipedeBody* Segment, FVector2D Direction);
|
||||||
};
|
|
||||||
|
UPROPERTY()
|
||||||
|
class AM4_Gamemode* GM_REF_PTR;
|
||||||
|
};
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ private:
|
|||||||
int32 CentipedeBodyCount = 10;
|
int32 CentipedeBodyCount = 10;
|
||||||
|
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
TObjectPtr<AM4_CentipedeController> CentipedeController;
|
TObjectPtr<UM4_CentipedeController> CentipedeController;
|
||||||
|
|
||||||
int Score = 0;
|
int Score = 0;
|
||||||
int Lives = 3;
|
int Lives = 3;
|
||||||
|
|||||||
@@ -13,9 +13,14 @@ class M4_CPP_API AM4_Mushroom : public AStaticMeshActor
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Sets default values for this pawn's properties
|
|
||||||
AM4_Mushroom();
|
AM4_Mushroom();
|
||||||
|
|
||||||
|
int MushLife;
|
||||||
|
int DestructionHit = 0;
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void OnHit(UPrimitiveComponent* HitComp,AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse,const FHitResult& Hit);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void BeginPlay() override;
|
virtual void BeginPlay() override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "M4_Projectile.h"
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "GameFramework/Pawn.h"
|
#include "GameFramework/Pawn.h"
|
||||||
#include "InputAction.h"
|
#include "InputAction.h"
|
||||||
@@ -11,6 +12,7 @@ UCLASS()
|
|||||||
class AM4_PlayerPawn : public APawn
|
class AM4_PlayerPawn : public APawn
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AM4_PlayerPawn();
|
AM4_PlayerPawn();
|
||||||
|
|
||||||
@@ -18,6 +20,19 @@ public:
|
|||||||
virtual void Tick(float DeltaTime) override;
|
virtual void Tick(float DeltaTime) override;
|
||||||
virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
|
virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
|
||||||
void Move(const FInputActionInstance& Instance);
|
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:
|
protected:
|
||||||
|
|
||||||
@@ -27,7 +42,19 @@ protected:
|
|||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
UInputAction* MoveAction;
|
UInputAction* MoveAction;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
UInputAction* ShootAction;
|
||||||
|
|
||||||
float MoveSpeed = 500.f;
|
float MoveSpeed = 500.f;
|
||||||
FVector2D MeshScale = FVector2D(0.6f, 0.5f);
|
FVector2D MeshScale = FVector2D(0.6f, 0.5f);
|
||||||
FVector2D LastMoveValue = FVector2D::ZeroVector;
|
FVector2D LastMoveValue = FVector2D::ZeroVector;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
bool bIsInvincible = false;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
float InvinciblityDuration = 2.0f;
|
||||||
|
|
||||||
|
FTimerHandle InvincibleTimerHandle;
|
||||||
|
void EndInvincibility();
|
||||||
};
|
};
|
||||||
44
Source/M4_CPP/public/M4_Projectile.h
Normal file
44
Source/M4_CPP/public/M4_Projectile.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#include "GameFramework/ProjectileMovementComponent.h"
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/Actor.h"
|
||||||
|
#include "M4_Projectile.generated.h"
|
||||||
|
|
||||||
|
class USphereComponent;
|
||||||
|
class UMeshComponent;
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class M4_CPP_API AM4_Projectile : public AActor
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
AM4_Projectile();
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleDefaultsOnly, Category = Projectile)
|
||||||
|
UStaticMeshComponent* ProjectileMeshComponent;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleDefaultsOnly, Category = Projectile)
|
||||||
|
UMaterialInstanceDynamic* ProjectileMat;
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
|
||||||
|
void FireInDir(const FVector& ShootDir);
|
||||||
|
};
|
||||||
|
|
||||||
Reference in New Issue
Block a user