我对iOS,Objective C和使用Xcode都很陌生.我只做了一个简单的新闻类型的应用程序,但现在我想创建一个我在另一个平台上发布的游戏.
基本上,我有一个对象随机出现然后淡出,目的是点击对象使其消失.
然而,即使我设置,我似乎无法点击该对象 mySKSpriteNode.userInteractionEnabled = YES;
这是我的touchesBegan方法中的内容:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
NSLog(@"Something was touched");
UITouch *touch = [touches anyObject];
NSLog(@"%@", touch);
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if(node == mySKSpriteNode)
[node runAction:[SKAction fadeOutWithDuration:0]];
}
Run Code Online (Sandbox Code Playgroud)
在我的日志中,当我点击屏幕时(不是我有对象的地方),我得到了这个:
2014-02-17 23:18:30.870 BubbleChallenge[48541:70b] Something was touched
2014-02-17 23:18:30.875 BubbleChallenge[48541:70b] <UITouch: 0x1130ea530> phase: Began tap count: 1 window: <UIWindow: 0x109c2ab60; frame = (0 0; 320 568); autoresize = W+H; gestureRecognizers = …Run Code Online (Sandbox Code Playgroud) 当兄弟姐妹重叠时,错误 - 命中测试无法正常工作:
场景中有2个重叠节点具有相同的父节点(即兄弟节点)
最顶层的节点具有
userInteractionEnabled = NO另一个节点userInteractionEnabled = YES.如果触摸了重叠,则在最顶层节点被命中测试并且失败(因为
userInteractionEnabled = NO)之后,而不是底部节点是下一个被命中测试的节点,它被跳过并且2个兄弟节点的父节点被命中测试.应该发生的是,下一个兄弟(底部节点)是经过重击测试而不是命中测试跳到父节点.
根据Sprite Kit文档:
"在场景中,当Sprite Kit处理触摸或鼠标事件时,它会遍历场景以找到想要接受事件的最近节点.如果该节点不想要事件,Sprite Kit会检查下一个最近的节点,所以处理命中测试的顺序基本上与绘制顺序相反.对于在命中测试期间要考虑的节点,其userInteractionEnabled属性必须设置为YES.除场景外的任何节点的默认值为NO节点."
这是一个错误,因为节点的兄弟姐妹在他们的父母之前呈现 - 兄弟姐妹应该是下一个被测试的,而不是它的父母.此外,如果一个节点有userInteractionEnabled = NO,那么肯定它应该是'透明'的关于命中测试 - 但是这不是因为它导致行为的改变,因为在测试中跳过了一个节点.
我在网上搜索过,但找不到任何人报告或发布此错误.我应该报告这个吗?
然后我在这里发布这个的原因是因为我想要一个关于这个bug的'修复'的建议(即建议在某处实现某些代码,以便SpriteKit以'预期'方式工作-testing)
复制错误:
使用在Xcode中启动新的"游戏"项目时提供的"Hello World"模板(它具有"Hello World"并在您单击时添加火箭精灵).
可选:[我还从项目中删除了火箭精灵图像,因为
X当找不到图像时出现的矩形更容易用于调试,可视化]将SKSpriteNode添加到场景中
userInteractionEnabled = YES(我将从现在开始将其称为节点A).运行代码.
您会注意到,当您单击节点A时,不会生成火箭精灵.(自命中测试成功后应该停止的预期行为 - 它在节点A上成功时停止)
但是,如果你在节点A旁边产生一些火箭,然后点击节点A和火箭重叠的地方,那么就有可能在节点A上产生另一个火箭 - 但这不可能.这意味着在最顶层节点(
userInteractionEnabled = NO默认情况下为火箭)上的命中测试失败后,它不再测试下一个节点A,而是测试火箭的父节点,而不是场景.
注意:我使用的是Xcode 7.3.1,Swift,iOS - 我还没有测试过这个bug是否具有通用性.
额外的细节:我做了一些额外的调试(上面的复制有轻微的复杂性),并确定命中测试后来发送给父母,因此不一定是场景.
我注意到SKNode方法children和childNodeWithName:名称暗示只返回查询节点正下方的子节点的结果.ie [root children];将返回NSArray包含节点的内容@[CUBE1, CUBE2, CUBE3].
在下图中,我想从ROOT(SKScene)级别下载到SPHERE2,以便我可以快速访问子节点.我希望这[root childNodeWithName:@"SPHERE2"];将遍历整个层次结构并返回指向SPHERE2的指针

我的问题:是否有一些我错过的东西让我跳到指定点的节点树(即使用节点名称)
我可以使用属性来存储指向树中重要位置的指针,然后使用它们来访问和处理任何子节点,这是一个选项......
我已经开发了相当完善的SpriteKit游戏,添加了一些代码来向场景中添加一个新的SKSpriteNode(与我在代码中的其他几十个地方相同,但由于某种原因,这次它只是忽略了我已经为节点设置了位置,我通过显式.position = CGPointMake(x,y)尝试了它并尝试了[node setPosition:CGPointMake(x,y)]
既不工作......节点确实被添加到场景中,但总是在0,0,无论我做什么,都检查了x和y以确保它们是有效的并且在场景的范围内,并且尝试过使用显式浮点数等,无论我做什么,这个节点总是显示在0,0并且它完全没有意义.我正在做的事情与我在游戏过程中与其他几十个节点做的一样,但无论我做什么,这个节点都不会出现在0,0以外的地方:
int width = 64;
SKSpriteNode *node = [[SKSpriteNode alloc] initWithColor:[SKColor grayColor] size:CGSizeMake(width,25)];
node.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:node.size];
node.physicsBody.dynamic = NO;
node.physicsBody.categoryBitMask=nodeCategory;
node.name=@"node";
node.position = CGPointMake(200,250);
//Have also tried [node setPosition:CGPointMake(200,250);
[self addChild:node];
Run Code Online (Sandbox Code Playgroud)
我在这里完全不知所措,我已经尝试将.0添加到CGPointMake的输入中以确保它们作为浮点数处理没有...无论我对此节点做什么,当它被添加到场景时它总是默认为0,0位置,我很沮丧,我正在添加各种节点而没有发生事故,只是关于这个节点添加的东西只是不起作用,无法弄清楚有什么不同或为什么.
我有一个SKSpriteNode,它是滚动背景(即孩子)的父级.SKSpriteNode不会自动移动,它只会随着滚动背景一起移动.在背景移动时找到SKSpriteNode的绝对位置的最佳方法是什么.
我创建了一个非常简单的示例代码,只有一个场景,一个精灵节点20x20px,屏幕上的点0.0.当我调用scene.physicsWorld bodyAtPoint它时,即使在例如34x34点,也会返回此节点.但在35x35点它会返回null.所以基本上所有从0px到34px的点都返回此节点,从35px开始,它不再返回它.任何想法可能是什么原因,如果精灵明显以20px 20px结束?可以看到相同的行为bodyInRect.
以下是示例代码:
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
self.physicsWorld.gravity = CGVectorMake(0, 0);
SKSpriteNode *node = [[SKSpriteNode alloc] initWithColor:[UIColor whiteColor] size:CGSizeMake(20, 20)];
node.position = CGPointMake(10, 10);
node.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(20, 20)];
[self addChild:node];
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
if([self.physicsWorld bodyAtPoint:location])
{
NSLog(@"Detected at …Run Code Online (Sandbox Code Playgroud) 我想知道如何在屏幕外删除我的 SKNode 以帮助我的游戏运行更流畅。
非常感谢
这是我的设置,使用Sprite Kit.首先,我在SKScene中创建一个简单的精灵节点,如下所示:
let block = SKSpriteNode(color: UIColor.redColor(), size: CGSizeMake(90, 160))
block.zPosition = 2
block.shadowCastBitMask = 1
addChild(block)
Run Code Online (Sandbox Code Playgroud)
然后向场景添加一个灯光节点:
let light = SKLightNode()
light.categoryBitMask = 1
light.falloff = 1
addChild(light)
Run Code Online (Sandbox Code Playgroud)
果然,块现在投下一个漂亮的小阴影:

现在我通过操纵其alpha值来淡化块,例如通过运行一个动作:
let fadeOut = SKAction.fadeAlphaTo(0.0, duration: 5.0)
block.runAction(fadeOut)
Run Code Online (Sandbox Code Playgroud)
这是一个尴尬的情况:当块变得越来越半透明时,阴影保持完全相同.这就是它在行动结束前的一刻:

一旦alpha完全降至0.0,阴影就会从一帧到下一帧突然消失.
这将是多漂亮,但有阴影慢慢的越来越弱,作为对象铸造它变得越来越透明.
使用Sprite Kit可以达到这样的效果吗?如果是这样,你会怎么做呢?
我想使用多个.sks文件存储一些复杂的SKNode层次结构,例如游戏菜单。我有一个想要在整个游戏中保持移动的物体的背景,因此呈现不同的SKScenes并不能达到我想要的效果。我被限制在一个场景中,但是我仍然想尽可能地将代码与图稿分开,试图将所有内容压缩到一个.sks文件中很快就会变得拥挤!
因此,我想拥有多个.sks文件,每个文件存储一个不同的菜单:titleMenu,getReadyMenu,pauseMenu,gameOverMenu,每个菜单的所有元素都是一个空SKNode的后代。
我设法加载了文件,将SKNode缓存在本地变量中,并在屏幕上显示了它,但是当我单击菜单上的按钮时,当我单击菜单上的按钮之外时,永远不会调用touchesBegan函数。这是正常的响应者链功能。很困惑。
我确信我的解决方案是如此复杂,以至于仅询问某人是否可以发布一个示例,就可以从.sks文件中仅捕获一个SKNode(和子级),而无需呈现一个新场景,这将更加简单。
因此,有人可以在Swift中发布一个示例吗?
这个问题展示了如何找到属于某个类的 SKNode 的所有子节点,但是如果我们想要属于某个类的所有后代(例如,孙子节点)呢?
在 SpriteKit 中是否有一种本机方法可以做到这一点,还是从上述问题中创建递归形式的唯一选择?
SKNode 文档突出显示了一个搜索功能,可以让您找到具有特定名称的后代,但是有没有办法按类而不是名称过滤后代?如果可以避免,我们不想为节点分配名称。
我们正在使用 Swift 3。
sknode ×10
sprite-kit ×10
ios ×6
swift ×4
ios7 ×2
objective-c ×2
skspritenode ×2
hittest ×1
position ×1
removechild ×1
shadow ×1
skscene ×1
touch ×1