zoukankan      html  css  js  c++  java
  • 游戏震屏效果的实现

    震屏效果在游戏里使用相当广泛的,特别在被物体撞击的时候,震屏效果能大大提高游戏的真实感。我开始以为实现震屏效果很简单,通过正弦函数去设置场景位置偏移量即可,但真正去做时发现还是有一点点挑战。

    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的源码。

  • 相关阅读:
    Hibernate
    Redis的学习
    Redis的人门以及使用
    Win32 配置文件用法
    Using virtual lists
    windows log
    Win查询注册表获取CPU与内存参数
    MFC 多线程及线程同步
    使用Custom Draw优雅的实现ListCtrl的重绘
    MFC工具栏设计
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167332.html
Copyright © 2011-2022 走看看