我想实现一个简单的GKGameModel在夫特2.苹果例如Objective-C中被表达,并且包括此方法声明(所要求的协议NSCopying从GKGameModel继承):
- (id)copyWithZone:(NSZone *)zone {
AAPLBoard *copy = [[[self class] allocWithZone:zone] init];
[copy setGameModel:self];
return copy;
}
Run Code Online (Sandbox Code Playgroud)
这如何转化为Swift 2?以下在效率和忽略区域方面是否合适?
func copyWithZone(zone: NSZone) -> AnyObject {
let copy = GameModel()
// ... copy properties
return copy
}
Run Code Online (Sandbox Code Playgroud) 我的代码中包含以下代码main.swift:
let strategist = GKMinmaxStrategist()
strategist.gameModel = position
strategist.maxLookAheadDepth = 1
strategist.randomSource = nil
let move = strategist.bestMoveForActivePlayer()
Run Code Online (Sandbox Code Playgroud)
... position我的GKGameModel子类的实例在哪里Position.运行此代码后,move是nil.bestMoveForPlayer(position.activePlayer!)也导致nil(但position.activePlayer!导致一个Player对象).
然而,
let moves = position.gameModelUpdatesForPlayer(position.activePlayer!)!
Run Code Online (Sandbox Code Playgroud)
导致非空的可能移动数组.从Apple的文档(关于bestMoveForPlayer(_:)):
如果玩家无效,玩家不是游戏模型的一部分,或玩家没有有效的移动,则返回nil.
据我所知,这种情况都不是这样,但功能仍然存在nil.这可能会发生什么?
如果它可以有任何帮助,这是我的GKGameModel协议的实现:
var players: [GKGameModelPlayer]? = [Player.whitePlayer, Player.blackPlayer]
var activePlayer: GKGameModelPlayer? {
return playerToMove
}
func setGameModel(gameModel: GKGameModel) {
let position = gameModel as! Position
pieces = position.pieces …Run Code Online (Sandbox Code Playgroud) 我对Apple的新GameplayKit有一个愚蠢的问题.
我正在为我的游戏创建一个基于2D网格的节点布局.我大多喜欢它的功能GKGraphNode2D,但想以一种方式调整它.我想在遍历某种节点对时有条件地添加惩罚.换句话说,我希望一些节点以直接的方式连接,并且一些节点连接起来使得它们的遍历距离被我的app修改.
我认为继承GKGraphNode2D和覆盖-costToNode:,-estimatedCostToNode:并将完美地工作!我super有时会返回提供的值,并在其他时间为我的游戏调整它.这两个方法都是方法GKGraphNode,超类GKGraphdNode2D.
不幸的是,当我尝试这样做时,似乎-costToNode:并且-estimatedCostToNode:永远不会在我的GKGraphNode2D子类上调用它.我希望当我打电话要调用这些方法-findPathFromNode:toNode:我的GKGraph对象,它包含了一堆我的GKGraphNode2D子类的对象.
我究竟做错了什么?
以下是我的代码.
创建两个班,CheapNode和ExpensiveNode,是的子类GKGraphNode2D,如下所示:
@import UIKit;
@import GameplayKit;
@interface CheapNode : GKGraphNode2D
@end
@implementation CheapNode
- (float)estimatedCostToNode:(GKGraphNode *)node {
return 1;
}
- (float)costToNode:(GKGraphNode *)node {
return 1;
}
@end
Run Code Online (Sandbox Code Playgroud)
和
@import UIKit;
@import GameplayKit;
@interface ExpensiveNode : GKGraphNode2D
@end
@implementation ExpensiveNode
- (float)estimatedCostToNode:(GKGraphNode …Run Code Online (Sandbox Code Playgroud) 我似乎很难将我的精灵节点保持在我通过以下方式设置的地图边界内:
我有一个SKNode *enemy是围绕移动SKScene通过的目标和行为礼貌GameplayKit从iOS版9.目前的节点飘荡,避免障碍物被定义GKPolygonObstacle对象。我设置了我的位掩码,以便任何障碍物都被认为是类别wall,节点被告知要与之碰撞(AKA 不允许通过)。
在我中,didBeginContact:(SKPhysicsContact *)contact我正在处理这些碰撞。一切都按计划进行,手动移动这个敌人时没有问题。
然而,当我让敌人通过一个SKGoal *wanderGoal设置在场景中四处游荡时,问题就开始了。
// Low --> 0.5 Lowest --> 0.25
enemy.wanderGoal = [GKGoal goalToWander:low];
[enemy.agent.behavior setWeight:lowest forGoal:enemy.wanderGoal];
// Add obstacles to avoid for each of the inner map nodes
// that act as impassible areas for the enemy to pass through.
NSArray *obstacles = [SKNode obstaclesFromNodePhysicsBodies:innerMapArray];
/** This goal does not change --> enemies will ALWAYS
avoid the obstacles in …Run Code Online (Sandbox Code Playgroud) 我正在使用SpriteKit开发(或至少尝试开发)一个体面的大型实时战术游戏(类似于RTS).
我正在使用GamePlay工具包进行寻路.
最初我使用SKActions来移动路径中的精灵,但足够快我意识到这是一个很大的错误.
然后我试着用GKAgents 来实现它(这是我现在的状态)我觉得GKAgents非常原始而且不成熟他们正在遵循一些奇怪的Newton Law#1让它们永远移动(我想不出任何场景它会很有用 - 也许适用于WWDC的演示)
以及我看到他们有一些Angular速度来执行我根本不需要的旋转,并且无法真正找到如何禁用它...
除了GKBehavior给定GKGoals似乎做出一些奇怪的事情......
设置行为以避开障碍物使我的单位在他们周围慢跑...设置跟随路径目标的行为完全忽略了一切,除非maxPredictionTime它足够低......我甚至不愿意告诉当我将它们组合时会发生什么.
我觉得很破碎......
我觉得我现在有两个选择:
1)与这些代理人进行更多的斗争,并试图让他们按照我的意愿行事
2)在我的帮助下自行滚动所有的动作GKObstacleGraph和一条路径Finding(这也是我在某些方面要说的路径,这条路的路径会产生最糟糕的路径,比如"触摸那个障碍然后反向触摸"那个人然后去实际点(从一开始就可以通过直线实现)").
问题是:
这些选项中最好的是什么?
主题
我的问题是关于在结合 Apple 的框架以尊重该主题的典型模式和良好实践时更新周期的划分,因为大多数文档和示例代码尚未适应 Swift(或者至少我可以)在任何地方都找不到)。
在 GameplayKit 中管理更新周期的方法太多了,我不太确定什么是组合所有内容的好方法。
要素
首先也是最重要的:实体/组件中的每个类(GKComponent和GKEntity(子)类)都有一个update()方法,您可以重写该方法以执行每帧更新。这必须来自当前GKScene/的更新周期SKScene。
然后GKComponentSystem,您可以使用它来启动update()已添加到其中的给定类型的每个组件的方法。我明白了这一点,它非常方便。
但我也想使用状态机系统,它也有它自己的更新周期......结合所有让我感到困惑的东西。
我的情况
在我有一个在初始化时创建GKEntity的实例的子类的情况下GKStateMachine。状态机有几个状态(目前:“Spawn”、“Normal”、“Stunned”和“Death”。
现在,我正在用我的GKEntity子类创建一个大的“千篇一律”,并创建它在初始化期间要使用的所有组件。但它变得非常不切实际。例如,我有一个MovementComponent,它是GKAgent2D. 我创建了一个管理实体创建的单例,因此在创建实例后, if 循环遍历实体的所有组件并将它们添加到相关的GKComponentSystems. 单例有它自己的 update() 方法,更新将调用传递给GKComponentSystems. 我使用的一些组件不需要每帧更新,所以没有GKComponentSystem为它们创建,我根据需要手动更新它们。
如果我回到我的实体,因为我一次创建所有内容并用于GKComponentSystems更新组件,我的组件的更新方法加载了guard和if-let语句,因为我需要访问实体的状态机,检查它是否是实体可以移动的状态(正常状态)并做它的事情或逃避功能。在我看来,这并不高效:移动组件在生成、眩晕或死亡时不需要更新。
最重要的是,它使我使用GKStateMachine完全矫枉过正,因为我的更新方法是空的:GKComponentSystem无论如何,组件都会被更新。
我的想法
掉落GKComponentSystems通过我所有的实体(在某些时候也许某种他们在不同的藏品如果需要的话)完全和简单的循环,并呼吁他们的update()方法。将更新分派给状态机,状态机又会更新该状态中涉及的组件。
保持GKComponentSystems和使用状态机来处理组件,例如MovementComponent 在进入和退出正常状态时从组件系统中添加和删除。
选项 1很简单,但从长远来看,当我的结构变得更加复杂时,可能会导致问题,因为某些组件可能需要先于其他组件进行更新。让每个实体更新自己的组件会分散更新过程。
选项 2 …
我正在使用SpriteKit并在xcode中使用场景编辑器绘制场景.根据SpriteKit,我们可以使用导航图来绘制路径,我可以使用导航图绘制路径,但我无法在swift后端访问此对象.
如何从场景中访问此导航图形对象.
当我CustomComponent (GKComponent)在 Xcode SpriteKit 场景编辑器中向实体添加 a并尝试.sks使用 a加载该文件时GKScene.init,GKScene.rootNode未设置。更奇怪的是,这仅发生在 iOS 13 上,而不发生在 iOS 12 上。
我有一个小精灵套件 github 项目设置,它清楚地演示了这个问题。只需在 iOS 13 模拟器上运行该应用程序即可重现该问题。https://github.com/hdsenevi/answers-gkscene-rootnode-nil-bug
如果我CustomComponent从 SpriteKit 场景编辑器实体/精灵中删除,那么它运行良好。即:加载SKScene到GKScene.rootNode
以供参考
import UIKit
import SpriteKit
import GameplayKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Load 'GameScene.sks' as a GKScene. This provides …Run Code Online (Sandbox Code Playgroud) 我试图SCNNode围绕一个场景移动,约束到一个GKGridGraph.按照PacMan的思路,但在3D中.
我有一个ControlComponent处理我的SCNNode的运动.逻辑应该像这样......
queuedDirection属性.isMoving标志为false,则调用move()方法使用GKGridGraph评估下一步行动
3.1如果实体可以使用direction属性移动到GKGridGraphNode ,nextNode = nodeInDirection(direction)
3.2如果实体可以使用该queuedDirection属性移动到GKGridGraphNodenextNode = nodeInDirection(queuedDirection)
3.3如果实体无法移动到具有任一方向的节点,请将该isMoving标志设置为false并返回.
moveTo动作runBlock调用该move()方法的方法moveTo和runBlock操作作为序列应用于SCNNode我已经粘贴在下面的全班中.但我会解释我先遇到的问题.上述逻辑有效,但只是间歇性的.有时动画停止工作几乎immediatley,有时它运行长达一分钟.但在某些时候,由于某种原因,它只是停止工作 - setDirection()将触发,move()将触发,SCNNode将在指定方向上移动一次空间然后该move()方法停止被调用.
我并不是100%确信我当前的方法是正确的,所以我很高兴听到是否有更惯用的SceneKit/GameplayKit方法来做到这一点.
这是全班,但我认为重要的是setDirection()和move()方法.
import GameplayKit
import SceneKit
enum BRDirection {
case Up, Down, Left, Right, None
}
class ControlComponent: GKComponent {
var level: BRLevel!
var …Run Code Online (Sandbox Code Playgroud) 我试图让精灵朝着一个点移动,同时避免一些障碍.我正在使用的图是GKObstacleGraph从这个场景获得的:
为简单起见,我决定不使用圆形物理体来制作障碍物,但现在就足以使用精灵的界限了.这就是我创建图表的方式:
lazy var graph:GKObstacleGraph? =
{
guard let spaceship = self.spaceship else { return nil }
let obstacles = SKNode.obstacles(fromNodeBounds: self.rocks)
let graph = GKObstacleGraph(obstacles: obstacles, bufferRadius: Float(spaceship.size.width))
return graph
}()
Run Code Online (Sandbox Code Playgroud)
当用户点击场景的任何位置时,飞船应该通过避开障碍物开始向该位置移动:
func tap(locationInScene location:CGPoint)
{
guard let graph = self.graph else { return }
guard let spaceship = self.spaceship else { return }
let startNode = GKGraphNode2D(point: vector_float2(withPoint: spaceship.position))
let endNode = GKGraphNode2D(point: vector_float2(withPoint: location))
graph.connectUsingObstacles(node: startNode)
graph.connectUsingObstacles(node: endNode)
let path = graph.findPath(from: startNode, to: endNode) …Run Code Online (Sandbox Code Playgroud) gameplay-kit ×10
sprite-kit ×6
swift ×6
ios ×3
swift3 ×2
game-physics ×1
ios13 ×1
objective-c ×1
scenekit ×1
swift2 ×1
xcode ×1