簡體   English   中英

HTML5 畫布 | 彈跳球 | 循環遍歷圖像數組並在每個球上放置不同的背景圖像,居中

[英]HTML5 Canvas | Bouncing Balls | Looping through an image array and placing different background images on each ball, centered

我有一些噩夢,將不同的背景圖像應用到在重力和畫布邊界的作用下在畫布中彈跳的球上,最終安定下來並堆積在底部。

我創建了一個圖像數組,我試圖循環遍歷並為每個圖像創建一個球,其中圖像成為居中的背景。

我可以將圖像居中,但這會使球看起來離開畫布的邊界。 所以已經恢復了這種變化。

我無法使背景圖像與之前的球不同。 所有球上顯示的圖像是陣列中的最后一個圖像。 然而,創建的球數確實反映了陣列中圖像的數量。

這是代碼筆的鏈接: 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>

我已經被困在代碼中大約一個星期了,真的可以得到一些天才的幫助!

目標:

  • 添加與圖像數組長度相等的球。

  • 每個球都有其各自的圖像作為居中的背景。

  • 球不會離開畫布的邊界。

相關代碼:

  • 初始化球()

  • 添加球()

謝謝,傑森。

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-s 替換,問題應該會消失。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM