【发布时间】:2017-07-28 23:01:05
【问题描述】:
我是 Swift SpriteKit 的新手,我想制作一个像虚拟操纵杆和两个按钮(两个节点)这样的游戏,我启用了多点触控。但是,每当我同时移动虚拟操纵杆并攻击 Spritenode 时,按钮的虚拟操纵杆似乎是锯齿状的。我如何将虚拟操纵杆的触摸与触摸攻击按钮分开
class GameScene: SKScene {
var defend : Bool = false
var attack : Bool = false
var stickMove : Bool = false
var stickEnd:Bool = false
var moveattack:Bool = false
var movedefend:Bool = false
var playermovement:Bool = true
let vj1 = SKSpriteNode(imageNamed: "vj1")
let vj2 = SKSpriteNode(imageNamed: "vj2")
let player = SKSpriteNode(imageNamed: "player")
let rotationSpeed :CGFloat = CGFloat(M_PI)
let rotationOffSet : CGFloat = -CGFloat(M_PI/2.0)
let attackvj = SKSpriteNode(imageNamed: "attackvj")
let defendvj = SKSpriteNode(imageNamed: "defendvj")
private var touchPosition: CGFloat = 0
private var targetZRotation: CGFloat = 0
override func didMove(to view: SKView) {
self.view?.isMultipleTouchEnabled = true
self.backgroundColor = SKColor.black
//position of joystick
vj1.zPosition = 1
vj1.xScale = 1.5
vj1.yScale = 1.5
self.addChild(vj1)
vj1.position = CGPoint(x: self.size.width*15/100, y:self.size.height*30/100)
vj2.zPosition = 1
vj2.xScale = 1.5
vj2.yScale = 1.5
self.addChild(vj2)
vj2.position = vj1.position
player.zPosition = 0
player.physicsBody = SKPhysicsBody(rectangleOf: player.size)
player.physicsBody!.affectedByGravity = false
player.position = CGPoint(x: self.size.width/2, y:self.size.height/2)
self.addChild(player)
attackvj.anchorPoint = CGPoint(x: 0.5, y:0.5)
attackvj.position = CGPoint(x: self.size.width*80/100, y:self.size.height*30/100)
attackvj.xScale = 2.0
attackvj.yScale = 2.0
self.addChild(attackvj)
defendvj.anchorPoint = CGPoint(x: 0.5, y:0.5)
defendvj.position = CGPoint(x: self.size.width*90/100, y:self.size.height*50/100)
defendvj.xScale = 2.0
defendvj.yScale = 2.0
self.addChild(defendvj)
vj1.alpha = 0.4
vj2.alpha = 0.4
attackvj.alpha = 0.4
defendvj.alpha = 0.4
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches){
let location = touch.location(in: self)
if vj2.contains(location){
stickEnd = false
stickMove = true
}
if defendvj.contains(location){
defend = true
}
if attackvj.contains(location){
attack = true
attackvj.xScale = 2.5
attackvj.yScale = 2.5
}
if(stickMove == true && attack == true){
moveattack = true
}
if(stickMove == true && defend == true){
movedefend = true
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches){
let location = touch.location(in: self)
let previousLocation = touch.previousLocation(in: self)
let v = CGVector(dx: location.x - vj1.position.x, dy: location.y - vj1.position.y)
print("locationsss" , location , "previouslocationsss", previousLocation)
let angle = atan2(v.dy, v.dx)
targetZRotation = angle + rotationOffSet
let length:CGFloat = vj1.frame.size.height / 2
let xDist:CGFloat = sin(angle - 1.57079633) * length
let yDist:CGFloat = cos(angle - 1.57079633) * length
if(stickMove == true){
if(vj1.frame.contains(location)){
vj2.position = location
}
else{
vj2.position = CGPoint(x: vj1.position.x - xDist, y: vj1.position.y + yDist)
}
if(attackvj.frame.contains(location)){//How am I gonna make this location in attackvj, not to influence my joystick location?
}
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if(stickMove == true && attack == false && defend == false){
let move:SKAction = SKAction.move(to: vj1.position, duration: 0.2)
move.timingMode = .easeOut
vj2.run(move)
stickEnd = true
stickMove = false
}
if(attack == true){
attack = false
attackvj.xScale = 2.0
attackvj.yScale = 2.0
moveattack = false
}
if(defend == true){
defend = false
movedefend = false
}
}
override func update(_ currentTime: TimeInterval) {
//rotation
if (stickEnd == false) {
var angularDisplacement = targetZRotation - player.zRotation
if angularDisplacement > CGFloat(M_PI) {
angularDisplacement = (angularDisplacement - CGFloat(M_PI)*2)
}
else if angularDisplacement < -CGFloat(M_PI) {
angularDisplacement = (angularDisplacement + CGFloat(M_PI)*2)
}
if abs(angularDisplacement) > rotationSpeed*(1.0/60.0){
let angularVelocity = angularDisplacement < 0 ? -rotationSpeed : rotationSpeed
player.physicsBody!.angularVelocity = angularVelocity
} else {
player.physicsBody!.angularVelocity = 0
player.zPosition = targetZRotation
}
}
else{
player.physicsBody!.angularVelocity = 0
}
//movement but use attack button to testing
if (attack == true)
{
player.position = CGPoint(x:player.position.x + cos(player.zRotation + 1.57079633),y:player.position.y + sin(player.zRotation + 1.57079633))
}
}
【问题讨论】:
-
您遇到的问题是您没有将触摸与各种控件的行为联系起来。您可以在 touchesBegan 和 touchesMoved 调用之间存储 UITouch 对象,以便您可以跟踪哪个触摸是哪个,并分别理解它们。使用 touchesBegan 开始跟踪各种类型的触摸,并使用 touchesMoved 作为信号,表明您正在跟踪的触摸之一可能发生了变化。
-
一个(也许)更好的方法是为您的各种按钮设置单独的“触摸板”,并让它们将游戏事件向上传递到您的游戏逻辑,而不是尝试制作一个尝试将所有可能的 UI 元素考虑在内的大项目。这样,您可以按照代码示例中显示的方式构建您的 UI 元素,但多个上下文之间不会有串扰来混淆事物。
-
嗨,cc,非常感谢您对这个主题的回应,我已经开始在网上搜索并反复试验,但仍然没有令人满意的结果。
-
嗨,cc,我非常感谢您对这个主题的回应,我已经开始在网上搜索并反复试验,但仍然没有令人满意的输出。当我按住操纵杆并四处移动+按住攻击按钮并四处移动时,操纵杆似乎受到按钮的“新”触摸位置的影响。有没有办法为每个按钮单独触发触摸?
-
元,我在下面添加了一个答案,应该说明这个过程。基本上,它是关于跟踪哪个触摸与哪个功能相关 - 这是您缺少的部分。
标签: swift3 sprite-kit multi-touch touchesmoved