js实现数字自由落体弹跳canvas动画效果代码

代码语言:html

所属分类:动画

代码描述:js实现数字自由落体弹跳canvas动画效果代码

代码标签: 自由落体 弹跳 canvas 动画 效果

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<html>
<head>
    <style>
        html, body {
            touch-action: none;
            content-zooming: none;
            margin: 0;
            padding: 0;
            background: #333;
            position: absolute;
            width: 100%;
            height: 100%;
        }

        #screen {
            width: 100%;
            height: 100%;
            margin: auto auto;
            position: fixed;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            background: #000;
            cursor: pointer;
        }
    </style>

</head>
<body>
    <canvas id="screen" width="642" height="679"></canvas><script>
        ! function () {
            "use strict";

            /* ==== screen setup ==== */

            var screen = {
                elem: document.getElementById("screen"),
                width: 0,
                height: 0,
                top: 0,
                left: 0,
                resize: function () {
                    var o = screen.elem;
                    screen.width = o.offsetWidth;
                    screen.height = o.offsetHeight;
                    for (screen.left = 0, screen.top = 0; o != null; o = o.offsetParent) {
                        screen.left += o.offsetLeft;
                        screen.top += o.offsetTop;
                    }
                    screen.elem.width = screen.width;
                    screen.elem.height = screen.height;
                    if (PHY2D) {
                        PHY2D.deleteStatic();
                        PHY2D.rectangle(screen.width / 2, screen.height + 50, screen.width, 100, 0, 0);
                        PHY2D.rectangle(screen.width / 2, -screen.height * 2, screen.width, 100, 0, 0);
                        PHY2D.rectangle(-50, 0, 100, screen.height * 4, 0, 0);
                        PHY2D.rectangle(screen.width + 50, 0, 100, screen.height * 4, 0, 0);
                    }
                }
            }

            screen.elem.onselectstart = function () {
                return false;
            }
            screen.elem.ondrag = function () {
                return false;
            }
            var ctx = screen.elem.getContext("2d");
            window.addEventListener('resize', screen.resize, false);

            /* ==== pointer setup ==== */

            var pointer = {
                pos:
                {
                    x: 0,
                    y: 0
                },
                active: false,
                down: function (e, touch) {
                    e.preventDefault();
                    var p = touch ? e.touches[0]: e;
                    (!touch && document.setCapture) && document.setCapture();
                    this.pos.x = p.clientX - screen.left;
                    this.pos.y = p.clientY - screen.top;
                    this.active = true;
                },
                up: function (e, touch) {
                    e.preventDefault();
                    (!touch && document.releaseCapture) && document.releaseCapture();
                    this.active = false;
                },
                move: function (e, touch) {
                    e.preventDefault();
                    var p = touch ? e.touches[0]: e;
                    if (this.active) {
                        this.pos.x = p.clientX - screen.left;
                        this.pos.y = p.clientY - screen.top;
                    }
                }
            }

            if ('ontouchstart' in window) {
                screen.elem.ontouchstart = function (e) {
                    pointer.down(e, true);
                }.bind(pointer);
                screen.elem.ontouchmove = function (e) {
                    pointer.move(e, true);
                }.bind(pointer);
                screen.elem.ontouchend = function (e) {
                    pointer.up(e, true);
                }.bind(pointer);
                screen.elem.ontouchcancel = function (e) {
                    pointer.up(e, true);
                }.bind(pointer);
            }
            document.addEventListener("mousedown", function (e) {
                pointer.down(e, false);
            }.bind(pointer), true);
            document.addEventListener("mousemove", function (e) {
                pointer.move(e, false);
            }.bind(pointer), true);
            document.addEventListener("mouseup", function (e) {
                pointer.up(e, false);
            }.bind(pointer), true);

            /* ==== vector 2D library ==== */

            function Vector(x, y) {
                this.x = x || 0.0;
                this.y = y || 0.0;
            }
            Vector.prototype = {
                set: function (x, y) {
                    this.x = x;
                    this.y = y;
                    return this;
                },
                dot: function (v) {
                    return this.x * v.x + this.y * v.y;
                },
                lenSqr: function () {
                    return this.x * this.x + this.y * this.y;
                },
                transform: function (v, m) {
                    this.x = m.cos * v.x - m.sin * v.y + m.pos.x;
                    this.y = m.sin * v.x + m.cos * v.y + m.pos.y;
                    return this;
                },
                rotate: function (v, m) {
                    this.x = m.cos * v.x - m.sin * v.y;
                    this.y = m.sin * v.x + m.cos * v.y;
                    return this;
                },
                normal: function (a, b) {
                    var x = a.x - b.x,
                    y = a.y - b.y,
                    len = Math.sqrt(x * x + y * y);
                    this.x = -y / len;
                    this.y = x / len;
                    return this;
                },
                project: function (a, b, n) {
                    var x = a.x - b.x,
                    y = a.y - b.y,
                    len = Math.sqrt(x * x + y * y);
                    return (-y / len) * n.x + (x / len) * n.y;
                },
                addScale: function (v1, v2, s) {
                    this.x = v1.x + (v2.x * s);
                    this.y = v1.y + (v2.y * s);
                    return this;
                },
                subScale: function (v1, v2, s) {
                    this.x = v1.x - (v2.x * s);
                    this.y = v1.y - (v2.y * s);
                    return this;
                },
                add: function (v1, v2) {
                    this.x = v1.x + v2.x;
                    this.y = v1.y + v2.y;
                    return this;
                },
                sub: function (v1, v2) {
                    this.x = v1.x - v2.x;
                    this.y = v1.y - v2.y;
                    return this;
                },
                scale: function (v1, s) {
                    this.x = v1.x * s;
                    this.y = v1.y * s;
                    return this;
                },
                perp: function () {
                    var x = this.x;
                    this.x = -this.y;
                    this.y = x;
                    return this;
                },
                inv: function (v1) {
                    this.x = -v1.x;
                    this.y = -v1.y;
                    return this;
                },
                clamp: function (v, min, max) {
                    if (v > max) v = max;
                    else if (v < min) v = min;
                    return v;
                },
                rotateIntoSpaceOf: function (a, m) {
                    var dx = -a.x,
                    dy = -a.y;
                    this.x = dx * m.cos + dy * m.sin;
                    this.y = dx * -m.sin + dy * m.cos;
                    return this;
                },

                // SIMD Array vectors

                array: function (n, values) {
                    var array = new Array(n);
                    array.min = new Vector();
                    array.max = new Vector();
                    for (var i = 0; i < n; i++) {
                        array[i] = new Vector(
                            values ? values[i * 2 + 0]: 0.0,
                            values ? values[i * 2 + 1]: 0.0
                        );
                    }
                    array.transform = function (v, m) {
                        for (var i = 0, len = this.length; i < len; i++) {
                            var vi = v[i],
                            elem = this[i];
                            var x = m.cos * vi.x - m.sin * vi.y + m.pos.x;
                            var y = m.sin * vi.x + m.cos * vi.y + m.pos.y;
                            if (x < this.min.x) this.min.x = x;
                            if (y < this.min.y) this.min.y = y;
                            if (x > this.max.x) this.max.x = x;
                            if (y > this.max.y) this.max.y = y;
                            elem.x = x;
                            elem.y = y;
                        }
                        return this;
                    }
                    array.rotate = function (v, m) {
                        for (var i = 0, len = this.length; i < len; i++) {
                            var vi = v[i],
                            elem = this[i];
                            elem.x = m.cos * vi.x - m.sin * vi.y;
                            elem.y = m.sin * vi.x + m.cos * vi.y;
                        }
                        return this;
                    }
                    array.resetMinmax = function () {
                        this.min.x = 100000.0;
                        this.min.y = 100000.0;
                        this.max.x = -100000.0;
                        this.max.y = -100000.0;
                    }
                    array.normal = function (points) {
                        for (var i = 0; i < this.length; i++) {
                            this[i].normal(
                                points[(i + 1) % this.length],
                                points[i]
                            );
                        }
                        return this;
                    }
                    return array;
                }
            }

            /* ==== Matrix container ==== */

            function Matrix() {
                this.cos = 0.0;
                this.sin = 0.0;
                this.pos = new Vector();
                this.ang = 0.0;
            }

            Matrix.prototype = {
                set: function (a, x, y, w, h) {
                    this.cos = Math.cos(a);
                    this.sin = Math.sin(a);
                    this.ang = a;
                    this.pos.x = x;
                    this.pos.y = y;
                    this.w = w;
                    this.h = h;
                    return this;
                },
                copy: function (matrix) {
                    this.cos = matrix.cos;
                    this.sin = matrix.sin;
                    this.ang = matrix.ang;
                    this.pos.x = matrix.pos.x;
                    this.pos.y = matrix.pos.y;
                    return this;
                },
                integrate: function (va, vx, vy, kTimeStep) {
                    this.pos.x += vx * kTimeStep;
                    this.pos.y += vy * kTimeStep;
                    this.ang += va * kTimeStep;
                    this.cos = Math.cos(this.ang);
                    this.sin = Math.sin(this.ang);
                    return this;
                }
            }

            /* ==== PHY2D continuous collision engine ==== */

            var PHY2D = function (ctx, pointer, Vector, Matrix) {
                var kGravity = 5;
                var kTimeStep = 1 / 60;
                var kFriction = 0.5;
                var objects = [];
                var drag = false;
                var v0 = new Vector();
                var v1 = new Vector();
                var v2 = new Vector();
                var v3 = new Vector();
                var v4 = new Vector();
                var v5 = new Vector();

                // contacts list

                var contacts = [];
                contacts.index = 0;
                contacts.create = function (A, B, pa, pb, nx, ny) {
                    if (!this[this.index]) this[this.index] = new Contact();
                    this[this.index++].set(A, B, pa, pb, nx, ny);
                }

                // AABB container

                function AABB() {
                    this.x = 0.0;
                    this.y = 0.0;
                    this.w = 0.0;
                    this.h = 0.0;
                }

                // Polygon constructor

                function Polygon(x, y, w, h, vertices, invMass, angle, img) {
                    this.img = img;
                    this.vel = new Vector();
                    this.angularVel = 0.0;
                    this.invMass = invMass;
                    this.matrix = new Matrix().set(angle, x, y, w, h);
                    this.aabb = new AABB();
                    this.drag = false;
                    this.static = false;
                    this.length = (vertices.length / 2) | 0;
                    this.localSpacePoints = new Vector().array(this.length, vertices);
                    this.localSpaceNormals = new Vector().array(this.length).normal(this.localSpacePoints);
                    this.worldSpaceNormals = new Vector().array(this.length);
                    this.worldSpacePoints = new Vector().array(this.length);
                    this.invI = (invMass > 0) ? 1 / ((1 / invMass) * (w * w + h * h) / 3): 0
                    this.c1 = new Vector();
                    this.c0 = new Vector();
                    objects.push(this);
                }

                Polygon.prototype = {

                    // calculate aabb & transform world space points

                    motionAABB: function () {
                        this.worldSpacePoints.resetMinmax();
                        this.worldSpacePoints.transform(this.localSpacePoints, this.matrix);
                        this.worldSpaceNormals.rotate(this.localSpaceNormals, this.matrix);
                        var min = this.worldSpacePoints.min;
                        var max = this.worldSpacePoints.max;
                        this.aabb.x = (min.x + max.x) * 0.5;
                        this.aabb.y = (min.y + max.y) * 0.5;
                        this.aabb.w = (max.x - min.x) * 0.5;
                        this.aabb.h = (max.y - min.y) * 0.5;
                    },

                    // Poly vs poly collision detection (Minkowski Difference)

                    contact: function (that) {
                        var face,
                        vertex,
                        vertexRect,
                        faceRect,
                        fp,
                        va,
                        vb,
                        vc,
                        nx,
                        ny,
                        wsN,
                        wdV0,
                        wdV1,
                        wsV0,
                        wsV1;
                        mostSeparated.set(100000, -1, -1, 0, 100000);
                        mostPenetrating.set(-100000, -1, -1, 0, 100000);
                        this.featurePairJudgement(that, 2);
                        that.featurePairJudgement(this, 1);

                        if (mostSeparated.dist > 0 && mostSeparated.fpc !== 0) {
                            face = mostSeparated.edge;
                            vertex = mostSeparated.closestI;
                            fp = mostSeparated.fpc;
                        } else if (mostPenetrating.dist <= 0) {
                            face = mostPenetrating.edge;
                            vertex = mostPenetrating.closestI;
                            fp = mostPenetrating.fpc;
                        }

                        if (fp === 1) vertexRect = this,
                        faceRect = that;
                        else vertexRect = that,
                        faceRect = this;

                        wsN = faceRect.worldSpaceNormals[face];
                        va = vertexRect.worldSpacePoints[(vertex - 1 + vertexRect.length) % vertexRect.length];
                        vb = vertexRect.worldSpacePoints[vertex];
                        vc = vertexRect.worldSpacePoints[(vertex + 1) % vertexRect.length];
                        if (v0.project(vb, va, wsN) < v1.project(vc, vb, wsN)) {
                            wdV0 .........完整代码请登录后点击上方下载按钮下载查看

网友评论0