SpriteKit 中可供点击的提示效果

最近做项目发现,一个模型的部分需要提示用户点击,但不知道做哪种效果。试验后发现呼吸活动光圈+点击放大效果不错。

逻辑很简单,就是在图像位置创建一个重复放大缩小的光圈,待用户点击图像时,将图像放大至120%并将光圈alpha=0,再次点击图像缩小时,将alpha恢复。

对应代码如下:

import SpriteKit
import GameplayKit

class GameScene: SKScene {
    
    private var label: SKLabelNode?
    private var spinnyNode: SKShapeNode?
    private var D: SKSpriteNode!
    private var X: SKSpriteNode!
    private var Y: SKSpriteNode!
    
    private var enlargedNode: SKSpriteNode?  // 记录当前放大的图像
    private var glowNodes: [SKSpriteNode: SKShapeNode] = [:]  // 记录每个图像的光圈效果
    
    override func didMove(to view: SKView) {
        self.backgroundColor = .gray  // 设置背景色为灰色
        
        D = self.childNode(withName: "D") as? SKSpriteNode
        X = self.childNode(withName: "X") as? SKSpriteNode
        Y = self.childNode(withName: "Y") as? SKSpriteNode
        
        // 创建光圈动画
        createGlowEffect(for: D)
        createGlowEffect(for: X)
        createGlowEffect(for: Y)
    }
    
    func createGlowEffect(for node: SKSpriteNode) {
        // 创建一个圆,作为光圈效果
        let glow = SKShapeNode(circleOfRadius: 50)
        glow.strokeColor = .white
        glow.fillColor = .clear
        glow.lineWidth = 2
        glow.alpha = 1
        glow.position = node.position
        glow.zPosition = 3  // 确保该层在图片上方
        
        // 创建一个无限循环的动画
        let pulseAction = SKAction.sequence([
            SKAction.scale(to: 1.2, duration: 1.0),
            SKAction.scale(to: 1.0, duration: 1.0)
        ])
        let pulseLoop = SKAction.repeatForever(pulseAction)
        glow.run(pulseLoop)
        
        // 添加到场景
        self.addChild(glow)
        
        // 保存光圈效果与图像的关联
        glowNodes[node] = glow
    }
    
    func hideGlowEffect(for node: SKSpriteNode) {
        if let glow = glowNodes[node] {
            glow.run(SKAction.fadeOut(withDuration: 0.2))
        }
    }
    
    func showGlowEffect(for node: SKSpriteNode) {
        if let glow = glowNodes[node] {
            glow.run(SKAction.fadeIn(withDuration: 0.2))
        }
    }

    
    func touchDown(atPoint pos: CGPoint) {
        // 判断点击的位置和图像
        let nodesAtTouch = [D, X, Y].compactMap { $0 }.filter { $0.contains(pos) }
        
        if let clickedNode = nodesAtTouch.first {
            // 如果已经有一个图像放大,则缩小它并恢复光圈提示效果
            if let enlargedNode = enlargedNode {
                enlargedNode.run(SKAction.scale(to: 1.0, duration: 0.2))
                enlargedNode.zPosition = 1  // 恢复zPosition
                showGlowEffect(for: enlargedNode)  // 恢复效果
            }
            
            // 如果点击的是未放大的图像,则放大它并隐藏光圈提示效果
            if clickedNode != enlargedNode {
                clickedNode.run(SKAction.scale(to: 1.3, duration: 0.2))
                clickedNode.zPosition = 4  // 放大时设置zPosition为4
                enlargedNode = clickedNode  // 更新当前放大的图像
                
                // 隐藏放大图像的光圈提示效果
                hideGlowEffect(for: clickedNode)
            } else {
                // 如果点击的是已经放大的图像,则缩小它并恢复光圈提示效果
                clickedNode.run(SKAction.scale(to: 1.0, duration: 0.2))
                clickedNode.zPosition = 1  // 恢复zPosition
                enlargedNode = nil  // 清空放大的图像记录
                
                // 重新显示光圈提示效果
                showGlowEffect(for: clickedNode)
            }
        } else {
            // 如果点击了空白区域,则缩小当前放大的图像并恢复光圈提示效果
            if let enlargedNode = enlargedNode {
                enlargedNode.run(SKAction.scale(to: 1.0, duration: 0.2))
                enlargedNode.zPosition = 1  // 恢复zPosition
                self.enlargedNode = nil  // 清空放大的图像记录
                
                // 重新显示光圈提示效果
                showGlowEffect(for: enlargedNode)
            }
        }
    }
    
    func touchUp(atPoint pos: CGPoint) {
        // 不再需要缩小,放大与缩小在touchDown里处理
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let label = self.label {
            label.run(SKAction.init(named: "Pulse")!, withKey: "fadeInOut")
        }
        for t in touches { self.touchDown(atPoint: t.location(in: self)) }
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 触摸结束时不做任何操作
    }
    
    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 触摸取消时不做任何操作
    }
    
    func distance(from pointA: CGPoint, to pointB: CGPoint) -> CGFloat {
        return hypot(pointA.x - pointB.x, pointA.y - pointB.y)
    }
}
代码解释
  1. 场景初始化:在 didMove(to:) 方法中,我们首先设置了场景的背景色为灰色,然后通过 childNode(withName:) 方法获取场景中的三个图像 DX 和 Y。接着,调用 createGlowEffect(for:) 方法为每个图像创建提示效果。

  2. 创建提示效果createGlowEffect(for:) 方法用于为指定的图像创建一个圆形的光圈,并为其添加一个无限循环的缩放动画,模拟提示效果。光圈的位置与图像的位置相同,并且通过 zPosition 属性确保提示层在图像上方。最后,将光圈添加到场景中,并记录提示效果与图像的关联。

  3. 隐藏和显示提示效果hideGlowEffect(for:) 和 showGlowEffect(for:) 方法分别用于隐藏和显示指定图像的提示效果。通过 SKAction.fadeOut(withDuration:) 和 SKAction.fadeIn(withDuration:) 方法实现渐变效果。

  4. 处理点击事件touchDown(atPoint:) 方法用于处理触摸事件。当玩家点击图像时,会判断点击的图像是否已经放大。如果已经放大,则缩小它并恢复提示效果;如果未放大,则放大它并隐藏提示效果。如果点击的是空白区域,则缩小当前放大的图像并恢复提示效果。

  5. 触摸事件处理touchesBegan(_:with:) 方法会在触摸开始时调用 touchDown(atPoint:) 方法处理触摸事件。touchesEnded(_:with:) 和 touchesCancelled(_:with:) 方法在触摸结束或取消时不做任何操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑-麦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值