- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
已经有一些关于如何在 SpriteKit 中制作按钮的问题,例如 Swift Spritekit Adding Button Programaticly和 Setting up buttons in SKScene .
无论哪种方式,解决方案是制作一个带有按钮纹理的 SKSpriteNode
,然后在函数 touchesEnded
中,测试触摸是否落在按钮内-SKSpriteNode
。
然而,有趣的是,如果要让按钮成为一个子节点,例如 SKCameraNode
或另一个 SKSpriteNode
,那么此方法将不再有效。
我的问题是为什么?以及如何克服这一困境。
关于下面的帖子,这里有两个简单的 GameScene.swift 文件的替代版本。主要区别在于,在第一种情况下,sprite2
不是相机的子级,而在版本 2 中是。
注意:在 gif 中,请注意在版本 1 中,单击紫色 Sprite (sprite2
) 会导致它打印“您点击了紫色 Sprite 。”,而它会显示“蓝色 Sprite ”版本 2. 因此问题很清楚:
点击另一个 SKNode 的子节点会注册为点击最上面的父节点,而不是实际点击的节点!
新问题:如何更正此问题。
附录:在版本 2 中,sprite2
由于成为相机的子项而稍微改变了位置 - 因为它是 M.W.E.且不影响本次演示,我选择不更正。
class GameScene: SKScene {
var cam: SKCameraNode!
var sprite = SKSpriteNode(imageNamed: "sprite")
var sprite2 = SKSpriteNode(imageNamed: "sprite2")
override func didMove(to view: SKView) {
backgroundColor = SKColor.white
sprite.position = CGPoint(x: size.width/4,y: size.height/2)
sprite2.position = CGPoint(x: size.width/4 * 3,y: size.height/2)
sprite.anchorPoint = CGPoint(x:0.5, y:0.5)
// Set up the camera
cam = SKCameraNode()
self.camera = cam
cam.setScale(3.0)
cam.position = CGPoint(x: size.width/4, y: 0)
sprite.addChild(cam)
addChild(sprite); addChild(sprite2)
}
func touchDown(atPoint pos : CGPoint) {
}
func touchMoved(toPoint pos : CGPoint) {
}
func touchUp(atPoint pos : CGPoint) {
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
if sprite.contains(touchLocation) {
print("You tapped the blue sprite")
}
if sprite2.contains(touchLocation) {
print("You tapped the purple sprite")
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
class GameScene: SKScene {
var cam: SKCameraNode!
var sprite = SKSpriteNode(imageNamed: "sprite")
var sprite2 = SKSpriteNode(imageNamed: "sprite2")
override func didMove(to view: SKView) {
backgroundColor = SKColor.white
// Scale Sprites
// sprite.setScale(0.3)
sprite2.setScale(0.3)
sprite.position = CGPoint(x: size.width/4,y: size.height/2)
// sprite2.position = CGPoint(x: size.width/4 * 3,y: size.height/2)
sprite.anchorPoint = CGPoint(x:0.5, y:0.5)
// Set up the camera
cam = SKCameraNode()
self.camera = cam
cam.setScale(3.0)
cam.position = CGPoint(x: size.width/4, y: 0)
sprite.addChild(cam)
addChild(sprite); //addChild(sprite2)
cam.addChild(sprite2)
}
func touchDown(atPoint pos : CGPoint) {
}
func touchMoved(toPoint pos : CGPoint) {
}
func touchUp(atPoint pos : CGPoint) {
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
if sprite.contains(touchLocation) {
print("You tapped the blue sprite")
}
if sprite2.contains(touchLocation) {
print("You tapped the purple sprite")
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
最佳答案
我不认为你说的是真的。您可以检测来自子节点的触摸。为了演示,我只是在我的一个 SpriteKit 项目中运行了一些测试代码,我在其中检测到相机节点上的触摸
var cameraNode = SKCameraNode()
然后在 didMove(to:)
中:
addChild(cameraNode)
camera = cameraNode
camera?.position = CGPoint(x: size.width/2, y: size.height/2)
使用 touchesEnded
检测 cameraNode
上的触摸:
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let location = touch.location(in: cameraNode)
print("LocationX: \(location.x), LocationY: \(location.y)")
}
这是我打印出来的:
LocationX: -13.9129028320312, LocationY: 134.493041992188
为了进一步解释,如果您添加一个按钮作为您的 cameraNode
的子节点,您将执行如下操作:
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let location = touch.location(in: cameraNode)
// Check if tap was within button frame (assuming your buttonNode is named button and a child of cameraNode)
if button.frame.contains(location) {
// Tap was within the frame of the button
// Do whatever is necessary
}
}
进一步编辑 -
您的问题源于您请求触摸位置的节点。正如我在回答中提到的,您需要根据您检查 Sprite 框架的节点来推断触摸位置。在您的编辑中,您仅检测到 self
上的触摸,然后它将为您提供相对于您的 scene
的坐标。如果你想检测像相机节点这样的 subview 上的触摸,你需要请求相机节点内的触摸位置。根据您添加的代码,这就是我所说的内容:
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
// This will give you touch location from the camera node 'cam' NOT 'self'
let cameraLocation = touch.location(in: cam)
// This will give you touch location from the scene itself
let sceneLocation = touch.location(in: self)
if sprite.contains(sceneLocation) {
print("You tapped the blue sprite")
}
if sprite2.contains(cameraLocation) {
print("You tapped the purple sprite")
}
}
我刚试过这个,对我来说效果很好。
关于 swift 3.0 : SKSpriteNode as Button does not work when given a non-SKView parent?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41663503/
我刚刚构建了一个 SpriteKit 演示应用程序。我不在下面的代码下 if let view = self.view as! SKView? { ... } (self.vi
我正在尝试创建一个基于 SpriteKit 的游戏,并尝试在继续之前建立基本的蓝牙连接,但是我的游戏在从菜单转到 GameScene 时崩溃了,并且我收到了“无法转换值”将“UIView”键入“SKV
我有一个 SKView 正在运行以进行游戏,并希望在关卡完成(或失败)时覆盖一个较小的 SKView。当用户选择一个 Action (重启、下一级等)时,我需要关闭这个 SKView([self re
我是 SpriteKit 的新手,看到这样的代码 let skView = view as! SKView 那么这个有什么用呢?另外,我对 view 和 skView、scene 和 GameScen
如题所示,didMove(to view: SKView) 和 didMoveToView(view: SKView) 有什么区别? 我知道 didMoveToView 是方法,并且该 View 在旧
下面的代码显示 SKView,直到您将 skHeight 更改为 2050 或更高的值(例如 5000)。 1) 如何让 SKView 在 2050 或 5000 的高度上也能显示? 2) SKVie
运行我的 SwiftUI 和 SpriteKit 应用程序时,我在日志中收到以下消息: 2019-11-18 21:58:57.631912+0000 PixelBattles[2812:121580
运行我的 SwiftUI 和 SpriteKit 应用程序时,我在日志中收到以下消息: 2019-11-18 21:58:57.631912+0000 PixelBattles[2812:121580
我喜欢我的代码是明确的,所以我想删除 storyboard文件并创建 SKView以编程方式。 到目前为止我已经尝试过: 我创建了一个 SpriteKit xcode 中的游戏项目。 删除了 Stor
class MyClass: UIViewController { var playerViewController = AVPlayerViewController() var playerView
我正在尝试根据我的 userAcceleration 围绕原点旋转我的整个 SKView。虽然旋转单个 Sprite 非常容易。我无法围绕原点旋转整个场景和所有 child 。希望这是有道理的。谢谢。
我是第一次尝试 Sprite 套件。只是为了说明这一点,我已经阅读了文档,但我还不能安静地掌握创建多个按钮的想法。我可以创建按钮。它们出现在我的 View 中,但我无法将功能附加到它们以指向不同的 V
我的默认 UIView 带有两个 subview 。一个是 UIButton,另一个是 SKView。按下按钮会触发 SKView 中的发射器。如果 SKView 不与按钮重叠,则效果很好。然而,一旦
我目前正在制作一个应用程序,该应用程序首先使用 UIKit,然后过渡到 SpriteKit。我现在想从应用程序的 SpriteKit 部分返回到 UIKit。这让我想知道是否有办法使用 Swift 从
我正在尝试使用图案作为 SKScene 的背景颜色: override func didMoveToView(view: SKView) { let backgroundImage:
我在 Storyboard中放置了两个 SKView,并通过 socket 将它们连接起来。他们都在渲染正确的内容,并更新他们的 FPS 显示。我可以更改他们的相机位置,并且两者都可以正确渲染。 但是
我的项目中有这段代码用于练习 SpriteKit。但是,由于某种意外的原因,它给了我这个错误(编译正常)。 仅供引用,我的 HelloScene.h 文件中没有任何内容。我希望这没关系。除了这些代码,
我似乎在我正在开发的游戏中遇到了一个特别奇怪的问题。该游戏包含三种游戏类型,每种类型都使用SKView作为游戏的显示。前两种游戏类型(称为普通游戏和国际象棋)可以正确更改代码中的背景颜色,如下所示:
如何从 SKView 中删除场景。我已经调用了 removeFromParent,将场景设置为 nil,几乎所有我能想到的但场景仍然显示。 最佳答案 我删除场景的方式是正确的,它是 scene.vie
您好,我从主菜单 UIViewController 开始玩我创建的游戏。但是如果我想退出回到主菜单,SpriteKit 中没有 prepareForSegue 函数。 如何从场景中返回主菜单? 我正在
我是一名优秀的程序员,十分优秀!