gpt4 book ai didi

ios - 使用 GKComponent 制作可重复使用的防护罩

转载 作者:行者123 更新时间:2023-11-29 00:11:00 25 4
gpt4 key购买 nike

我正在尝试制作一个简单的游戏:屏幕底部的 spaceship 射击从屏幕顶部“坠落”的小行星。

我正在学习ECS和GameplayKit,一直在尝试把盾牌变成一个组件。我严重依赖 Apple 的 DemoBots 示例应用程序,并从示例代码中提取了 PhysicsComponentColliderTypeContactNotifiableType

护盾需要渲染与其相关的 Assets (一个用于全护盾,一个用于半护盾),一个与船不同的物理体,因为它的半径明显大于船,并跟踪它的状态。为此,我写道:

final class ShieldComponent: GKComponent {
enum ShieldLevel: Int {
case full = 0, half, none
}

var currentShieldLevel: ShieldLevel = .full {
didSet {
switch currentShieldLevel {
case .full:
node.isHidden = false
node.texture = SKTexture(image: #imageLiteral(resourceName: "shield"))
case .half:
node.isHidden = false
node.texture = SKTexture(image: #imageLiteral(resourceName: "damagedShield"))
case .none:
node.isHidden = true
}
}
}

let node: SKSpriteNode

override init() {
node = SKSpriteNode(imageNamed: "shield")
super.init()

node.physicsBody = {
let physicsBody = SKPhysicsBody(circleOfRadius: node.frame.size.width / 2)
physicsBody.pinned = true
physicsBody.allowsRotation = false
physicsBody.affectedByGravity = false

ColliderType.definedCollisions[.shield] = [
.obstacle,
.powerUp
]

physicsBody.categoryBitMask = ColliderType.shield.rawValue
physicsBody.contactTestBitMask = ColliderType.obstacle.rawValue
physicsBody.collisionBitMask = ColliderType.obstacle.rawValue
return physicsBody
}()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func loseShields() {
if let newShieldLevel = ShieldLevel(rawValue: self.currentShieldLevel.rawValue + 1) {
self.currentShieldLevel = newShieldLevel
}
}

func restoreShields() {
self.currentShieldLevel = .full
}
}

在我的 Ship 初始值设定项中,我这样做:

    let shieldComponent = ShieldComponent()
renderComponent.node.addChild(shieldComponent.node)

如果我可以重用 DemoBots 中的 RenderComponentPhysicsComponent 我的飞船和小行星 GKEntity 子类,那就太好了,但是组件不能有组件。我已将 ShieldComponent 设为 ContactNotifiableType,但因为盾牌节点实际上并不属于船舶实体。

我知道我显然犯了这个错误,但我不知道如何纠正这个问题。我希望得到一个如何制作屏蔽组件的示例。

最佳答案

您必须了解码件只能处理一种行为。所以 git 去掉 init() 函数中的物理代码,而是构建一个类似于 DemoBots 中的物理组件。

根据您的喜好调整渲染组件。使用 DemoBots 代码的问题在于它并不完全适合。所以我们来调整一下

class RenderComponent: GKComponent {
// MARK: Properties

// The `RenderComponent` vends a node allowing an entity to be rendered in a scene.
@objc let node = SKNode()

var sprite = SKSpriteNode

// init
init(imageNamed name: String) {
self.sprite = SKSpriteNode(imageNamed: name)
}
// MARK: GKComponent

override func didAddToEntity() {
node.entity = entity
}

override func willRemoveFromEntity() {
node.entity = nil
}

final class ShieldComponent: GKComponent {


var node : SKSpriteNode
//add reference to ship entity
weak var ship: Ship?


enum ShieldLevel: Int {
case full = 0, half, none
}

var currentShieldLevel: ShieldLevel = .full {
didSet {
switch currentShieldLevel {
case .full:
node.isHidden = false
node.texture = SKTexture(image: #imageLiteral(resourceName: "shield"))
case .half:
node.isHidden = false
node.texture = SKTexture(image: #imageLiteral(resourceName: "damagedShield"))
case .none:
node.isHidden = true
}
}
}

// Grab the visual component from the entity. Unwrap it with a Guard. If the Entity doesnt have the component you get an error.
var visualComponentRef : RenderComponent {
guard let renderComponent = ship?.component(ofType: RenderComponent.self) else {
fatalError("entity must have a render component")
}
}

override init(shipEntity ship: Ship) {
let visualComponent = RenderComponent(imageNamed: "imageName")
node = visualComponent.sprite
self.ship = ship
super.init()

// get rid of this. Use a Physics Component for this, Kep your components to one behaviour only. Make them as dumb as possible.
// node.physicsBody = {
// let physicsBody = SKPhysicsBody(circleOfRadius: node.frame.size.width / 2)
// physicsBody.pinned = true
// physicsBody.allowsRotation = false
// physicsBody.affectedByGravity = false
//
// ColliderType.definedCollisions[.shield] = [
// .obstacle,
// .powerUp
// ]
//
// physicsBody.categoryBitMask = ColliderType.shield.rawValue
// physicsBody.contactTestBitMask = ColliderType.obstacle.rawValue
// physicsBody.collisionBitMask = ColliderType.obstacle.rawValue
// return physicsBody
// }()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func loseShields() {
if let newShieldLevel = ShieldLevel(rawValue: self.currentShieldLevel.rawValue + 1) {
self.currentShieldLevel = newShieldLevel
}
}

func restoreShields() {
self.currentShieldLevel = .full
}

};

请务必查看我如何更改组件与实体的交互。您可以创建一个引用对象来直接Ship实体。或者您可以检查天气,ShieldComponent 是否具有带有 entity? 属性的 entity。 (注意。它是可选的,因此请打开它。

获得实体引用后,您可以在其中搜索其他组件并检索 using component(ofType:_) 属性。例如 ship?.component(ofType: RenderComponent.self)

除此之外,我认为你有一个不错的护盾组件

关于ios - 使用 GKComponent 制作可重复使用的防护罩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46472328/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com