上一篇文章写了整体框架,这篇文章来贴出我自己跟着siki学院的飞机大作战视频所制作的代码,编译环境为VS2019,UE4.26完美运行。
SpaceShip.cpp
#include "SpaceShip.h" #include "Components/StaticMeshComponent.h" #include "Components/SphereComponent.h" #include "Camera/CameraComponent.h" #include "Gameframework/PlayerController.h" #include "Kismet/KismetMathLibrary.h" #include "Gameframework/SpringArmComponent.h" #include "Misc/App.h" #include "Engine/World.h" #include "Bullet.h" #include "TimerManager.h" #include "Enemy.h" #include "Kismet/GameplayStatics.h" #include "Sound/SoundCue.h" #include "Particles/ParticleSystemComponent.h" #include "Particles/ParticleSystem.h" // Sets default values ASpaceShip::ASpaceShip() { // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; CollisionComp = CreateDefaultSubobject(TEXT("CollisionComp")); RootComponent = CollisionComp; ShipSM = CreateDefaultSubobject (TEXT("ShipSM")); ShipSM->SetupAttachment(RootComponent); SpringArmComp = CreateDefaultSubobject (TEXT("SpringArmComp")); SpringArmComp->SetupAttachment(RootComponent); CameraComp = CreateDefaultSubobject (TEXT("CameraComp")); CameraComp->SetupAttachment(SpringArmComp); SpawnPoint = CreateDefaultSubobject (TEXT("SpawnPoint")); SpawnPoint->SetupAttachment(ShipSM); ThrusterParticleComp = CreateDefaultSubobject (TEXT("ThrusterParticleComp")); ThrusterParticleComp->SetupAttachment(RootComponent); Speed = 2500.0f; TimeBetweenShot = 0.2f; bDead = false; } // Called when the game starts or when spawned void ASpaceShip::BeginPlay() { Super::BeginPlay(); PC = Cast(GetController()); PC->bShowMouseCursor = true; } void ASpaceShip::LookAtCursor() { FVector MouseLocation, MouseDirection; PC->DeprojectMousePositionToWorld(MouseLocation, MouseDirection); FVector TargetLocation = FVector(MouseLocation.X, MouseLocation.Y, GetActorLocation().Z); FRotator Rotator = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), TargetLocation); SetActorRotation(Rotator); } void ASpaceShip::MoveUp(float Value) { if (Value != 0) { bUpMove = true; } else { bUpMove = false; } AddMovementInput(FVector::ForwardVector, Value); } void ASpaceShip::MoveRight(float Value) { if (Value != 0) { bRightMove = true; } else { bRightMove = false; } AddMovementInput(FVector::RightVector, Value); } void ASpaceShip::Move() { AddActorWorldOffset(ConsumeMovementInputVector() * Speed * FApp::GetDeltaTime(), true); } void ASpaceShip::Fire() { if (Bullet && !bDead) { FActorSpawnParameters SpawnParams; GetWorld()->SpawnActor(Bullet, SpawnPoint->GetComponentLocation(), SpawnPoint->GetComponentRotation(), SpawnParams); if (ShootCue) UGameplayStatics::PlaySoundAtLocation(this, ShootCue, GetActorLocation()); } } void ASpaceShip::StartFire() { GetWorldTimerManager().SetTimer(TimerHandle_BetweenShot, this, &ASpaceShip::Fire, TimeBetweenShot, true, 0.0f); } void ASpaceShip::EndFire() { GetWorldTimerManager().ClearTimer(TimerHandle_BetweenShot); } void ASpaceShip::RestartLevel() { UGameplayStatics::OpenLevel(this, "MainMap"); } void ASpaceShip::onDeath() { bDead = true; CollisionComp->SetVisibility(false, true); if (GameOverCue) UGameplayStatics::PlaySoundAtLocation(this, GameOverCue, GetActorLocation()); if (ExplosionParticle) UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplosionParticle, GetActorLocation(), FRotator::ZeroRotator, true); GetWorldTimerManager().SetTimer(TimerHandle_Restart, this, &ASpaceShip::RestartLevel, 2.0f, false); } // Called every frame void ASpaceShip::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (!bDead) { if (bRightMove || bUpMove) { ThrusterParticleComp->Activate(); } else { ThrusterParticleComp->Deactivate(); } LookAtCursor(); Move(); } else { ThrusterParticleComp->Deactivate(); } } // Called to bind functionality to input void ASpaceShip::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); PlayerInputComponent->BindAxis("MoveUp", this, &ASpaceShip::MoveUp); PlayerInputComponent->BindAxis("MoveRight", this, &ASpaceShip::MoveRight); PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &ASpaceShip::StartFire); PlayerInputComponent->BindAction("Fire", IE_Released, this, &ASpaceShip::EndFire); } void ASpaceShip::NotifyActorBeginOverlap(AActor* OtherActor) { Super::NotifyActorBeginOverlap(OtherActor); AEnemy* Enemy = Cast(OtherActor); if (Enemy) { Enemy->Destroy(); UE_LOG(LogTemp, Warning, TEXT("Player is Dead")); onDeath(); //Destroy(); } }
SpaceShip.h
#pragma once #include "CoreMinimal.h" #include "Gameframework/Pawn.h" #include "SpaceShip.generated.h" class USphereComponent; class UCameraComponent; class USpringArmComponent; class ABullet; class USoundCue; UCLASS() class SPACESHIPBATTLE_API ASpaceShip : public APawn { GENERATED_BODY() public: // Sets default values for this pawn's properties ASpaceShip(); protected: UPROPERTY(VisibleAnywhere, Category = "Component") USphereComponent* CollisionComp; UPROPERTY(VisibleAnywhere, Category = "Component") UStaticMeshComponent* ShipSM; UPROPERTY(VisibleAnywhere, Category = "Component") UCameraComponent* CameraComp; UPROPERTY(VisibleAnywhere, Category = "Component") USpringArmComponent* SpringArmComp; APlayerController* PC; UPROPERTY(EditAnywhere, Category = "Fire") TSubclassOf Bullet; UPROPERTY(VisibleAnywhere, Category = "Component") USceneComponent* SpawnPoint; UPROPERTY(EditAnywhere, Category = "Move") float Speed; FTimerHandle TimerHandle_BetweenShot; FTimerHandle TimerHandle_Restart; UPROPERTY(EditAnywhere, Category = "Fire") float TimeBetweenShot; UPROPERTY(EditAnywhere, Category = "Souned") USoundCue* GameOverCue; UPROPERTY(EditAnywhere, Category = "Souned") USoundCue* ShootCue; UPROPERTY(VisibleAnywhere, Category = "Component") UParticleSystemComponent* ThrusterParticleComp; UPROPERTY(EditAnywhere, Category = "Particle") UParticleSystem* ExplosionParticle; bool bDead; bool bUpMove; bool bRightMove; // Called when the game starts or when spawned virtual void BeginPlay() override; void LookAtCursor(); void MoveUp(float Value); void MoveRight(float Value); void Move(); void Fire(); void StartFire(); void EndFire(); void RestartLevel(); void onDeath(); public: // Called every frame virtual void Tick(float DeltaTime) override; // Called to bind functionality to input virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; virtual void NotifyActorBeginOverlap(AActor* OtherActor) override; FORCEINLINE bool GetBDead() { return bDead; } };
Enemy.cpp
#include "Enemy.h" #include "Components/StaticMeshComponent.h" #include "Components/SphereComponent.h" #include "Kismet/GameplayStatics.h" #include "SpaceShip.h" #include "Kismet/KismetMathLibrary.h" #include "ShipGameMode.h" #include "EnemySpawner.h" #include "Particles/ParticleSystem.h" // Sets default values AEnemy::AEnemy() { // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; CollisionComp = CreateDefaultSubobject(TEXT("CollisionComp")); RootComponent = CollisionComp; ShipSM = CreateDefaultSubobject (TEXT("ShipSM")); ShipSM->SetupAttachment(RootComponent); } // Called when the game starts or when spawned void AEnemy::BeginPlay() { Super::BeginPlay(); SpaceShip = Cast(UGameplayStatics::GetPlayerPawn(this, 0)); SetColor(); MyGameMode = Cast(UGameplayStatics::GetGameMode(this)); TArray EnemySpawnerArray; UGameplayStatics::GetAllActorsOfClass(this, AEnemySpawner::StaticClass(), EnemySpawnerArray); EnemySpawner = Cast(EnemySpawnerArray[0]); } void AEnemy::MoveTowardsPlayer(float DeltaTime) { FVector Direction = (SpaceShip->GetActorLocation() - GetActorLocation()).GetSafeNormal(); AddActorWorldOffset(Direction * Speed * DeltaTime, true); SetActorRotation(UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), SpaceShip->GetActorLocation())); } void AEnemy::onDeath() { MyGameMode->IncreaseScore(); EnemySpawner->DecreaseEnemyCount(); SpawnExplosion(); Destroy(); } // Called every frame void AEnemy::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (SpaceShip->GetBDead() == false) MoveTowardsPlayer(DeltaTime); } // Called to bind functionality to input void AEnemy::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); }
Enemy.h
#pragma once #include "CoreMinimal.h" #include "Gameframework/Pawn.h" #include "Enemy.generated.h" class USphereComponent; class ASpaceShip; class AShipGameMode; class AEnemySpawner; UCLASS() class SPACESHIPBATTLE_API AEnemy : public APawn { GENERATED_BODY() public: // Sets default values for this pawn's properties AEnemy(); protected: UPROPERTY(VisibleAnywhere, Category = "Component") USphereComponent* CollisionComp; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Component") UStaticMeshComponent* ShipSM; // Called when the game starts or when spawned virtual void BeginPlay() override; void MoveTowardsPlayer(float DeltaTime); ASpaceShip* SpaceShip; AShipGameMode* MyGameMode; float Speed = 300.0f; AEnemySpawner* EnemySpawner; UFUNCTION(BlueprintImplementableEvent) void SetColor(); UFUNCTION(BlueprintImplementableEvent) void SpawnExplosion(); UPROPERTY(EditAnywhere, Category = "Particle") UParticleSystem* ExplosionParticle; public: // Called every frame virtual void Tick(float DeltaTime) override; // Called to bind functionality to input virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; void onDeath(); };
Bullet.cpp
#include "Bullet.h" #include "Components/StaticMeshComponent.h" #include "Components/SceneComponent.h" #include "Gameframework/ProjectileMovementComponent.h" #include "Enemy.h" #include "Engine/BlockingVolume.h" #include "Kismet/GameplayStatics.h" #include "EnemySpawner.h" // Sets default values ABullet::ABullet() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; RootComp = CreateDefaultSubobject(TEXT("RootComp")); RootComponent = RootComp; BulletSM = CreateDefaultSubobject (TEXT("BulletSM")); BulletSM->SetupAttachment(RootComponent); ProjectileMovementComp = CreateDefaultSubobject (TEXT("ProjectileMovementComp")); } // Called when the game starts or when spawned void ABullet::BeginPlay() { Super::BeginPlay(); } // Called every frame void ABullet::Tick(float DeltaTime) { Super::Tick(DeltaTime); } void ABullet::NotifyActorBeginOverlap(AActor* OtherActor) { Super::NotifyActorBeginOverlap(OtherActor); AEnemy* Enemy = Cast(OtherActor); if (Enemy) { Enemy->onDeath(); Destroy(); } else if (Cast(OtherActor)) { Destroy(); } }
Bullet.h
#pragma once #include "CoreMinimal.h" #include "Gameframework/Actor.h" #include "Bullet.generated.h" class UProjectileMovementComponent; UCLASS() class SPACESHIPBATTLE_API ABullet : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties ABullet(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; UPROPERTY(VisibleAnywhere, Category = "Component") USceneComponent* RootComp; UPROPERTY(VisibleAnywhere, Category = "Component") UStaticMeshComponent* BulletSM; UPROPERTY(VisibleAnywhere, Category = "Component") UProjectileMovementComponent* ProjectileMovementComp; public: // Called every frame virtual void Tick(float DeltaTime) override; virtual void NotifyActorBeginOverlap(AActor* OtherActor) override; };
ShipGameMode.cpp
#include "ShipGameMode.h" AShipGameMode::AShipGameMode() { Score = 0; } void AShipGameMode::IncreaseScore() { Score++; }
ShipGameMode.h
#pragma once #include "CoreMinimal.h" #include "Gameframework/GameModebase.h" #include "ShipGameMode.generated.h" UCLASS() class SPACESHIPBATTLE_API AShipGameMode : public AGameModebase { GENERATED_BODY() protected: AShipGameMode(); UPROPERTY(BlueprintReadOnly) int Score; public: void IncreaseScore(); };
EnemySpawner.cpp
#include "EnemySpawner.h" #include "Components/BoxComponent.h" #include "Kismet/KismetMathLibrary.h" #include "Kismet/GameplayStatics.h" #include "SpaceShip.h" #include "Engine/World.h" #include "Enemy.h" // Sets default values AEnemySpawner::AEnemySpawner() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; SpawnArea = CreateDefaultSubobject(TEXT("SpawnArea")); RootComponent = SpawnArea; SpawnInterval = 2.0f; MaxEnemyNum = 30; CurrentEnemyCount = 0; } // Called when the game starts or when spawned void AEnemySpawner::BeginPlay() { Super::BeginPlay(); SpaceShip = Cast(UGameplayStatics::GetPlayerPawn(this, 0)); GetWorldTimerManager().SetTimer(TimerHandle_Spawn, this, &AEnemySpawner::SpawnEnemy, SpawnInterval, true, 0.0f); } FVector AEnemySpawner::GetGenerateLocation() { float Distance = 0; FVector Location; while (Distance < MininumDistanceToPlayer) { Location = UKismetMathLibrary::RandomPointInBoundingBox(SpawnArea->Bounds.Origin, SpawnArea->Bounds.BoxExtent); Distance = (Location - SpaceShip->GetActorLocation()).Size(); } return Location; } void AEnemySpawner::SpawnEnemy() { if (SpaceShip->GetBDead() == false && CurrentEnemyCount < MaxEnemyNum) { FActorSpawnParameters SpawnParameters; GetWorld()->SpawnActor(Enemy, GetGenerateLocation(), FRotator::ZeroRotator, SpawnParameters); CurrentEnemyCount++; } } // Called every frame void AEnemySpawner::Tick(float DeltaTime) { Super::Tick(DeltaTime); } void AEnemySpawner::DecreaseEnemyCount() { if (CurrentEnemyCount > 0) { CurrentEnemyCount--; UE_LOG(LogTemp, Warning, TEXT("%s"), *FString::SanitizeFloat(CurrentEnemyCount)); } }
EnemySpawner.h
#pragma once #include "CoreMinimal.h" #include "Gameframework/Actor.h" #include "EnemySpawner.generated.h" class AEnemy; class UBoxComponent; class ASpaceShip; UCLASS() class SPACESHIPBATTLE_API AEnemySpawner : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties AEnemySpawner(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; UPROPERTY(EditAnywhere, Category = "Enemy") TSubclassOf Enemy; UPROPERTY(VisibleAnywhere, Category = "Component") UBoxComponent* SpawnArea; FVector GetGenerateLocation(); float MininumDistanceToPlayer = 1200.0f; ASpaceShip* SpaceShip; void SpawnEnemy(); FTimerHandle TimerHandle_Spawn; float SpawnInterval; UPROPERTY(EditAnywhere, Category = "Spawn") int MaxEnemyNum; int CurrentEnemyCount; public: // Called every frame virtual void Tick(float DeltaTime) override; void DecreaseEnemyCount(); };
以上就是编写的全部代码了,相关的在UE4中需要进行设置的在此就不再赘述,如有任何问题欢迎与我讨论。整体工程太大(10G左右),如果你想要的话私聊我,我可以网盘发给你。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)