Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added formatting instructions #645

Merged
merged 11 commits into from
Dec 28, 2024
35 changes: 31 additions & 4 deletions Sources/UntoldEngine/Systems/SteeringSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,33 @@ func setWaypointIndex(for entityId: EntityID, index: Int) {
entityWaypointIndices[entityId] = index
}

public func getDistanceFromPath(for entityId: EntityID, path: [simd_float3]) -> Float? {
// Return nil if the path is empty
guard !path.isEmpty else {
return nil
}

// Ensure the current waypoint index is valid
let currentWaypointIndex = max(0, getWaypointIndex(for: entityId) - 1)
let nextWaypointIndex = (currentWaypointIndex + 1) % path.count

// Extract relevant points
let entityPosition = getPosition(entityId: entityId)
let startPoint = path[currentWaypointIndex]
let endPoint = path[nextWaypointIndex]

// Compute the direction vector and normalize it
let direction = simd_normalize(endPoint - startPoint)

// Project the entity's position onto the line segment
let offset = entityPosition - startPoint
let projection = dot(offset, direction)
let closestPointOnPath = startPoint + projection * direction

// Compute the distance from the entity's position to the closest point
return distance(entityPosition, closestPointOnPath)
}

// Low-Level Steering Behaviors

func seek(entityId: EntityID, targetPosition: simd_float3, maxSpeed: Float) -> simd_float3 {
Expand Down Expand Up @@ -261,7 +288,7 @@ public func orbit(entityId: EntityID, centerPosition: simd_float3, radius: Float
/// - targetPosition: The position to move towards.
/// - maxSpeed: The maximum speed of the entity.
/// - deltaTime: The elapsed time for the current frame.
public func steerTo(entityId: EntityID, targetPosition: simd_float3, maxSpeed: Float, deltaTime: Float, turnSpeed: Float = 1.0) {
public func steerTo(entityId: EntityID, targetPosition: simd_float3, maxSpeed: Float, deltaTime: Float, turnSpeed: Float = 1.0, weight: Float = 1.0) {
if gameMode == false {
return
}
Expand All @@ -278,7 +305,7 @@ public func steerTo(entityId: EntityID, targetPosition: simd_float3, maxSpeed: F
}

// Use the seek behavior to calculate the steering velocity adjustment
let steeringAdjustment = seek(entityId: entityId, targetPosition: targetPosition, maxSpeed: maxSpeed)
let steeringAdjustment = seek(entityId: entityId, targetPosition: targetPosition, maxSpeed: maxSpeed) * weight

// Convert the velocity adjustment into a force for the physics system
if let physicsComponent = scene.get(component: PhysicsComponents.self, for: entityId) {
Expand Down Expand Up @@ -435,7 +462,7 @@ public func steerPursuit(entityId: EntityID, targetEntity: EntityID, maxSpeed: F
}
}

public func followPath(entityId: EntityID, path: [simd_float3], maxSpeed: Float, deltaTime: Float, turnSpeed: Float = 1.0, waypointThreshold: Float = 0.5) {
public func followPath(entityId: EntityID, path: [simd_float3], maxSpeed: Float, deltaTime: Float, turnSpeed: Float = 1.0, waypointThreshold: Float = 0.5, weight: Float = 1.0) {
if gameMode == false {
return
}
Expand Down Expand Up @@ -469,7 +496,7 @@ public func followPath(entityId: EntityID, path: [simd_float3], maxSpeed: Float,
}

// Seek toward the current waypoint
let seekForce = seek(entityId: entityId, targetPosition: targetWaypoint, maxSpeed: maxSpeed)
let seekForce = seek(entityId: entityId, targetPosition: targetWaypoint, maxSpeed: maxSpeed) * weight

guard let physicsComponent = scene.get(component: PhysicsComponents.self, for: entityId) else {
handleError(.noPhysicsComponent, entityId)
Expand Down
73 changes: 73 additions & 0 deletions Tests/UntoldEngineTests/SteeringSystemTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,77 @@ final class SteeringSystemTests: XCTestCase {
let newPosition = getPosition(entityId: entityId)
XCTAssertNotEqual(newPosition, simd_float3(radius, 0, 0)) // Position changes around the orbit
}

func testGetDistanceFromPath() {
// Mock EntityID and its position
let entityId: EntityID = 1
let mockPosition = simd_float3(2, 0, 0)

// Mock path
let path: [simd_float3] = [
simd_float3(0, 0, 0), // Waypoint 1
simd_float3(5, 0, 0), // Waypoint 2
]

// Mock functions
func getWaypointIndex(for _: EntityID) -> Int {
1 // Simulate that the entity is closest to the first waypoint
}

func getPosition(entityId _: EntityID) -> simd_float3 {
mockPosition
}

// Run the function
let distance = getDistanceFromPath(for: entityId, path: path)

// Expected result: perpendicular distance from (2,0,0) to the line segment (0,0,0) -> (5,0,0) is 0
let expectedDistance: Float = 0.0

// Assert the results
XCTAssertNotNil(distance, "Distance should not be nil for a valid path.")
XCTAssertEqual(distance, expectedDistance, "Distance should be accurately calculated.")
}

func testEmptyPathReturnsNil() {
let entityId: EntityID = 1
let path: [simd_float3] = []

// Run the function
let distance = getDistanceFromPath(for: entityId, path: path)

// Assert the results
XCTAssertNil(distance, "Distance should be nil for an empty path.")
}

func testInvalidWaypointIndexHandledGracefully() {
// Mock EntityID and its position
let entityId: EntityID = 1
let mockPosition = simd_float3(2, 0, 0)

// Mock path
let path: [simd_float3] = [
simd_float3(0, 0, 0), // Waypoint 1
simd_float3(5, 0, 0), // Waypoint 2
]

// Mock functions
func getWaypointIndex(for _: EntityID) -> Int {
-10 // Simulate an invalid negative waypoint index
}

func getPosition(entityId _: EntityID) -> simd_float3 {
mockPosition
}

// Run the function
let distance = getDistanceFromPath(for: entityId, path: path)

// Expected result: Still calculates distance properly from clamped waypoint index
let expectedDistance: Float = 0.0

// Assert the results
XCTAssertNotNil(distance, "Distance should not be nil for a valid path.")
XCTAssertEqual(distance, expectedDistance, "Distance should be accurately calculated.")
}
}
1 change: 1 addition & 0 deletions docs/ContributionGuidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Your guide must follow this structure:
- Use concise and user-friendly language.
- Ensure all code examples are complete, tested, and follow the engine’s coding conventions.
- PRs must be documented in the /Documentation folder, with guides in markdown format.
- Make sure your code follows the [formatting guidelines](Formatting.md).

---
Thank you for contributing to the Untold Engine! Following these guidelines will ensure that your work aligns with the project's goals and provides value to users.
48 changes: 48 additions & 0 deletions docs/Formatting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Formatting and Linting

To maintain a consistent code style across the Untold Engine repo, we use [SwiftFormat](https://github.com/nicklockwood/SwiftFormat). SwiftFormat is a code formatter for Swift that helps enforce Swift style conventions and keep the codebase clean.

### Installing SwiftFormat

The simplest way to install SwiftFormat is through the command line.

1. Install SwiftFormat Using Homebrew: Open the terminal and run the following command:

```bash
brew install swiftformat
```
2. Verify Installation: After installation, verify that SwiftFormat is installed correctly by running:

```bash
swiftformat --version
```
This should print the installed version of SwiftFormat.

### Using SwiftFormat

Format a Single File

To format a specific Swift file:

1. Open the terminal and navigate to your project directory.

2. Run the following command:

```bash
swiftformat path/to/YourFile.swift
```
This will format YourFile.swift according to the default rules.

### Format Multiple Files

To format all Swift files in your project:

1. Navigate to your project directory in the terminal.

2. Run the following command:

```bash
swiftformat .
```

This will recursively format all Swift files in the current directory and its subdirectories.
4 changes: 2 additions & 2 deletions docs/Installation.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# How to test the Untold Engine
# How to install the Untold Engine

Follow these steps to set up and run the Untold Engine:
Follow these steps to set up and run the Untold Engine. Or if you are a visual learner, you can watch this [video tutorial](https://www.youtube.com/watch?v=XK7GGLeFlFg):

1. Clone the Repository

Expand Down
5 changes: 3 additions & 2 deletions docs/Onboarding.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Choose your starting path

I’ve designed three different ways for you to get started with the Untold Engine. Whether you just want to explore or are ready to make your own game, we’ve got you covered:
I’ve designed three different ways for you to get started with the Untold Engine. Whether you just want to explore or are ready to make your own game, we’ve got you covered. Before you begin, make sure to [clone the Untold Engine](Installation.md).


## Demo Game – Jump Right In

Expand Down Expand Up @@ -44,7 +45,7 @@ What’s Included:
- A fully set-up Xcode project that’s ready to roll.
- Easy integration with your own assets or code.

How to Start: Check out the step-by-step guide in [Create a Mac OS Game](docs/Installation.md), and you’ll be on your way in no time.
How to Start: Check out the step-by-step guide in [Create a Mac OS Game](CreateMacOSGame.md), and you’ll be on your way in no time.

---

Expand Down