HTML5画布| 弹跳球| 循环遍历图像阵列并将不同背景图像放置在每个球上,居中

杰森是我的名字

我有些恶梦,在重力和画布边界的作用下,将不同的背景图像应用于在画布上反弹的球上,最终沉降并堆积在底部。

我创建了一个图像数组,我试图遍历该图像数组并为每个图像创建一个球,其中该图像成为居中的背景。

我可以将图像居中,但这会使球看起来离开画布的边界。因此已还原了该更改。

我无法获得与前一个球不同的背景图像。所有球上显示的图像是阵列中的最后一个图像。但是,创建的球的数量确实反映了阵列中图像的数量。

这是一个代码笔的链接:https ://codepen.io/jason-is-my-name/pen/BbNRXB

html, body{
    width:100%;
    height:100%;
    margin: 0;
    padding: 0;
    background: #333333;
}
*{
    margin: 0;
    padding: 0;
}
    .container {
        width: 410px;
        height: 540px;
    }
    #ball-stage{
        width: 100%;
        height: 100%;
    }

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="container">
    <canvas id="ball-stage" ></canvas>
</div>

<script>
    /*
    /*
     * Created by frontside.com.au
     * Amended by Jason
    */

    $(document).ready(function () {
        $.ajaxSetup({
            cache: true
        });
        var url1 = "https://code.createjs.com/easeljs-0.6.0.min.js";
        $.getScript(url1, function () {
            new App();
        })
    });

    function App() {

        var self = this;
        self.running = false;
        self.initialized = false;
        var stageClicked = false;
        var stage, canvas;

        var canvasWidth = 410;
        var canvasHeight = 540;
        var bounce = -0.75;
        var balls = [];
        var _gravityY = 1;
        var _gravityX = 0;
        var FPS = 30;
        var infoText, detailsText;
        var ballsInitalized = false;
        var iOS = navigator.userAgent.match(/(iPod|iPhone|iPad)/);

        self.initialize = function () {
            toggleListeners(true);
            self.initCanvas();
            self.initGame();
        };

        var toggleListeners = function (enable) {
            if (!enable) return;
        };

        self.refresh = function () {}

        self.initCanvas = function () {
            canvas = $("#ball-stage").get(0);
            stage = new createjs.Stage(canvas);

            window.addEventListener('resize', onStageResize, false);
            onStageResize();
            createjs.Touch.enable(stage);
            createjs.Ticker.addListener(tick);
            createjs.Ticker.setFPS(FPS);

            self.initialized = true;
        }

        self.initGame = function () {
            initBalls(canvasWidth, canvasHeight);
        }

        var onStageResize = function () {
            stage.canvas.width = canvasWidth;
            stage.canvas.height = canvasHeight;
        }

        var initBalls = function (stageX, stageY) {

            var imagesArray = ["img-1.png","img-2.png","img-3.png","img-4.png","img-5.png","img-6.png","img-7.png","img-8.png"];

            for (var i = 0; i < imagesArray.length; i++) {
                console.log(i);

                var imageArray = imagesArray[i];
                console.log(imageArray);

                setTimeout(function () {

                    var arrayImage = new Image();
                    console.log(arrayImage);

                    arrayImage.onload = function(){

                        addBall(arrayImage, stageX / 2, 0);

                    }

                    arrayImage.src = imageArray;

                }, i * 1000);

            }
        }

        var addBall = function (img, x, y) {
            console.log(img);
            var shape = new createjs.Shape();
            shape.id = balls.length;
            shape.radius = 51.25;
            shape.mass = shape.radius;
            shape.x = x;
            shape.y = y;
            shape.vx = rand(-3, 3);
            shape.vy = rand(-3, 3);

            var image = new Image();
            image.src = img;
            shape.graphics.beginBitmapFill(img,'repeat').drawCircle(0, 0, shape.radius);

            stage.addChild(shape);
            balls.push(shape);
        }

        var numBalls = function () {
            return balls.length;
        }
        var tick = function () {
            balls.forEach(move);
            for (var ballA, i = 0, len = numBalls() - 1; i < len; i++) {
                ballA = balls[i];
                for (var ballB, j = i + 1; j < numBalls(); j++) {
                    ballB = balls[j];
                    checkCollision(ballA, ballB);
                }
            }

            stage.update();
        }

        var rotate = function (x, y, sin, cos, reverse) {
            return {
                x: (reverse) ? (x * cos + y * sin) : (x * cos - y * sin),
                y: (reverse) ? (y * cos - x * sin) : (y * cos + x * sin)
            };
        }

        var checkCollision = function (ball0, ball1) {
            var dx = ball1.x - ball0.x,
                dy = ball1.y - ball0.y,
                dist = Math.sqrt(dx * dx + dy * dy);
            //collision handling code here
            if (dist < ball0.radius + ball1.radius) {
                //calculate angle, sine, and cosine
                var angle = Math.atan2(dy, dx),
                    sin = Math.sin(angle),
                    cos = Math.cos(angle),
                    //rotate ball0's position
                    pos0 = {
                        x: 0,
                        y: 0
                    }, //point
                    //rotate ball1's position
                    pos1 = rotate(dx, dy, sin, cos, true),
                    //rotate ball0's velocity
                    vel0 = rotate(ball0.vx, ball0.vy, sin, cos, true),
                    //rotate ball1's velocity
                    vel1 = rotate(ball1.vx, ball1.vy, sin, cos, true),
                    //collision reaction
                    vxTotal = vel0.x - vel1.x;
                vel0.x = ((ball0.mass - ball1.mass) * vel0.x + 2 * ball1.mass * vel1.x) /
                    (ball0.mass + ball1.mass);
                vel1.x = vxTotal + vel0.x;
                //update position - to avoid objects becoming stuck together
                var absV = Math.abs(vel0.x) + Math.abs(vel1.x),
                    overlap = (ball0.radius + ball1.radius) - Math.abs(pos0.x - pos1.x);
                pos0.x += vel0.x / absV * overlap;
                pos1.x += vel1.x / absV * overlap;
                //rotate positions back
                var pos0F = rotate(pos0.x, pos0.y, sin, cos, false),
                    pos1F = rotate(pos1.x, pos1.y, sin, cos, false);
                //adjust positions to actual screen positions
                // ball1.x = ball0.x + pos1F.x;
                setBallX(ball1, ball0.x + pos1F.x)
                //ball1.y = ball0.y + pos1F.y;
                setBallY(ball1, ball0.y + pos1F.y)
                // ball0.x = ball0.x + pos0F.x;
                setBallX(ball0, ball0.x + pos0F.x)
                // ball0.y = ball0.y + pos0F.y;
                setBallY(ball0, ball0.y + pos0F.y)
                //rotate velocities back
                var vel0F = rotate(vel0.x, vel0.y, sin, cos, false),
                    vel1F = rotate(vel1.x, vel1.y, sin, cos, false);
                ball0.vx = vel0F.x;
                ball0.vy = vel0F.y;
                ball1.vx = vel1F.x;
                ball1.vy = vel1F.y;
            }
        }

        var checkWalls = function (ball) {
            if (ball.x + ball.radius > canvas.width) {
                //  ball.x = canvas.width - ball.radius;
                setBallX(ball, canvas.width - ball.radius)
                ball.vx *= bounce;
            } else
            if (ball.x - ball.radius < 0) {
                // ball.x = ball.radius;
                setBallX(ball, ball.radius)
                ball.vx *= bounce;
            }
            if (ball.y + ball.radius > canvas.height) {
                //  ball.y = canvas.height - ball.radius;
                setBallY(ball, canvas.height - ball.radius)
                ball.vy *= bounce;
            } else
            if (ball.y - ball.radius < 0) {
                //ball.y = ball.radius;
                setBallY(ball, ball.radius)
                ball.vy *= bounce;
            }
        }

        var move = function (ball) {
            ball.vy += _gravityY;
            ball.vx += _gravityX;
            setBallX(ball, ball.x + ball.vx)
            setBallY(ball, ball.y + ball.vy)
            checkWalls(ball);
        }
        var setBallX = function (ball, x) {
            if (isNaN(ball.pointerID)) {
                ball.x = x
            }
        }
        var setBallY = function (ball, y) {
            if (isNaN(ball.pointerID)) {
                ball.y = y
            }
        }

        var rand = function (min, max) {
            return Math.random() * (max - min) + min;
            return (Math.random() * max) + min;
        }

        self.initialize();
        return self;
    }

    window.log = function f() {
        log.history = log.history || [];
        log.history.push(arguments);
        if (this.console) {
            var args = arguments,
                newarr;
            args.callee = args.callee.caller;
            newarr = [].slice.call(args);

            if (typeof console.log === 'object') log.apply.call(console.log, console, newarr);
            else console.log.apply(console, newarr);
        }
    };
    (function (a) {
        function b() {}

        for (var c = "assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","), d; !!(d = c.pop());) {
            a[d] = a[d] || b;
        }
    })

    (function () {
        try {
            console.log();
            return window.console;
        } catch (a) {
            return (window.console = {});
        }
    }());
</script>

现在,我被困在代码中大约一个星期了,确实可以得到一些天才的帮助!

目的:

  • 添加等于图像阵列长度的球。

  • 每个球都有其各自的图像作为居中的背景。

  • 球不会离开画布的边界。

相关代码:

  • initBalls()

  • addBall()

谢谢,杰森。

约翰·约翰逊

https://codepen.io/prtjohanson/pen/vPKQBg

需要更改的内容:

for (let i = 0; i < imagesArray.length; i++) {
  console.log(i);

  const imageArray = imagesArray[i];

  setTimeout(function() {
    var arrayImage = new Image();

    arrayImage.onload = function() {
      addBall(arrayImage, stageX / 2, 0);
    };

    arrayImage.src = imageArray;
  }, i * 1000);
}

在setTimeout回调被触发时,您的for循环已经完成,并且使用var声明,for循环迭代没有自己的作用域,而let则每个迭代都像函数一样具有自己的作用域。

如果它必须在没有let或const关键字的浏览器上运行,请告诉我,我也可以为他们提供解决方案

这将在IE11和其他不支持ES6的浏览器中运行

 for (var i = 0; i < imagesArray.length; i++) {
  (function(imageArray) {

    setTimeout(function() {
      var arrayImage = new Image();

      arrayImage.onload = function() {
        console.log('Add'+i);
        addBall(arrayImage, stageX / 2, 0);
      };

      arrayImage.src = imageArray;
    }, i * 1000);
  })(imagesArray[i]);
}

要使图像居中,而不会超出画布的范围,请对beginBitmapFill操作使用2D变换:

var transform = new createjs.Matrix2D();
transform.appendTransform(-shape.radius, -shape.radius, 1, 1, 0);
shape.graphics.beginBitmapFill(img, "repeat", transform).drawCircle(0, 0, shape.radius);

至于数组中没有多少个URL,似乎图像源URL有时会提示“我不是机器人”验证码。如果用您控制下的URL替换,该问题将消失。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章