移相器:如何使用0到3的简单计时器

时间:2019-02-11 12:19:35

标签: javascript timer phaser-framework game-development

我正在使用以下代码(为了使代码更具可读性,这是一个简化的代码段)

import UIKit
import PlaygroundSupport

enum CircleProgressionViewAnimationState {
    case start, firstAnimation, secondAnimation, progress, stop
}

class CircleProgressionView : UIView {
    static let offset: CGFloat = 10.0
    private var path : UIBezierPath? {
        didSet {
            circleLayer.path = path?.cgPath
        }
    }

    private var state : CircleProgressionViewAnimationState {
        didSet {
            observe(change: state)
        }
    }
    private var progressionPath : UIBezierPath?
    var circleLayerContainer = CALayer()

    var circleLayer : CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.lineWidth = 4
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = #colorLiteral(red: 0.6666666865, green: 0.6666666865, blue: 0.6666666865, alpha: 1)

        return shapeLayer
    }()

    var circleProgressLayer : CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.lineWidth = 15
        shapeLayer.cornerRadius = 2
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
        shapeLayer.lineCap = CAShapeLayerLineCap.round
        return shapeLayer
    }()

    override init(frame: CGRect) {
        state = .stop
        super.init(frame:frame)
        initLayerValues()
    }

    required init?(coder aDecoder: NSCoder) {
        state = .stop
        super.init(coder:aDecoder)
        initLayerValues()
    }



    private func initLayerValues() {
        let side = min(frame.width, frame.height)
        circleLayerContainer.frame = CGRect(x: 0, y: 0, width: side, height: side)
        let offset = CircleProgressionView.offset
        let bezierSide = side - (offset * 2)
        let bezierRect = CGRect(x:offset,
                                y:offset,
                                width: bezierSide,
                                height:bezierSide)
        path = UIBezierPath(roundedRect: bezierRect,
                            cornerRadius: CGFloat(bezierSide / 2))
        circleLayerContainer.addSublayer(circleLayer)
        layer.addSublayer(circleLayerContainer)
        layer.addSublayer(circleProgressLayer)
    }

    func setProgressionPath(_ progressionInPercent: CGFloat) {
        let progression = progressionInPercent / 100 * (360)
        let rad = (progression + 270) * CGFloat.pi / 180
        let start = 270 *  CGFloat.pi / 180
        let offset = CircleProgressionView.offset

        progressionPath = UIBezierPath(arcCenter: CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2),
                radius: (self.frame.size.height - offset - circleProgressLayer.lineWidth / 2) / 2,
                startAngle: start,
                endAngle: rad,
                clockwise: true)
    }

    func observe(change: CircleProgressionViewAnimationState) {
        print(change)
        switch change {
        case .firstAnimation:
             fullAnimate { self.state = .secondAnimation }
            break
       case .secondAnimation:
             emptyAnimate { self.state = .firstAnimation }
            break
        case .start, .progress, .stop: break
        }
    }

    func animate(loop: Bool) {

        var completion : ()->Void = {}
        if loop {
            state = .start
            completion = { self.state = .secondAnimation }
        }
        fullAnimate(completion: completion)
    }



    func fullAnimate(completion: @escaping ()->Void) {
        self.state = .progress
        circleProgressLayer.removeAllAnimations()
        circleProgressLayer.path
        CATransaction.begin()
         circleProgressLayer.path = progressionPath?.cgPath
        CATransaction.setCompletionBlock{ completion() }
        let animation : CABasicAnimation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.strokeEnd))

        animation.fromValue = 0.0
        animation.toValue = 1.0

        animation.duration = 2

       animation.timingFunction =  CAMediaTimingFunction(name:
            CAMediaTimingFunctionName.easeInEaseOut)

        circleProgressLayer.add(animation, forKey: #keyPath(CAShapeLayer.strokeEnd))
        CATransaction.commit()


    }

    func emptyAnimate(completion: @escaping ()->Void) {
        self.state = .progress
        circleProgressLayer.removeAllAnimations()
        CATransaction.begin()

        circleProgressLayer.path = progressionPath?.reversing().cgPath
        CATransaction.setCompletionBlock{ completion() }
        let animation : CABasicAnimation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.strokeEnd))

        animation.fromValue = 1.0
        animation.toValue = 0.0

        animation.duration = 2
        animation.timingFunction =  CAMediaTimingFunction(name:
            CAMediaTimingFunctionName.easeInEaseOut)

        circleProgressLayer.add(animation, forKey: #keyPath(CAShapeLayer.strokeEnd))
        CATransaction.commit()
    }
}

var container : UIView = {
    let frame = CGRect(x: 0, y: 0, width: 300, height: 300)
    let view = UIView(frame: frame)
    view.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
    return view
}()

let circle = CircleProgressionView(frame: container.frame)
PlaygroundPage.current.liveView = container
circle.setProgressionPath(100)
container.addSubview(circle)
circle.animate(loop: true)
  • 实际情况:

当玩家击中炸弹时:玩家死亡;游戏结束

  • 期望的举止:

当玩家击中炸弹时:炸弹等待3秒钟然后爆炸!如果玩家离得太近,他会死。 但是即使在论坛上阅读了很多示例之后,我也很难使用计时器。我是有关Phaser的新手,所以到目前为止我还没有成功。

任何帮助将不胜感激,在此先感谢您!

2 个答案:

答案 0 :(得分:3)

假设您正在使用Phaser 3,则可以使用这些计时器。

  1. delayedCall方法,它更短。

delayedCall(delay, callback, args, callbackScope)

因此,您将执行以下操作。

this.time.delayedCall(2000, onEvent, null, this);

  1. addEvent方法

addEvent(config) Docs for config

this.time.addEvent({ delay: 2000, callback: onEvent, callbackScope: this });

在文档here中找到这些方法。

查找计时器事件here的示例。


您可以做的另一件事是,如果有一个补间播放3秒钟(如果您要补间炸弹或对其设置动画3秒钟)。您可以在其上附加onComplete回调。因此,在Tween克服之后,onComplete回调将被执行。

答案 1 :(得分:1)

如果要将hitTnt()逻辑的执行时间延迟3秒,可以将其包装在setTimeout()调用中,如下所示:

function hitTnt(player, boxes) {
    setTimeout(() => {
        this.physics.pause();
        player.setTint(0xff0000);
        player.anims.play('default');
        gameOver = true;
        textGameOver.setText('GAME OVER');
    }, 3000);
}