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

feat/add camera #17

Merged
merged 13 commits into from Mar 25, 2024
9 changes: 5 additions & 4 deletions .swiftlint.yml
Expand Up @@ -2,7 +2,6 @@ excluded:
- Pods

opt_in_rules:
- anyobject_protocol
- array_init
- attributes
- closure_body_length
Expand All @@ -20,7 +19,6 @@ opt_in_rules:
- empty_xctest_method
- expiring_todo
- explicit_init
- explicit_self
- fallthrough
- fatal_error_message
- file_name
Expand Down Expand Up @@ -65,8 +63,6 @@ opt_in_rules:
- unneeded_parentheses_in_closure_argument
- unowned_variable_capture
- untyped_error_in_catch
- unused_declaration
- unused_import
- vertical_parameter_alignment_on_call
- xct_specific_matcher
- yoda_condition
Expand All @@ -81,3 +77,8 @@ disabled_rules:
line_length:
warning: 120
error: 150

analyzer_rules:
- explicit_self
- unused_declaration
- unused_import
11 changes: 10 additions & 1 deletion SDPhysicsEngine/Sources/SDPhysicsEngine/GameScene.swift
Expand Up @@ -43,6 +43,15 @@ extension GameScene: SDScene {
objectMap[object.node] = nil
object.removeFromParent()
}

public func addCameraObject(_ cameraObject: SDCameraObject) {
addObject(cameraObject)
camera = cameraObject.cameraNode
}

public func setCameraObjectXPosition(to x: CGFloat) {
camera?.position.x = x
}
}

extension GameScene: SKPhysicsContactDelegate {
Expand All @@ -57,7 +66,7 @@ extension GameScene: SKPhysicsContactDelegate {
fatalError("Unknown node in game scene")
}

sceneDelegate?.contactOccured(
sceneDelegate?.contactOccurred(
objectA: objectA,
objectB: objectB,
contactPoint: contact.contactPoint
Expand Down
@@ -0,0 +1,10 @@
import SpriteKit

public class SDCameraObject: SDObject {
let cameraNode: SKCameraNode

override public init() {
cameraNode = SKCameraNode()
super.init(node: cameraNode)
}
}
2 changes: 2 additions & 0 deletions SDPhysicsEngine/Sources/SDPhysicsEngine/SDScene.swift
Expand Up @@ -6,4 +6,6 @@ public protocol SDScene {

func addObject(_ object: SDObject)
func removeObject(_ object: SDObject)
func addCameraObject(_ cameraObject: SDCameraObject)
func setCameraObjectXPosition(to x: CGFloat)
}
Expand Up @@ -3,5 +3,5 @@ import CoreGraphics
public protocol SDSceneDelegate: AnyObject {

func update(_ scene: SDScene, deltaTime: Double)
func contactOccured(objectA: SDObject, objectB: SDObject, contactPoint: CGPoint)
func contactOccurred(objectA: SDObject, objectB: SDObject, contactPoint: CGPoint)
}
9 changes: 5 additions & 4 deletions star-dash/.swiftlint.yml
Expand Up @@ -2,7 +2,6 @@ excluded:
- Pods

opt_in_rules:
- anyobject_protocol
- array_init
- attributes
- closure_body_length
Expand All @@ -20,7 +19,6 @@ opt_in_rules:
- empty_xctest_method
- expiring_todo
- explicit_init
- explicit_self
- fallthrough
- fatal_error_message
- file_name
Expand Down Expand Up @@ -65,8 +63,6 @@ opt_in_rules:
- unneeded_parentheses_in_closure_argument
- unowned_variable_capture
- untyped_error_in_catch
- unused_declaration
- unused_import
- vertical_parameter_alignment_on_call
- xct_specific_matcher
- yoda_condition
Expand All @@ -81,3 +77,8 @@ disabled_rules:
line_length:
warning: 120
error: 150

analyzer_rules:
- explicit_self
- unused_declaration
- unused_import
2 changes: 0 additions & 2 deletions star-dash/star-dash.xcodeproj/project.pbxproj
Expand Up @@ -858,8 +858,6 @@
E69EE9322BAC6CBB00033AB5 /* GameInfo.swift in Sources */,
46D418222BA5D4E60091A38B /* Obstacle+Collidable.swift in Sources */,
E638B9CF2BAB3C5D00931CC2 /* TeleportEvent.swift in Sources */,
E6A745162BA057040080C1BE /* MTKRenderer.swift in Sources */,
E6A745182BA057040080C1BE /* Renderer.swift in Sources */,
143AA3972BA4E0D9009C28E7 /* PickupCollectibleEvent.swift in Sources */,
46D418242BA5D5280091A38B /* Tool+Collidable.swift in Sources */,
E64361142BA4C2CD003850FD /* CreationModule.swift in Sources */,
Expand Down
8 changes: 8 additions & 0 deletions star-dash/star-dash/GameEngine/GameEngine.swift
Expand Up @@ -73,6 +73,14 @@ class GameEngine {
eventManager.add(event: StopMovingEvent(on: playerEntityId))
}

func playerPosition() -> CGPoint? {
guard let playerEntityId = entityManager.playerEntityId(),
let positionComponent = entityManager.component(ofType: PositionComponent.self, of: playerEntityId) else {
return nil
}
return positionComponent.position
}

private func setUpSystems() {
systemManager.add(PositionSystem(entityManager, dispatcher: self))
systemManager.add(PhysicsSystem(entityManager, dispatcher: self))
Expand Down
60 changes: 28 additions & 32 deletions star-dash/star-dash/Persistence/Database.swift
Expand Up @@ -233,40 +233,36 @@ struct Database {

extension Database {
func insertJsonData() {
do {
if let fileURL = Bundle.main.url(forResource: "data", withExtension: "json") {
// Read JSON data from the file
do {
let jsonData = try Data(contentsOf: fileURL)
// Decode JSON data into LevelData
let levelData = try JSONDecoder().decode(LevelData.self, from: jsonData)
let levelPersistable = LevelPersistable(
id: levelData.id,
name: levelData.name,
size: levelData.size
)
insert(persistable: levelPersistable)
for persistable in levelData.collectibles {
insert(persistable: persistable)
}
for persistable in levelData.tools {
insert(persistable: persistable)
}
for persistable in levelData.obstacles {
insert(persistable: persistable)
}
for persistable in levelData.monsters {
insert(persistable: persistable)
}

} catch {
print("Error reading or decoding JSON: \(error)")
if let fileURL = Bundle.main.url(forResource: "data", withExtension: "json") {
// Read JSON data from the file
do {
let jsonData = try Data(contentsOf: fileURL)
// Decode JSON data into LevelData
let levelData = try JSONDecoder().decode(LevelData.self, from: jsonData)
let levelPersistable = LevelPersistable(
id: levelData.id,
name: levelData.name,
size: levelData.size
)
insert(persistable: levelPersistable)
for persistable in levelData.collectibles {
insert(persistable: persistable)
}
for persistable in levelData.tools {
insert(persistable: persistable)
}
for persistable in levelData.obstacles {
insert(persistable: persistable)
}
for persistable in levelData.monsters {
insert(persistable: persistable)
}
} else {
print("JSON file not found.")

} catch {
print("Error reading or decoding JSON: \(error)")
}
} catch {
print(error)
} else {
print("JSON file not found.")
}
}

Expand Down
6 changes: 4 additions & 2 deletions star-dash/star-dash/Rendering/MTKRenderer/ControlView.swift
Expand Up @@ -58,7 +58,8 @@ class ControlView: UIView {

// MARK: Gesture handler methods

@objc func jumpButtonTapped() {
@objc
func jumpButtonTapped() {
controlViewDelegate?.jumpButtonPressed()
}

Expand Down Expand Up @@ -92,7 +93,8 @@ class ControlView: UIView {
joystickView?.returnJoystick()
}

@objc func handlePan(_ gesture: UIPanGestureRecognizer) {
@objc
func handlePan(_ gesture: UIPanGestureRecognizer) {
guard let joystickView = self.joystickView else {
return
}
Expand Down
Expand Up @@ -7,7 +7,7 @@ import MetalKit
the game on to the iOS device.

The `SKScene` is rendered through a MetalKit while the controls
and game information overlay is rendered throuhg UIKit.
and game information overlay is rendered through UIKit.
*/
class MTKRenderer: NSObject, Renderer {
var scene: SKScene
Expand Down
18 changes: 17 additions & 1 deletion star-dash/star-dash/ViewController.swift
Expand Up @@ -43,6 +43,10 @@ class ViewController: UIViewController {
return
}

let camera = SDCameraObject()
camera.position = CGPoint(x: scene.size.width / 2, y: scene.size.height / 2)
scene.addCameraObject(camera)

let background = SDSpriteObject(imageNamed: "GameBackground")
background.position = CGPoint(x: scene.size.width / 2, y: scene.size.height / 2)
background.zPosition = -1
Expand Down Expand Up @@ -80,6 +84,18 @@ extension ViewController: SDSceneDelegate {
gameEngine?.update(by: deltaTime)
gameBridge?.syncFromEntities()

updateCameraObjectPosition(scene)
updateOverlay()
}

private func updateCameraObjectPosition(_ scene: SDScene) {
guard let playerPosition = gameEngine?.playerPosition() else {
return
}
scene.setCameraObjectXPosition(to: playerPosition.x)
}

private func updateOverlay() {
guard let gameInfo = gameEngine?.gameInfo() else {
return
}
Expand All @@ -89,7 +105,7 @@ extension ViewController: SDSceneDelegate {
))
}

func contactOccured(objectA: SDObject, objectB: SDObject, contactPoint: CGPoint) {
func contactOccurred(objectA: SDObject, objectB: SDObject, contactPoint: CGPoint) {
guard let entityA = gameBridge?.entityId(of: objectA.id),
let entityB = gameBridge?.entityId(of: objectB.id) else {
return
Expand Down
14 changes: 7 additions & 7 deletions star-dash/star-dashUITests/star_dashUITests.swift
Expand Up @@ -9,15 +9,15 @@ import XCTest

final class star_dashUITests: XCTestCase {

override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
// override func setUpWithError() throws {
// // Put setup code here. This method is called before the invocation of each test method in the class.

// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// // In UI tests it is usually best to stop immediately when a failure occurs.
// continueAfterFailure = false

// In UI tests it’s important to set the initial state - such as interface orientation -
// required for your tests before they run. The setUp method is a good place to do this.
}
// // In UI tests it’s important to set the initial state - such as interface orientation -
// // required for your tests before they run. The setUp method is a good place to do this.
// }

// override func tearDownWithError() throws {
// // Put teardown code here. This method is called after the invocation of each test method in the class.
Expand Down