Unity游戏震屏效果实现

发表于2018-08-24
评论0 3.6k浏览
为了让游戏显得有真实感,开发人员会选择使用震屏效果,例如大家耳熟能详的水果忍者。在下面的文章中要和大家介绍的是震屏功能的实现,核心思路是通过正弦函数去设置场景位置偏移量,当然在开发的时候也会遇到一些问题,需要大家去解决。

1、通过正弦函数去设置场景位置偏移量,只能实现单独的上下/左右/斜线震动,怎么也无法实现其它游戏里那种效果。仔细分析之后才知道,垂直和水平方向分别分别用正弦函数和余弦函数计算偏移量。
    var xo = aX * Math.cos(angle);
    var yo = aY * Math.sin(angle);

2、提供各种定制参数,以满足不同情况的需要。比如振幅的变化(减弱/增强/增强再减弱),振动的次数和持续的时间等等。
UIShaker.prototype.setAmplitudeX = function(value) {
    this.amplitudeX = value;
    return this;
}
UIShaker.prototype.setAmplitudeY = function(value) {
    this.amplitudeY = value;
    return this;
}
UIShaker.prototype.setDuration = function(value) {
    this.duration = value;
    return this;
}
UIShaker.prototype.setTimes = function(value) {
    this.times = value;
    return this;
}
UIShaker.prototype.setAmplitudeModifier = function(value) {
    this.amplitudeModifier = value;
    return this;
}

3、我希望可以让任何一个控件都可以支持震动效果,而不光是整个场景才能震动,同时又不想修改基类UIElement。当然装饰模式是比较好的选择,不过在JS不需要那么麻烦。UIShaker去重载它所在容器的paintSelf函数就行了,UIShaker放到任何一个控件里面,启用UIShaker时就会让这个控件震动,震动完成后自动恢复原状。
UIShaker.prototype.setEnable = function(enable) {
    var parent = this.getParent();
    if(!parent || this.enable == enable) {
        return this;
    }
    if(!enable) {
        this.enable = enable;
        return this;
    }
    var me = this;
    var aX = this.amplitudeX ? this.amplitudeX : 0;
    var aY = this.amplitudeY ? this.amplitudeY : 0;
    var n = this.times ? this.times : 1;
    var duration = this.duration ? this.duration : 200;
    var startTime = Date.now();
    var oldPaintSelf = parent.paintSelf;
    var range = n * 2 * Math.PI;
    var am = this.amplitudeModifier;
    parent.paintSelf = function(canvas) {
        var dt = (Date.now() - startTime);
        if(dt < duration) {
            var factor = 1;
            var percent = dt/duration;
            var angle = range *  percent;
            var xo = aX * Math.cos(angle);
            var yo = aY * Math.sin(angle);
            if(am === "i") {
                factor = percent;
            }
            else if(am === "d") {
                factor = (1-percent);
            }
            else if(am === "i->d") {
                factor = 2 * (percent < 0.5 ? percent : (1-percent));
            }
            xo *= factor;
            yo *= factor;
            canvas.translate(xo, yo);
        }
        else {
             parent.paintSelf = oldPaintSelf;
             me.enable = false;
        }
        oldPaintSelf.call(parent, canvas);
    }
    return this;
}

在TangIDE里使用震屏控件非常方便,拖动一个震屏控件到场景中,在特定事件发生时启用它即可,整个过程不需要写一行代码。

震屏控件的完整实现请参考CanTK的源码。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引