20 Commits

Author SHA1 Message Date
5e7712f0ac Update README.md 2025-02-18 13:05:54 +05:30
939e851c37 Implement basic combat system 2025-02-17 23:24:04 +05:30
4b588e8667 Modify movement to feel more intuitive (align with direction faster) 2025-02-17 16:17:44 +05:30
b815c07878 Adjust ThrustDeacceleration for better control 2025-02-17 15:04:10 +05:30
df2a9520e4 Merge pull request 'Add first level implementation' (#1) from EnvironmentAssests into main
Reviewed-on: #1
2025-02-17 14:42:46 +05:30
efce317da1 Modified Asteriod Movements 2025-02-17 14:41:36 +05:30
7653d26934 revert 561a9de8dd
revert Remove old file
2025-02-17 00:26:56 +05:30
5ac7b648b9 Update README.md 2025-02-16 23:40:23 +05:30
561a9de8dd Remove old file 2025-02-16 23:09:56 +05:30
833edd7d8f Modify acceleration 2025-02-16 23:09:20 +05:30
b3bbca282d First complete implementation of 3d movement 2025-02-16 17:36:16 +05:30
482f386975 Basic mouse look implementation (only left/right) 2025-02-16 16:31:45 +05:30
49895ec6a6 Begin mouse control implementation 2025-02-16 15:16:22 +05:30
2519db2ced Implement better throttle system 2025-02-16 14:43:13 +05:30
6fb1b648ec Create blueprints for classes and add meshes and textures 2025-02-16 14:02:01 +05:30
32365c408c Create input actions and input mapping context 2025-02-15 22:16:14 +05:30
4ee95ea366 Create shooting game mode 2025-02-15 22:15:10 +05:30
536a938d55 Modify to use EnhancedInput 2025-02-15 21:32:16 +05:30
bb4d1bef59 Add basic class files 2025-02-15 21:30:02 +05:30
07ed6f8876 Add EnhancedInput module to build file 2025-02-15 21:28:36 +05:30
38 changed files with 958 additions and 16 deletions

View File

@@ -6,4 +6,5 @@ bUseDistanceScaledCameraSpeed=True
[ContentBrowser] [ContentBrowser]
ContentBrowserTab1.SourcesExpanded=True ContentBrowserTab1.SourcesExpanded=True
[/Script/AdvancedPreviewScene.SharedProfiles]

View File

@@ -64,7 +64,7 @@ bOffsetPlayerGamepadIds=False
GameInstanceClass=/Script/Engine.GameInstance GameInstanceClass=/Script/Engine.GameInstance
GameDefaultMap=/Engine/Maps/Templates/OpenWorld.OpenWorld GameDefaultMap=/Engine/Maps/Templates/OpenWorld.OpenWorld
ServerDefaultMap=/Engine/Maps/Entry.Entry ServerDefaultMap=/Engine/Maps/Entry.Entry
GlobalDefaultGameMode=/Game/StarterContent/Blueprints/Deathmatch.Deathmatch_C GlobalDefaultGameMode=/Game/Blueprints/BP_SpaceShooterGameMode.BP_SpaceShooterGameMode_C
GlobalDefaultServerGameMode=None GlobalDefaultServerGameMode=None
[/Script/UnrealEd.UnrealEdEngine] [/Script/UnrealEd.UnrealEdEngine]
@@ -148,3 +148,61 @@ ConnectionType=USBOnly
bUseManualIPAddress=False bUseManualIPAddress=False
ManualIPAddress= ManualIPAddress=
[/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. ")
+Profiles=(Name="Projectile",CollisionEnabled=QueryOnly,bCanModify=True,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Player",Response=ECR_Ignore)),HelpMessage="Needs description")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False,Name="Player")
-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.

Binary file not shown.

Binary file not shown.

BIN
Content/Environment.umap LFS Normal file

Binary file not shown.

Binary file not shown.

BIN
Content/Input/IA_Fire.uasset LFS Normal file

Binary file not shown.

Binary file not shown.

BIN
Content/Input/IA_MouseLook.uasset LFS Normal file

Binary file not shown.

BIN
Content/Input/IA_Movement.uasset LFS Normal file

Binary file not shown.

BIN
Content/Input/IA_Shoot.uasset LFS Normal file

Binary file not shown.

BIN
Content/Input/IA_Throttle.uasset LFS Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,4 @@
# Simulator Project # Simulator Game Project
## Overview ## Overview
A spaceship simulator game developed in Unreal Engine 5, focusing on realistic physics and comprehensive ship systems management. Players control a fully simulated spacecraft with integrated power, navigation, and damage systems. A spaceship simulator game developed in Unreal Engine 5, focusing on realistic physics and comprehensive ship systems management. Players control a fully simulated spacecraft with integrated power, navigation, and damage systems.
@@ -7,9 +7,8 @@ A spaceship simulator game developed in Unreal Engine 5, focusing on realistic p
- Realistic zero-gravity space flight physics - Realistic zero-gravity space flight physics
- Comprehensive power management system - Comprehensive power management system
- Dynamic damage and shield mechanics - Dynamic damage and shield mechanics
- Advanced navigation and autopilot capabilities
- Detailed ship systems simulation - Detailed ship systems simulation
- Interactive cockpit and HUD - Interactive HUD
## Prerequisites ## Prerequisites
- Unreal Engine 5.2 or higher - Unreal Engine 5.2 or higher
@@ -22,7 +21,7 @@ A spaceship simulator game developed in Unreal Engine 5, focusing on realistic p
### Installation ### Installation
1. Clone the repository: 1. Clone the repository:
```bash ```bash
git clone https://github.com/YourUsername/SpaceshipSimulator.git git clone https://git.cinis.cf/Ludusphere/Yamato.git
``` ```
2. Initialize and update Git LFS: 2. Initialize and update Git LFS:
@@ -38,13 +37,13 @@ git lfs pull
### Project Structure ### Project Structure
``` ```
├── Config/ # Engine configuration ├── Config/ # Engine configuration
├── Content/ ├── Content/
│ ├── Core/ # Base game systems │ ├── Core/ # Base game systems
│ ├── Ships/ # Ship-related assets │ ├── Ships/ # Ship-related assets
│ ├── Environment/ # Space environment │ ├── Environment/ # Space environment
│ ├── UI/ # HUD and menus │ ├── UI/ # HUD and menus
│ └── VFX/ # Visual effects │ └── VFX/ # Visual effects
├── Source/ # C++ source code ├── Source/ # C++ source code
└── Documentation/ # Additional documentation └── Documentation/ # Additional documentation
``` ```
@@ -95,11 +94,8 @@ git checkout -b feature/your-feature-name
5. Create a Pull Request 5. Create a Pull Request
## Project Team ## Project Team
- Person A: Core Systems Developer - Aiden Correya: Core Systems Developer
- Person B: Content and Design Developer - Shashank Kumar: Content and Design Developer
## License
- To be decided
## Acknowledgments ## Acknowledgments
- Unreal Engine - Epic Games (Unreal Engine)

View File

@@ -0,0 +1,78 @@
#include "EnemySpaceship.h"
#include "Kismet/GameplayStatics.h"
AEnemySpaceship::AEnemySpaceship()
{
PrimaryActorTick.bCanEverTick = true;
// Create and setup the enemy mesh
EnemyMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("EnemyMesh"));
RootComponent = EnemyMesh;
// Disable gravity and physics simulation
EnemyMesh->SetSimulatePhysics(false);
EnemyMesh->SetEnableGravity(false);
// Set up collision for the enemy mesh
EnemyMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
EnemyMesh->SetCollisionObjectType(ECC_Pawn);
EnemyMesh->SetCollisionResponseToAllChannels(ECR_Block);
EnemyMesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Ignore); // Ignore other pawns
EnemyMesh->SetCollisionResponseToChannel(ECC_GameTraceChannel1, ECR_Ignore); // Ignore player
EnemyMesh->SetGenerateOverlapEvents(true);
}
void AEnemySpaceship::BeginPlay()
{
Super::BeginPlay();
// Find the player pawn
PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
}
void AEnemySpaceship::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (PlayerPawn)
{
// Move towards the player
FVector Direction = (PlayerPawn->GetActorLocation() - GetActorLocation()).GetSafeNormal();
FVector NewLocation = GetActorLocation() + Direction * MovementSpeed * DeltaTime;
SetActorLocation(NewLocation);
// Face towards the player
FRotator NewRotation = Direction.Rotation();
SetActorRotation(NewRotation);
}
}
float AEnemySpaceship::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent,
AController* EventInstigator, AActor* DamageCauser)
{
float DamageToApply = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
CurrentHealth -= DamageToApply;
// Debug message
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Red,
FString::Printf(TEXT("Enemy Health: %f"), CurrentHealth));
}
if (CurrentHealth <= 0)
{
Die();
}
return DamageToApply;
}
void AEnemySpaceship::Die()
{
// Add any death effects here
// Destroy the enemy
Destroy();
}

View File

@@ -0,0 +1,40 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "EnemySpaceship.generated.h"
UCLASS()
class MYPROJECT3_API AEnemySpaceship : public AActor
{
GENERATED_BODY()
public:
AEnemySpaceship();
protected:
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
UStaticMeshComponent* EnemyMesh;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float MovementSpeed = 300.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Combat")
float MaxHealth = 100.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Combat")
float CurrentHealth = 100.0f;
public:
virtual void Tick(float DeltaTime) override;
// Override TakeDamage to handle damage taken
virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent,
class AController* EventInstigator, AActor* DamageCauser) override;
private:
AActor* PlayerPawn;
void Die();
};

View File

@@ -10,7 +10,7 @@ public class MyProject3 : ModuleRules
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
PrivateDependencyModuleNames.AddRange(new string[] { }); PrivateDependencyModuleNames.AddRange(new string[] { "EnhancedInput" });
// Uncomment if you are using Slate UI // Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

View File

@@ -0,0 +1,99 @@
#include "SpaceShooterGameMode.h"
#include "SpaceshipPawn.h"
#include "EnemySpaceship.h"
#include "Kismet/GameplayStatics.h"
ASpaceShooterGameMode::ASpaceShooterGameMode()
{
// Set default pawn class using the inherited DefaultPawnClass
static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/Blueprints/BP_SpaceshipPawn"));
if (PlayerPawnBPClass.Class != nullptr)
{
DefaultPawnClass = PlayerPawnBPClass.Class;
}
// Find enemy blueprint class
static ConstructorHelpers::FClassFinder<AEnemySpaceship> EnemyBPClass(TEXT("/Game/Blueprints/BP_EnemySpaceship"));
if (EnemyBPClass.Class != nullptr)
{
EnemyClass = EnemyBPClass.Class;
}
// Enable Tick()
PrimaryActorTick.bCanEverTick = true;
// Debug message
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("GameMode Constructor"));
}
}
void ASpaceShooterGameMode::StartPlay()
{
Super::StartPlay();
// Start spawning enemies
GetWorldTimerManager().SetTimer(EnemySpawnTimer, this, &ASpaceShooterGameMode::SpawnEnemy,
EnemySpawnInterval, true);
// Debug message
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("GameMode StartPlay"));
}
}
void ASpaceShooterGameMode::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ASpaceShooterGameMode::SpawnEnemy()
{
// Count current enemies
TArray<AActor*> FoundEnemies;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AEnemySpaceship::StaticClass(), FoundEnemies);
// Only spawn if we haven't reached the maximum
if (FoundEnemies.Num() < MaxEnemies)
{
UWorld* World = GetWorld();
if (World && EnemyClass)
{
FVector SpawnLocation = GetRandomSpawnLocation();
FRotator SpawnRotation = FRotator::ZeroRotator;
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
// Spawn using the Blueprint class instead of the C++ class directly
AEnemySpaceship* NewEnemy = World->SpawnActor<AEnemySpaceship>(EnemyClass, SpawnLocation,
SpawnRotation, SpawnParams);
}
}
}
FVector ASpaceShooterGameMode::GetRandomSpawnLocation()
{
APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0);
if (PlayerController && PlayerController->GetPawn())
{
FVector PlayerLocation = PlayerController->GetPawn()->GetActorLocation();
// Generate random angle
float Angle = FMath::RandRange(0.0f, 2.0f * PI);
// Generate random radius between min and max
float Radius = FMath::RandRange(MinSpawnRadius, MaxSpawnRadius);
// Calculate spawn position in a circle around the player
FVector SpawnLocation;
SpawnLocation.X = PlayerLocation.X + Radius * FMath::Cos(Angle);
SpawnLocation.Y = PlayerLocation.Y + Radius * FMath::Sin(Angle);
SpawnLocation.Z = PlayerLocation.Z;
return SpawnLocation;
}
return FVector::ZeroVector;
}

View File

@@ -0,0 +1,38 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "SpaceShooterGameMode.generated.h"
UCLASS()
class MYPROJECT3_API ASpaceShooterGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
ASpaceShooterGameMode();
virtual void StartPlay() override;
virtual void Tick(float DeltaTime) override;
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawning")
TSubclassOf<class AEnemySpaceship> EnemyClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawning")
float EnemySpawnInterval = 2.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawning")
int32 MaxEnemies = 10;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawning")
float MinSpawnRadius = 1000.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawning")
float MaxSpawnRadius = 2000.0f;
private:
FTimerHandle EnemySpawnTimer;
void SpawnEnemy();
FVector GetRandomSpawnLocation();
};

View File

@@ -0,0 +1,338 @@
#include "SpaceshipPawn.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/StaticMeshComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "SpaceshipProjectile.h"
#include "Kismet/GameplayStatics.h"
#include "GameFramework/GameUserSettings.h"
ASpaceshipPawn::ASpaceshipPawn()
{
PrimaryActorTick.bCanEverTick = true;
// Create ship mesh
ShipMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ShipMesh"));
RootComponent = ShipMesh;
ShipMesh->SetSimulatePhysics(false);
ShipMesh->SetEnableGravity(false);
// Create projectile spawn point
ProjectileSpawnPoint = CreateDefaultSubobject<USceneComponent>(TEXT("ProjectileSpawnPoint"));
ProjectileSpawnPoint->SetupAttachment(ShipMesh);
// Create camera spring arm
CameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
CameraSpringArm->SetupAttachment(RootComponent);
CameraSpringArm->TargetArmLength = 400.0f;
CameraSpringArm->bEnableCameraLag = true;
CameraSpringArm->CameraLagSpeed = 10.0f;
CameraSpringArm->bEnableCameraRotationLag = true;
CameraSpringArm->CameraRotationLagSpeed = 10.0f;
CameraSpringArm->CameraLagMaxDistance = 7.0f;
CameraSpringArm->bUsePawnControlRotation = false; // Add this line
CameraSpringArm->bInheritPitch = true; // Add this line
CameraSpringArm->bInheritYaw = true; // Add this line
CameraSpringArm->bInheritRoll = false; // Add this line
// Create camera
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
Camera->SetupAttachment(CameraSpringArm, USpringArmComponent::SocketName);
// Initialize movement variables
CurrentThrust = 0.0f;
TargetThrust = 0.0f;
bThrottlePressed = false;
CurrentVelocity = FVector::ZeroVector;
CurrentPitch = 0.0f;
CurrentYaw = 0.0f;
TargetRotation = FRotator::ZeroRotator;
LastMouseDelta = FVector2D::ZeroVector;
if (ShipMesh)
{
ShipMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
ShipMesh->SetCollisionObjectType(ECC_GameTraceChannel1); // This is the "Player" channel
ShipMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block);
ShipMesh->SetCollisionResponseToChannel(ECC_GameTraceChannel1, ECollisionResponse::ECR_Ignore);
ShipMesh->SetCollisionResponseToChannel(ECC_Pawn, ECollisionResponse::ECR_Ignore);
}
}
void ASpaceshipPawn::BeginPlay()
{
Super::BeginPlay();
// Debug messages for setup verification
if (GEngine)
{
if (ProjectileClass)
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("ProjectileClass is set"));
else
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("ProjectileClass is NOT set"));
if (ShootAction)
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("ShootAction is set"));
else
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("ShootAction is NOT set"));
if (ProjectileSpawnPoint)
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("ProjectileSpawnPoint is set"));
else
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("ProjectileSpawnPoint is NOT set"));
}
// Store player controller reference
PlayerControllerRef = Cast<APlayerController>(Controller);
if (PlayerControllerRef)
{
// Setup input mapping context
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerControllerRef->GetLocalPlayer()))
{
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
// Setup mouse capture and fullscreen
PlayerControllerRef->SetShowMouseCursor(false);
PlayerControllerRef->SetInputMode(FInputModeGameOnly());
// Request fullscreen mode using GameUserSettings
UGameUserSettings* GameUserSettings = UGameUserSettings::GetGameUserSettings();
if (GameUserSettings)
{
GameUserSettings->SetFullscreenMode(EWindowMode::Fullscreen);
GameUserSettings->SetScreenResolution(FIntPoint(1920, 1080)); // Adjust the resolution if needed
GameUserSettings->ApplySettings(false);
}
}
}
void ASpaceshipPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// Debug info
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Yellow,
FString::Printf(TEXT("Thrust: %.2f"), CurrentThrust));
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Green,
FString::Printf(TEXT("Velocity: %.2f"), CurrentVelocity.Size()));
}
// Smooth mouse movement
MouseDeltaSmoothed = FMath::Vector2DInterpTo(
MouseDeltaSmoothed,
LastMouseDelta,
DeltaTime,
MouseSmoothingSpeed
);
// Update rotation based on smoothed mouse movement
CurrentYaw += MouseDeltaSmoothed.X * MouseSensitivity * DeltaTime * 60.0f; // Multiply by 60 to normalize for frame rate
CurrentPitch = FMath::ClampAngle(
CurrentPitch + (MouseDeltaSmoothed.Y * MouseSensitivity * DeltaTime * 60.0f),
-85.0f,
85.0f
);
// Set target rotation
TargetRotation = FRotator(CurrentPitch, CurrentYaw, 0.0f);
// Smoothly interpolate to target rotation using quaternions for better interpolation
FQuat CurrentQuat = GetActorQuat();
FQuat TargetQuat = TargetRotation.Quaternion();
FQuat NewQuat = FQuat::Slerp(CurrentQuat, TargetQuat, RotationSpeed * DeltaTime);
SetActorRotation(NewQuat);
// Get the current forward vector
FVector CurrentDirection = GetActorForwardVector();
float CurrentSpeed = CurrentVelocity.Size();
// Handle thrust and velocity direction
if (!bThrottlePressed)
{
// Decelerate when not thrusting
CurrentThrust = FMath::FInterpTo(CurrentThrust, 0.0f, DeltaTime, ThrustDeceleration);
bWasThrottlePressed = false;
// Maintain current velocity direction when not thrusting
DesiredVelocityDirection = CurrentVelocity.GetSafeNormal();
}
else
{
// Accelerate when thrusting
CurrentThrust = FMath::FInterpConstantTo(CurrentThrust, TargetThrust, DeltaTime, ThrustAcceleration);
if (!bWasThrottlePressed)
{
// Just started thrusting - blend between current and new direction
if (!CurrentVelocity.IsNearlyZero())
{
// Blend between current velocity direction and new direction
FVector CurrentDir = CurrentVelocity.GetSafeNormal();
DesiredVelocityDirection = FMath::Lerp(CurrentDir, CurrentDirection, 1.0f - DirectionalInertia);
DesiredVelocityDirection.Normalize();
}
else
{
// If nearly stationary, use new direction
DesiredVelocityDirection = CurrentDirection;
}
}
else
{
// Continuously blend towards current facing direction while thrusting
DesiredVelocityDirection = FMath::VInterpNormalRotationTo(
DesiredVelocityDirection,
CurrentDirection,
DeltaTime,
VelocityAlignmentSpeed
);
}
bWasThrottlePressed = true;
}
// Calculate thrust force
FVector ThrustForce = CurrentDirection * CurrentThrust;
// Apply drag
FVector DragForce = -CurrentVelocity * DragCoefficient;
// Update velocity with forces
CurrentVelocity += (ThrustForce + DragForce) * DeltaTime;
// Update position
FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
SetActorLocation(NewLocation, true);
// Update spring arm rotation to match ship with smooth interpolation
if (CameraSpringArm)
{
FRotator SpringArmRotation = CameraSpringArm->GetComponentRotation();
FRotator TargetSpringArmRotation = NewQuat.Rotator();
FRotator NewSpringArmRotation = FMath::RInterpTo(
SpringArmRotation,
TargetSpringArmRotation,
DeltaTime,
RotationSpeed
);
CameraSpringArm->SetWorldRotation(NewSpringArmRotation);
}
// Reset mouse delta for next frame
LastMouseDelta = FVector2D::ZeroVector;
// Debug info
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Yellow,
FString::Printf(TEXT("Smoothed Mouse Delta: X=%.2f Y=%.2f"), MouseDeltaSmoothed.X, MouseDeltaSmoothed.Y));
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Green,
FString::Printf(TEXT("Current Rotation: P=%.2f Y=%.2f"), CurrentPitch, CurrentYaw));
}
}
void ASpaceshipPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
// Bind both Hold and Released events for throttle
EnhancedInputComponent->BindAction(ThrottleAction, ETriggerEvent::Started, this, &ASpaceshipPawn::HandleThrottleStarted);
EnhancedInputComponent->BindAction(ThrottleAction, ETriggerEvent::Completed, this, &ASpaceshipPawn::HandleThrottleReleased);
// Bind mouse control
EnhancedInputComponent->BindAction(MouseLookAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::HandleMouseLook);
// Add shooting binding
EnhancedInputComponent->BindAction(ShootAction, ETriggerEvent::Triggered, this, &ASpaceshipPawn::HandleShoot);
}
}
// Split the throttle handling into two functions
void ASpaceshipPawn::HandleThrottleStarted(const FInputActionValue& Value)
{
const float ThrottleValue = Value.Get<float>();
bThrottlePressed = true;
TargetThrust = ThrottleValue * MaxThrust;
}
void ASpaceshipPawn::HandleThrottleReleased(const FInputActionValue& Value)
{
bThrottlePressed = false;
}
void ASpaceshipPawn::HandleMouseLook(const FInputActionValue& Value)
{
const FVector2D MouseDelta = Value.Get<FVector2D>();
// Smoothly interpolate mouse delta
LastMouseDelta = MouseDelta;
}
void ASpaceshipPawn::HandleShoot(const FInputActionValue& Value)
{
// Debug message
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Yellow, TEXT("HandleShoot Called"));
if (bCanFire)
{
Fire();
}
}
void ASpaceshipPawn::Fire()
{
// Debug messages
if (!ProjectileClass)
{
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Red, TEXT("ProjectileClass not set!"));
return;
}
UWorld* World = GetWorld();
if (World)
{
FVector SpawnLocation = ProjectileSpawnPoint->GetComponentLocation();
FRotator SpawnRotation = GetActorRotation();
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = this;
SpawnParams.Instigator = GetInstigator();
// Spawn the projectile
ASpaceshipProjectile* Projectile = World->SpawnActor<ASpaceshipProjectile>(
ProjectileClass,
SpawnLocation,
SpawnRotation,
SpawnParams
);
if (Projectile)
{
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Green, TEXT("Projectile Spawned"));
}
else
{
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Red, TEXT("Failed to spawn projectile"));
}
// Start fire rate timer
bCanFire = false;
GetWorldTimerManager().SetTimer(FireTimerHandle, this, &ASpaceshipPawn::ResetFire, FireRate, false);
}
}
void ASpaceshipPawn::ResetFire()
{
bCanFire = true;
}

View File

@@ -0,0 +1,111 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "InputActionValue.h"
#include "SpaceshipPawn.generated.h"
UCLASS()
class MYPROJECT3_API ASpaceshipPawn : public APawn
{
GENERATED_BODY()
public:
ASpaceshipPawn();
virtual void Tick(float DeltaTime) override;
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
protected:
virtual void BeginPlay() override;
// Components
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
class UStaticMeshComponent* ShipMesh;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
class USpringArmComponent* CameraSpringArm;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
class UCameraComponent* Camera;
// Enhanced Input Components
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputMappingContext* DefaultMappingContext;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputAction* ThrottleAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputAction* MouseLookAction;
// Movement Parameters
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float MaxThrust = 2000.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float ThrustAcceleration = 500.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float ThrustDeceleration = 500.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float RotationSpeed = 100.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float MouseSensitivity = 2.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float DragCoefficient = 0.05f;
// How quickly velocity aligns with new direction
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement", meta = (ClampMin = "0.0", ClampMax = "10.0"))
float VelocityAlignmentSpeed = 4.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement", meta = (ClampMin = "0.0", ClampMax = "1.0", ToolTip = "How much of the current velocity is maintained when changing direction (0 = none, 1 = full)"))
float DirectionalInertia = 0.3f;
// Shooting properties
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Combat")
TSubclassOf<class ASpaceshipProjectile> ProjectileClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Combat")
float FireRate = 0.2f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Combat")
USceneComponent* ProjectileSpawnPoint;
// Input action for shooting
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputAction* ShootAction;
// Input functions
void HandleThrottleStarted(const FInputActionValue& Value);
void HandleThrottleReleased(const FInputActionValue& Value);
void HandleMouseLook(const FInputActionValue& Value);
private:
// Movement state
float CurrentThrust;
float TargetThrust;
bool bThrottlePressed;
FVector CurrentVelocity;
FRotator TargetRotation;
float CurrentPitch;
float CurrentYaw;
APlayerController* PlayerControllerRef;
FVector2D MouseDeltaSmoothed;
FVector2D LastMouseDelta;
float MouseSmoothingSpeed = 10.0f;
bool bWasThrottlePressed;
FVector DesiredVelocityDirection;
FTimerHandle FireTimerHandle;
bool bCanFire = true;
void HandleShoot(const FInputActionValue& Value);
void Fire();
void ResetFire();
};

View File

@@ -0,0 +1,75 @@
#include "SpaceshipProjectile.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Components/StaticMeshComponent.h"
#include "EnemySpaceship.h"
ASpaceshipProjectile::ASpaceshipProjectile()
{
PrimaryActorTick.bCanEverTick = true;
// Create and setup the projectile mesh
ProjectileMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ProjectileMesh"));
RootComponent = ProjectileMesh;
ProjectileMesh->SetCollisionProfileName(TEXT("Projectile"));
ProjectileMesh->OnComponentHit.AddDynamic(this, &ASpaceshipProjectile::OnHit);
// Set up collision
ProjectileMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
ProjectileMesh->SetCollisionObjectType(ECC_WorldDynamic);
ProjectileMesh->SetCollisionResponseToAllChannels(ECR_Ignore);
ProjectileMesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Block); // Block pawns (enemies)
ProjectileMesh->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block); // Block world static
ProjectileMesh->SetGenerateOverlapEvents(true);
// Bind hit event
ProjectileMesh->OnComponentHit.AddDynamic(this, &ASpaceshipProjectile::OnHit);
// Create and setup projectile movement
ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovement"));
ProjectileMovement->UpdatedComponent = ProjectileMesh;
ProjectileMovement->InitialSpeed = ProjectileSpeed;
ProjectileMovement->MaxSpeed = ProjectileSpeed;
ProjectileMovement->bRotationFollowsVelocity = true;
ProjectileMovement->ProjectileGravityScale = 0.0f;
// Set lifetime
InitialLifeSpan = 3.0f;
}
void ASpaceshipProjectile::BeginPlay()
{
Super::BeginPlay();
}
void ASpaceshipProjectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp,
FVector NormalImpulse, const FHitResult& Hit)
{
// Debug message to verify hit detection
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Yellow,
FString::Printf(TEXT("Projectile hit: %s"), *OtherActor->GetName()));
}
if (OtherActor && OtherActor != this)
{
// Check if we hit an enemy
AEnemySpaceship* Enemy = Cast<AEnemySpaceship>(OtherActor);
if (Enemy)
{
// Apply damage
FDamageEvent DamageEvent;
Enemy->TakeDamage(DamageAmount, DamageEvent, nullptr, this);
// Debug message for damage
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Red,
FString::Printf(TEXT("Dealt %f damage to enemy"), DamageAmount));
}
}
}
// Destroy the projectile
Destroy();
}

View File

@@ -0,0 +1,33 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SpaceshipProjectile.generated.h"
UCLASS()
class MYPROJECT3_API ASpaceshipProjectile : public AActor
{
GENERATED_BODY()
public:
ASpaceshipProjectile();
protected:
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
class UStaticMeshComponent* ProjectileMesh;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
class UProjectileMovementComponent* ProjectileMovement;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile")
float ProjectileSpeed = 3000.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile")
float DamageAmount = 20.0f;
UFUNCTION()
void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp,
FVector NormalImpulse, const FHitResult& Hit);
};