user3593994
user3593994

Reputation: 23

Using PreloadJS to load images and adding them to CreateJS stage

I'm trying to create a Tri Peaks Solitaire game in Javascript, using CreateJS to help interact with the HTML canvas. I'm not entirely new to programming, as I've taken college courses on Java and C, but I am new to both Javascript and HTML.

I created a large amount of the card game using a Card class and Deck class, with the image adding, event listening, and game logic done in one Javascript file, but this resulted in a lot of messy, somewhat buggy code that I felt needed cleaning up.

I'm trying to implement a separate class for the card table, which will be the canvas, or stage, and it will draw the 4 rows of playable cards, the stock pile, and the waste pile. I'm currently just trying to get the stock pile to show up on the canvas, but it's not happening.

My question is, why is my stock pile not showing up? Also, as you can see, the card images are being loaded when the cards are created. Should I be doing that differently?

Card class:

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 class:

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 class:

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 file:

<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" width="1000" height="450">
        </canvas> 

    </body>
</html>

PRELOADJS UPDATE:

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");
        }

Upvotes: 0

Views: 1605

Answers (2)

Berni
Berni

Reputation: 151

I would suggest waiting for all the images to load and then calling stage.update(). Alternatively use the createjs.Ticker.addEventListener("tick", handleTick); event handler to update the stage for you.

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

Upvotes: 0

gskinner
gskinner

Reputation: 2488

You are only updating the stage immediately after creating the cards. The cards are loading bitmap images, which is a concurrent operation that takes time. As such, the only time you render the stage is before the images load.

I would suggest using PreloadJS to preload your card images. This will also give you a lot more control over when / how they load, and let you show a progress bar or distractor to the user as they load.

Upvotes: 2

Related Questions