I'm creating a board game using Spritekit. Initially all the pieces (SKSpriteNode) are hidden. They are supposed to appear after I touch them? But since they are set hidden, I can't access them when I override the touchBegan function. What am I supposed to do?
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location = touches.first!.locationInNode(self)
let touchedNode = self.nodeAtPoint(location)
if(touchedNode.name == "pieces"){
if(touchedNode.hidden == true){
touchedNode.hidden = false
}
}
}
答案 0 :(得分:2)
您正在尝试使用的是iOS8。但这已在iOS9中修复。如果您在iOS8上试用代码,您会看到它的工作原理。这是让我在iOS8上烦恼的事情之一,因为你可以点击一个隐藏的节点是没有意义的。尽管如此,你可以点击一个带有alpha 0.0的节点(也可以在iOS8上运行),但这在iOS9中也已经修复。因此将alpha设置为0.0将无效。
解决方案
您可以使用SKNode的containsPoint方法:
返回一个布尔值,指示一个点是否位于 父母的坐标系。
您案例中的父母将是您的精灵。阅读here containsPoint
方法的工作原理。基本上,containsPoint
并不关心节点是否可见,或者它是否具有父节点。它只是检查某个点(location
)是否位于父级(touchedNode
)坐标系内。以下是使用此方法的方法:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location = touches.first!.locationInNode(self)
self.enumerateChildNodesWithName("pieces") { node, stop in
if node.containsPoint(location) && node.hidden == true {
node.hidden = false
stop.memory = true
}
}
}
在这里,您要枚举所有部分(我假设self是他们的父级),如果某个节点包含触摸位置加上它是隐藏的,那么让它可见(并停止进一步的,不必要的搜索)。 / p>
<强>提示:强>
此外,请考虑使用可选绑定:
if let touch = touches.first {
let location = touch.locationInNode(self)
//do your stuff here
}
使用可选绑定是个好习惯,因为它更安全。
答案 1 :(得分:0)
到目前为止,我有另一种似乎有效的方法:
//如果你必须轮流,你可以用黑色磁盘重复whitedisk for循环。我使用.name来识别选择了哪个方块
func drawBoard() {
let numRows = 8
let numCols = 8
let x = scene?.size.width
xOffset = ((x)! - ((x)! / 9) * CGFloat(numCols))
squareSize = CGSizeMake(x!/9, x!/9)
diskSize = CGSizeMake(x!/11, x!/11)
// Draw the squares
for row in 0...numRows-1 {
for col in 0...numCols-1 {
square = SKSpriteNode(texture: SKTexture(imageNamed: "square.png"), size: squareSize!)
//row and column both start with zero, may want to start with 1 later
square!.name = "square \(col)-\(row)"
square!.userInteractionEnabled = false
square!.position = CGPointMake(CGFloat(col) * squareSize!.width + xOffset, CGFloat(row) * squareSize!.height + xOffset)
self.addChild(square!)
}
}
// Draw the White disks "hidden"
for row in 0...numRows-1 {
for col in 0...numCols-1 {
let gamePiece = SKSpriteNode(texture: SKTexture(imageNamed: "whitedisk.png"), size: diskSize!)
gamePiece.name = "whitedisk \(col)-\(row)"
gamePiece.userInteractionEnabled = false
//print("Disk Name: \(gamePiece.name)")
gamePiece.position = CGPointMake(CGFloat(col) * squareSize!.width + xOffset, CGFloat(row) * squareSize!.height + xOffset)
gamePiece.hidden = true
self.addChild(gamePiece)
}
}
}
//磁盘变量是whitedisk或blackdisk,具体取决于轮到谁 此功能在确定选择了哪个方格后显示游戏块
func placeDisk(name: String, disk: String) {
var myName = name
let theDisk = disk
myName = myName.stringByReplacingOccurrencesOfString("square", withString: theDisk)
let node = self.childNodeWithName(myName)
//print("Display: \(myName) - Node: \(String(node))")
node?.hidden = false
}
//我覆盖了touchesEND函数,但你也可以使用触摸
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let positionInScene = touch.locationInNode(self)
let name = self.nodeAtPoint(positionInScene).name
if name != nil {
print("Touched: \(name)")
placeDisk(name!, disk: "whitedisk")
}
}
}
答案 2 :(得分:0)
这是来自苹果的文档:
<块引用>半透明节点——那些 alpha 小于 1 但大于 0 的节点——仍然接收用户交互。您可以将节点的 alpha 设置为 import 'package:flutter/material.dart';
typedef CustomCallBack = Widget Function(String name);
class CustomWidget extends StatefulWidget {
final CustomCallBack myWidget;
CustomWidget({this.myWidget});
@override
_CustomWidgetState createState() => _CustomWidgetState();
}
class _CustomWidgetState extends State<CustomWidget> {
@override
Widget build(BuildContext context) {
return Container(
child: widget.myWidget(
'ASAD'), //I'm able to access the constructor here but now I get an error.
);
}
}
class Profile extends StatefulWidget {
final String name;
Profile({this.name});
@override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
@override
Widget build(BuildContext context) {
return Center(
child: Text('${widget.name}'),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomWidget(
myWidget: (name) => Profile(
name: name,
),
) //I don't want to pass the argument here
);
}
}
以使其有效透明,但仍然可以响应触摸或鼠标移动,尽管给它一个透明色具有相同的效果。
在我的棋盘游戏中,我有一个带有 leastNonzeroMagnitude
的子对象。它没有纹理,因此它变得不可见(如果你的有纹理,你可以使用 clearcolor
我猜)。
我有一个 .sks 文件,我在这个屏幕截图中制作了清晰的颜色:
我选择了一种自定义颜色并将其不透明度设置为 0。
我确实用这个代码检测到它:
leastNonzeroMagnitude
有关更多信息,请访问 Apple 官方文章的链接:Controlling User Interaction on Nodes