使用 PreloadJS 加载图像并将它们添加到 CreateJS 阶段

Posted

技术标签:

【中文标题】使用 PreloadJS 加载图像并将它们添加到 CreateJS 阶段【英文标题】:Using PreloadJS to load images and adding them to CreateJS stage 【发布时间】:2015-12-25 02:09:47 【问题描述】:

我正在尝试用 javascript 创建一个 Tri Peaks Solitaire 游戏,使用 CreateJS 来帮助与 html 画布进行交互。我对编程并不完全陌生,因为我参加过 Java 和 C 的大学课程,但我对 Javascript 和 HTML 都很陌生。

我使用 Card 类和 Deck 类创建了大量的纸牌游戏,在一个 Javascript 文件中完成了图像添加、事件监听和游戏逻辑,但这导致了很多混乱、有点错误的代码我觉得需要清理。

我正在尝试为卡片表实现一个单独的类,它将是画布或舞台,它将绘制 4 行可玩卡片、库存堆和废物堆。我目前只是想让库存堆出现在画布上,但它没有发生。

我的问题是,为什么我的库存没有出现?此外,如您所见,创建卡片时正在加载卡片图像。我应该采取不同的做法吗?

卡类:

var Card = function(number) 
    this.isFaceUp = false;
    //number for image file path
    this.number = number;
    this.value = Math.ceil( (this.number)/4 );
    //back of the card is default image
    this.initialize("images/" + 0 + ".png");
    console.log("card created")
    this.height = this.getBounds().height;
    this.width = this.getBounds().width;
    //load the card's front image
    this.frontImage = new Image();
    this.frontImage.src = ( this.getImagePath() );
;

Card.prototype = new createjs.Bitmap("images/" + this.number + ".png");

Card.prototype.getImagePath = function() 
        return "images/" + this.number + ".png";
;

Card.prototype.getValue = function () 
    return this.value;

Card.prototype.flip = function() 
//    this.image = new Image();
//    this.image.src = ( this.getImagePath() );
    this.image = this.frontImage;
    this.isFaceUp = true;
;

Card.prototype.getHeight = function() 
    return this.height;
;

Card.prototype.getWidth = function() 
    return this.width;
;

CardDeck 类:

function CardDeck() 
    //create empty array
    this.deck = [];
    //fill empty array
    for(i=1; i<=52; i++) 
        //fill deck with cards, with i being the number of the card
        this.deck[i-1] = new Card(i);
    
    //shuffle deck
    this.shuffle();


CardDeck.prototype.getCard = function() 
    if(this.deck.length < 1) alert("No cards in the deck");
    return this.deck.pop();
;

CardDeck.prototype.getSize = function() 
    return this.deck.length;
;

CardDeck.prototype.shuffle = function() 
    for (i=0; i<this.deck.length; i++) 
      var randomIndex = Math.floor( Math.random()*this.deck.length );
      var temp = this.deck[i];
      this.deck[i] = this.deck[randomIndex];
      this.deck[randomIndex] = temp;
    
;

CardDeck.prototype.getRemainingCards = function() 
    return this.deck.splice(0);


CardDeck.prototype.listCards = function() 
    for(i=0; i<this.deck.length; i++) 
        console.log(this.deck[i].number);
    
;

CardTable 类:

var CardTable = function(canvas) 
    this.initialize(canvas);
    this.firstRow = [];
    this.secondRow = [];
    this.thirdRow = [];
    this.fourthRow = [];
    this.stockPile = [];
    this.wastePile = [];
    //startX is card width
    this.startX = ( new Card(0) ).width*3;
    //startY is half the card height
    this.startY = ( new Card(0) ).height/2;
;

CardTable.prototype = new createjs.Stage();

CardTable.prototype.createStockPile = function(cards) 
    for(i=0; i<23; i++) 
        cards[i].x = 10;
        cards[i].y = 50;
        this.stockPile[i] = cards[i];
    
;

CardTable.prototype.addToWastePile = function(card) 
    card.x = startX + card.width;
    card.y = startY;
    this.wastePile.push(card);
    this.addChild(card);
    this.update();
;

CardTable.prototype.drawStockPile = function() 
    for(i=0; i<this.stockPile.length; i++) 
        console.log("this.stockPile[i]");
        this.addChild(this.stockPile[i]);
    
    this.update();
;

HTML 文件:

<html>
    <head>
        <title>Tri-Peaks Solitaire</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="https://code.createjs.com/easeljs-0.8.1.min.js"></script>
        <script src="card.js"></script>
        <script src="carddeck.js"></script>
        <script src="cardtable.js"></script>
        <script>   
            function init()
                var canvas = document.getElementById("canvas");
                var table = new CardTable("canvas");
                deck = new CardDeck();
                table.createStockPile(deck.getRemainingCards());
                table.drawStockPile();
                table.update();
            
        </script>
    </head>
    <body onload="init()">
        <h1>Tri-Peaks Solitaire</h1>   
        <canvas style='border: 5px solid green; background: url("images/background.jpg");' 
                id="canvas"  >
        </canvas> 

    </body>
</html>

PRELOADJS 更新:

var canvas = document.getElementById("canvas");
        var stage = new createjs.Stage(canvas);
        var gameDeck = new CardDeck();
        var numbers = [];
        var preloader;
        var progressText = new createjs.Text("", "20px Arial","#FF0000");
        progressText.x = 50;
        progressText.y = 20;
        stage.addChild(progressText);
        stage.update();
        setupManifest();
        startPreload();
function setupManifest() 
            for(i=0; i<=52; i++) 
            console.log("manifest");
                manifest.push( src:"images/" + i + ".png",
                                id: i );
                numbers.push(i);
            
        

        function startPreload() 
            preload = new createjs.LoadQueue(true);
            preload.on("fileload", handleFileLoad);
            preload.on("progress", handleFileProgress);
            preload.on("complete", loadComplete);
            preload.on("error", loadError);
            preload.loadManifest(manifest);
        

        function handleFileLoad(event) 
            console.log("A file has loaded of type: " + event.item.type);
            //console.log(numbers.pop());
            var cardNumber = numbers.pop();
            var newCard = new Card(cardNumber);
            //faces.push( new Image() );
            //faces[ faces.length - 1 ].src = "images/" + cardNumber + ".png";
            gameDeck.insertCard(newCard);
        

        function loadError(evt) 
            console.log("error",evt.text);
        

        function handleFileProgress(event) 
            progressText.text = (preload.progress*100|0) + " % Loaded";
            stage.update();
        

        function loadComplete(event) 
            console.log("Finished Loading Assets");
        

【问题讨论】:

【参考方案1】:

您只是在创建卡片后立即更新关卡。卡片正在加载位图图像,这是一个需要时间的并发操作。因此,您渲染舞台的唯一时间是在图像加载之前。

我建议使用 PreloadJS 来预加载您的卡片图像。这也将让您更好地控制它们何时/如何加载,并让您在加载时向用户显示进度条或干扰项。

【讨论】:

感谢您的建议。我会试一试。 我试用了 PreloadJS,但遇到了类似的问题。除了背景图像之外,画布上没有显示任何内容。我目前只是尝试显示带有加载进度更新的文本,但没有显示任何内容。 你确定更新舞台了吗?除非您致电 stage.update(),否则舞台不会重绘 我在原始帖子的底部发布了新代码。添加进度文本子项后,我正在更新阶段。 insertCard 是做什么的?最好的方法是在加载卡片后创建您的套牌,或者至少在此时更新阶段。如果您仅在最初创建进度文本时进行更新,则不会显示任何内容。【参考方案2】:

我建议等待所有图像加载完毕,然后调用 stage.update()。或者使用createjs.Ticker.addEventListener("tick", handleTick); 事件处理程序为您更新舞台。

参考:http://www.createjs.com/docs/easeljs/classes/Ticker.html

【讨论】:

以上是关于使用 PreloadJS 加载图像并将它们添加到 CreateJS 阶段的主要内容,如果未能解决你的问题,请参考以下文章

PreloadJS getResult(spriteSheet)

HTML5 new Image() 图像需要加载后才能drawImage? 怎样保证多个Image对象都加载完成?

使用createjs的preloadjs加载图片

图片预先加载 preloadjs

如何在表单的输入类型=“文件”中添加图像并将它们都提交到同一个表单后生成缩略图

如何从OpenGL加载图像?