我的元球更有机运动?

时间:2017-12-22 21:35:57

标签: javascript animation canvas visualization paperjs

我正在努力实现我的“元球”(或blob?)更有机的感觉。当它撞到墙壁时,我希望它更加“松散”,并且还能找到更好的移动方式。关于如何改进它的任何想法/建议?

例如:

  • 让它重新变形,让它变得更有趣,不知道如何完成这个
  • 当它碰到墙壁时,我想表现得更像粘液,但仍然从墙上弹开,不确定如何完成这个
  • 由于我检查了分段点数,如果它们撞到了墙上,有些部分形状在我反弹之前会关闭,不确定如何以更好的方式检查它?

我的实验基于paper.js

这是我现在的代码。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <script type="text/javascript" src="http://paperjs.org/assets/js/paper.js"></script>

  <script type="text/paperscript" canvas="canvas">

    function Ball(p, v) {
        this.point = p;
        this.vector = v;
        this.maxVec = 15;
        this.points = 8;
        this.boundOffset = [];
        this.boundOffsetBuff = [];
        this.sidePoints = [];
        this.hitPoint = null;


        this.path = new Path({
            fillColor: {
                hue: Math.random() * 360,
                saturation: 1,
                brightness: 1
            },
            blendMode: 'lighter'
        });
        this.path.selected = true;
        this.path.closed = true;

        this.maxRadius = 8;

        var center = 150;

        for (var i = 0; i < this.points; i++) {
            var delta = new Point({
                length: (this.maxRadius * 0.5) + (Math.random() * this.maxRadius * 0.5),
                angle: (360 / this.points) * i
            });
            this.path.add(center + delta);

            this.boundOffset.push(this.maxRadius);
            this.boundOffsetBuff.push(this.maxRadius);

            this.sidePoints.push(delta);
        }
        this.path.smooth();
    }

    Ball.prototype = {
        iterate: function() {
            if (this.vector.length > this.maxVec)
                this.vector.length = this.maxVec;
            this.point += this.vector;
            this.updateShape();
        },

        updateShape: function() {
            var segments = this.path.segments;

            for (var i = 0; i < this.points; i ++){
                segments[i].point = this.getSidePoint(i);
            }

            for (var i = 0; i < this.points; i ++) {
                var nextPointIndex = (i + 1) % this.points;
                var prevPointIndex = (i > 0) ? i - 1 : this.points - 1;
                var offset = this.boundOffset[i];

                offset += (this.maxRadius - offset) / 15;
                offset += ((this.boundOffset[nextPointIndex] + this.boundOffset[prevPointIndex]) / 2 - offset) / 15;

                this.boundOffsetBuff[i] = this.boundOffset[i] = offset;
            }

            this.path.smooth();
        },

        generateRandomNumber : function(min, max) {
            return Math.random() * (max - min) + min;
        },

        reactToBounds : function(){

            var bounds = {
                xMin: 0,
                xMax: 300,
                yMin: 0,
                yMax: 150
            }

            for (var i = 0; i < this.points; i ++) {
                var sidePoint = this.getSidePoint(i);
                var pre = sidePoint + this.vector;

                if(pre.x <= bounds.xMin){
                    this.hitPoint = new Point(bounds.xMin, sidePoint.y);
                    this.vector.x *= -this.generateRandomNumber(.9, 1);
                    break;
                }

                if(pre.x >= bounds.xMax){
                    this.hitPoint = new Point(bounds.xMax, sidePoint.y);
                    this.vector.x *= -this.generateRandomNumber(.9, 1);
                    break;
                }

                if(pre.y <= bounds.yMin){
                    this.hitPoint = new Point(sidePoint.x, bounds.yMin);
                    this.vector.y *= -this.generateRandomNumber(.9, 1);
                    break;
                }

                if(pre.y >= bounds.yMax){
                    this.hitPoint = new Point(sidePoint.x, bounds.yMax);
                    this.vector.y *= -this.generateRandomNumber(.9, 1);
                    break;
                }
            }

            this.calcBounds();
            this.updateBounds();

        },

        getBoundOffsetWall : function(){
            var diff = this.point - this.hitPoint;
            var angle = (diff.angle + 180) % 360;

            return this.boundOffset[Math.floor(angle / 360 * this.boundOffset.length)];
        },

        calcBounds: function() {

            for (var i = 0; i < this.points; i ++) {
                var tp = this.getSidePoint(i);
                var bLen = this.getBoundOffsetWall();
                var td = tp.getDistance(this.hitPoint);
                if (td < bLen) {
                    this.boundOffsetBuff[i] -= (bLen  - td) / 15;
                }
            }
        },

        getSidePoint: function(index) {
            return this.point + this.sidePoints[index] * this.boundOffset[index];
        },

        updateBounds: function() {
            for (var i = 0; i < this.points; i ++)
                this.boundOffset[i] = this.boundOffsetBuff[i];
        }
    };

    var balls = [];
    var numBalls = 1;
    for (var i = 0; i < numBalls; i++) {
        var position = new Point(150, 75);
        var vector = new Point({
            angle: 180 * Math.random(),
            length: .5
        });
        balls.push(new Ball(position, vector));
    }

    function onFrame() {
        for (var i = 0; i < balls.length; i++) {
            var b = balls[i];
            b.reactToBounds();
            b.iterate();
        }
    }

    </script>

</head>
<body>
    <canvas id="canvas" resize hidpi="off" style="background:black"></canvas>
</body>
</html>

由于

0 个答案:

没有答案