0

複数のキャンバスを使用することを決定するまで、描画は正常に機能していました。ステージ キャンバス、エンティティ キャンバス、オブジェクト キャンバスがあります。ただし、オブジェクト キャンバスとエンティティ キャンバスを組み合わせることになるでしょう。とにかく、以下に示すように、私のヒーロー クラスは問題なく描画されます。次に、同じ描画関数でエンティティ クラスを作成しようとしましたが、関数を呼び出しても描画できません。背景キャンバスにもほぼ同じ問題があります。バックグラウンド用のクラスはまだありませんが、そうします。しかし、ステージのコンテキストで単純に画像を描画しようとすると、コードが壊れます。

(JSFiddle をセットアップしようとしましたが、そこに画像を取得できませんでした。)

UPDATE 私の問題の半分はmarkEによって修正されました。私が現在抱えている唯一の問題は、entitiesCtx が画像/長方形を描画できる唯一のコンテキストであることです。他のctxは何も描画できません。助けてください!コードを更新しました。

var stage = document.getElementById('stage');
var ctxStage = stage.getContext('2d');
var entitiesStage = document.getElementById('entities');
var ctxEntities = entitiesStage.getContext('2d');
var bg = document.getElementById('bg');
var ctxBg = bg.getContext('2d');
var playerImg = new Image();
playerImg.src = 'res/player_sprite_sheet.png';
var bgImg = new Image();
bgImg.onload = function() {
    ctxBg.drawImage(bgImg,0,0,80,50,-200,-90,1000,700);
};
bgImg.src = 'res/background.png';
var consoleImg = new Image();
consoleImg.onload = function() {
    ctxEntities.drawImage(consoleImg,0,0,80,50,20,20,1000,700);
};
console.src = 'res/console.png';

var hero = new Hero();
var prop;

var isPlaying = false;

window.onload = init;
var requestAnimFrame = window.requestAnimationFrame ||
                        window.webkitRequestAnimationFrame ||
                        window.mozRequestAnimationFrame ||
                        window.oRequestAnimationFrame ||
                        window.msRequestAnimationFrame ||
                        function(callback) {
                            window.setTimeout(callback, 1000 / 60);
                        };

function init() {
    console.debug('initializing...');

    document.addEventListener('keydown',keyDown,false);
    document.addEventListener('keyup',keyUp,false);

    ctxStage.imageSmoothingEnabled = false;
    ctxStage.webkitImageSmoothingEnabled = false;
    ctxStage.mozImageSmoothingEnabled = false;
    ctxEntities.imageSmoothingEnabled = false;
    ctxEntities.webkitImageSmoothingEnabled = false;
    ctxEntities.mozImageSmoothingEnabled = false;

    prop = new Entity(consoleImg,20,20,80,50,0,0);

    startLoop();
}

function startLoop(){
    console.debug('starting loop...');
    isPlaying = true;
    loop();
}

function stopLoop(){
    console.debug('stopping loop...');
    isPlaying = false;
}

function loop(){
    if(isPlaying){
        requestAnimFrame(loop);
        draw();
        update();
    }
}

function update(){
    hero.update();
}

function clearCtx(){
    ctxEntities.clearRect(0,0,stage.width,stage.height);
}

function draw(){
    clearCtx();
    ctxEntities.fillStyle = 'black';
    ctxEntities.fillRect(0,0,stage.width,stage.height);
    ctxEntities.drawImage(bgImg,0,0,80,50,-200,-90,1000,700);
    hero.draw();
    prop.draw();
}


// hero class
function Hero() {
    this.xpos = 140;
    this.ypos = 320;
    this.srcX = 0;
    this.srcY = 0;
    this.width = 10;
    this.height = 20;
    this.scaleX = 50;
    this.scaleY = 80;
    this.isUpKey;
    this.isDownKey;
    this.isLeftKey;
    this.isRightKey;
    this.img = playerImg;

    this.speed = 2;
    this.defspeed = 3.5;
    this.dir = 'right';
}

Hero.prototype.draw = function() {
    ctxEntities.drawImage(this.img,this.srcX,this.srcY,this.width,this.height,this.xpos,this.ypos,this.scaleX,this.scaleY);
};

Hero.prototype.update = function() {
    this.checkKeys();

    if(this.dir == 'right'){
        if(this.scaleX >= 0){
            this.srcX = 0;
        }
        if(this.scaleX >= 40){
            this.scaleX = 40;
            this.speed = this.defspeed;
        }else{
            this.xpos -= 2.3;
            this.speed = 0;
            this.scaleX += 5;
        }
    }else if(this.dir =='left'){
        if(this.scaleX <= 0){
            this.srcX = 10;
        }
        if(this.scaleX <= -40){
            this.scaleX = -40;
            this.speed = this.defspeed;
        }else{
            this.xpos += 2.3;
            this.speed = 0;
            this.scaleX -= 5;
        }
    }
};

Hero.prototype.checkKeys = function() {
    if(this.isLeftKey){
        this.xpos += -this.speed;
        this.dir = 'left';
    }
    if(this.isRightKey){
        this.xpos += this.speed;
        this.dir = 'right';
    }
};
// end of hero class


// entity class
function Entity(img,xpos,ypos,width,height,scaleX,scaleY){
    this.img = img;
    this.xpos = xpos;
    this.ypos = ypos;
    this.width = width;
    this.height = height;
    this.scaleX = scaleX;
    this.scaleY = scaleY;
}

Entity.prototype.draw = function(){
    ctxEntities.drawImage(this.img,0,0,this.width,this.height,this.xpos,this.ypos,this.scaleX,this.scaleY);
};
// end of entity class


// input handling
function keyDown(e){
    var keyID = (e.keyCode) ? e.keyCode : e.which;

    if(keyID == 38 || keyID == 87){ //w
        e.preventDefault();
        hero.isUpKey = true;
    }
    if(keyID == 37 || keyID == 65){ //a
        e.preventDefault();
        hero.isLeftKey = true;
    }
    if(keyID == 40 || keyID == 83){ //s
       e.preventDefault();
       hero.isDownKey = true;
    }
    if(keyID == 39 || keyID == 68){ //d
        e.preventDefault();
        hero.isRightKey = true;
    }
}

function keyUp(e){
    var keyID = (e.keyCode) ? e.keyCode : e.which;

    if(keyID == 38 || keyID == 87){
        hero.isUpKey = false;
    }
    if(keyID == 37 || keyID == 65){
        hero.isLeftKey = false;
    }
    if(keyID == 40 || keyID == 83){
        hero.isDownKey = false;
    }
    if(keyID == 39 || keyID == 68){
        hero.isRightKey = false;
    }
}
// end of input handling

UPDATE 私の問題の半分はmarkEによって修正されました。私が現在抱えている唯一の問題は、entitiesCtx が画像/長方形を描画できる唯一のコンテキストであることです。他のctxは何も描画できません。コードを更新しました。

4

1 に答える 1

1

JS の「クラス」を使用して複数のキャンバスに描画する

[JS クラスの使用例を含めるように回答を拡張しました]

この例は、キャンバスに画像を描画する 2 つの js クラスを示しています

  • Entity クラスは、キャンバス上の画像を制御および描画します。
  • Hero クラスは、キャンバス上のスプライト シートを制御および描画します。

すべての画像が使用前に完全に読み込まれるように、画像ローダーもあります。

あなたの質問には、js クラスのコードのみが含まれており、プロジェクトの詳細は含まれていません。

だから私はあなたの Hero クラスと Entity クラスを使って自分のプロジェクトを作りました (私の自由を許してください)。

この画像は、3 つのキャンバスすべてで描画中の Entity クラスと Hero クラスを示しています...

ここに画像の説明を入力

これは、以下を含むバックグラウンド キャンバスです。

  • キャンバスを埋める空色の四角形 (空)
  • 背景には 2 つの Entity クラス オブジェクトが含まれています。
  • Entity クラス オブジェクトにラップされた画像である太陽
  • エンティティ クラス オブジェクトにラップされた画像である壁

ここに画像の説明を入力

これは、以下を含むステージ キャンバスです。

  • 上下にアニメーションする Entity クラス オブジェクトである大砲

ここに画像の説明を入力

これは、以下を含むエンティティ キャンバスです。

  • 猫の画像は、Hero クラス オブジェクトにラップされたスプライト シート画像です。
  • cat オブジェクトは大砲オブジェクトに応答してスプライトをアニメーション化します
  • 猫は Hero クラスによって制御されるスプライトシートで構成されています

ここに画像の説明を入力

Entity クラスは、キャンバス上の画像を制御および描画します。

  • 画像は移動およびスケーリングできます。
  • Entity クラスには 3 つのメソッドがあります。
  • Entity.draw() はキャンバスに画像を描画します。
  • Entity.set() は、キャンバス上の画像の XY 位置を設定します。
  • Entity.scale() は画像をスケーリングします。

Entity クラスのコードは次のとおりです。

// Entity class
function Entity(context,img,x,y){
    this.context=context;
    this.img = img;
    this.xpos = x;
    this.ypos = y;
    this.width = img.width;
    this.height = img.height;
    this.scaleX = img.width;
    this.scaleY = img.height;
}

// Entity.set()
Entity.prototype.set = function(x,y){
    this.xpos=x;
    this.ypos=y;
}

// Entity.scale()
Entity.prototype.scale = function(scaleX,scaleY){
    this.scaleX=scaleX;
    this.scaleY=scaleY;
}

// Entity.draw()
Entity.prototype.draw = function(){
    this.context.drawImage(this.img,
        0,0,this.width,this.height,
        this.xpos,this.ypos,this.scaleX,this.scaleY);
}

Hero クラスは、キャンバス上のスプライト シートを制御および描画します。

  • 個々のスプライトは、スプライト シート イメージから取得されます。
  • 各スプライトは、スプライト シート内の x、y、幅、高さを持つオブジェクトによって定義されます。
  • スプライトは移動およびスケーリングできます。
  • Hero クラスには 3 つのメソッドがあります。
  • Hero.draw() は、キャンバスにスプライトの 1 つを描画します。
  • Hero.set() は、描画されるスプライトとそのキャンバス上の XY 位置を設定します
  • Hero.scale() はスプライトをスケーリングします。

Hero クラスのコードは次のとおりです。

// Hero class
function Hero(context,img,spriteDefs) {
    this.context=context;
    this.spriteDefs=spriteDefs;
    this.img = img;
    this.xpos = 0;
    this.ypos = 0;
    this.srcX = 0;
    this.srcY = 0;
    this.width = img.width;
    this.height = img.height;
    this.scaleX = img.width;
    this.scaleY = img.height;
    this.isUpKey;
    this.isDownKey;
    this.isLeftKey;
    this.isRightKey;

    this.speed = 2;
    this.defspeed = 3.5;
    this.dir = 'right';
}

// Hero.set()
Hero.prototype.set = function(spriteNumber,x,y){
    // pull the specified sprite
    var sprite=this.spriteDefs[spriteNumber];
    this.srcX=sprite.x;
    this.srcY=sprite.y;
    this.width=sprite.width;
    this.height=sprite.height;
    // default scale to 100%
    this.scaleX=sprite.width;
    this.scaleY=sprite.height;
    this.xpos=x;
    this.ypos=y;
}

// Hero.scale()
Hero.prototype.scale = function(scaleX,scaleY){
    this.scaleX=scaleX;
    this.scaleY=scaleY;
}

// Hero.draw()
Hero.prototype.draw = function() {
    this.context.drawImage(this.img,
        this.srcX,this.srcY,this.width,this.height,
        this.xpos,this.ypos,this.scaleX,this.scaleY);
}

これは、すべての画像が使用される前に読み込まれることを確認する画像ローダーです。

var imageURLs=[];
var imagesOK=0;
var imgs=[];
imageURLs.push("cats.png");
imageURLs.push("cannonLifted.png");
imageURLs.push("brickwall.jpg");
imageURLs.push("sun.png");
loadAllImages();

function loadAllImages(){
    for (var i = 0; i < imageURLs.length; i++) {
      var img = new Image();
      imgs.push(img);
      img.onload = function(){ imagesOK++; imagesAllLoaded(); };
      img.src = imageURLs[i];
    }      
}

var imagesAllLoaded = function() {
  if (imagesOK==imageURLs.length ) {
     // all images are fully loaded an ready to use
     cat=imgs[0];
     cannon=imgs[1];
     wall=imgs[2];
     sun=imgs[3];
     start();
  }
};

ここに完全なコードとフィドルがあります: http://jsfiddle.net/m1erickson/yCW9U/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; padding:20px; }
    h3{ font-size:2em; }
    #wrapper{
        position:relative;
        width:350px;
        height:400px;
    }
    #bg,#stage,#entities{
        position:absolute; top:0px; left:0px;
        border:1px solid green;
        width:100%;
        height:100%;
    }
</style>

<script>
$(function(){


    //////////////////////////////
    // get context references
    //////////////////////////////


    // stage
    var stage = document.getElementById('stage');
    var ctxStage = stage.getContext('2d');
    // entities
    var entitiesStage = document.getElementById('entities');
    var ctxEntities = entitiesStage.getContext('2d');
    // background
    var bg = document.getElementById('bg');
    var ctxBg = bg.getContext('2d');


    //////////////////////////////
    // public variables
    //////////////////////////////


    // images
    var wall,cat,cannon,sun;

    // display objectx
    var sunEntity,wallEntity,cannonEntity,catHero;

    // animation vars 
    var cannonX=65;
    var cannonMove=-10;
    var cannonMin=75;
    var cannonMax=185;
    var cannonY=185;
    var cannonSafe=145;

    // cat hero sprites
    var catSpriteNames={
        laying:0,
        layingX:250,
        layingY:127,
        standing:1,
        standingX:165,
        standingY:25
    };
    var catSprites=[
        {x:80, y:30, width:67, height:48},
        {x:15, y:8,  width:47, height:78}
    ];


    //////////////////////////////
    // preload all images
    //////////////////////////////


    var imageURLs=[];
    var imagesOK=0;
    var imgs=[];
    imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/cats.png");
    imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/cannonLifted.png");
    imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/BrickWall.jpg");
    imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/sun.png");
    loadAllImages();

    function loadAllImages(){
        for (var i = 0; i < imageURLs.length; i++) {
          var img = new Image();
          imgs.push(img);
          img.onload = function(){ imagesOK++; imagesAllLoaded(); };
          img.src = imageURLs[i];
        }      
    }

    var imagesAllLoaded = function() {
      if (imagesOK==imageURLs.length ) {
         // all images are fully loaded an ready to use
         cat=imgs[0];
         cannon=imgs[1];
         wall=imgs[2];
         sun=imgs[3];
         start();
      }
    };


    //////////////////////////////
    // build the display objects 
    // and start animation
    //////////////////////////////


    function start(){

        // static background (canvas: bg)
        // rectangle=blue sky
        ctxBg.rect(0,0,bg.width,bg.height);
        ctxBg.fillStyle="skyblue";
        ctxBg.fill();
        // sun image @ 75% scale
        sunEntity=new Entity(ctxBg,sun,185,15);
        sunEntity.set(25,15);
        sunEntity.scale(sun.width*.75,sun.height*.75);
        sunEntity.draw();
        // wall image
        wallEntity=new Entity(ctxBg,wall,250,bg.height-wall.height);
        wallEntity.set(250,bg.height-wall.height,wall.width,wall.height);
        wallEntity.draw();


        // stage (canvas: stage)
        // contents: wall
        cannonEntity=new Entity(ctxStage,cannon,cannonX,cannonY,cannon.width,cannon.height,cannon.width,cannon.height);
        cannonEntity.draw();


        // entities (canvas: entities)
        // contents: 
        catHero=new Hero(ctxEntities,cat,catSprites);
        catHero.set(catSpriteNames.laying,catSpriteNames.layingX,catSpriteNames.layingY);
        catHero.draw();

        animate();
    }

    function animate(){

        cannonY+=cannonMove;
        if(cannonY<cannonMin){ cannonY=cannonMin; cannonMove=-cannonMove; }
        if(cannonY>cannonMax){ cannonY=cannonMax; cannonMove=-cannonMove; }

        cannonEntity.context.clearRect(0,0,stage.width,stage.height);
        cannonEntity.set(cannonX,cannonY);
        cannonEntity.draw();

        if(cannonY>cannonSafe){
            catHero.set(catSpriteNames.laying,catSpriteNames.layingX,catSpriteNames.layingY);
        }else{
            catHero.set(catSpriteNames.standing,catSpriteNames.standingX,cannonY-50);
        }
        catHero.context.clearRect(0,0,entities.width,entities.height);
        catHero.draw()


        window.setTimeout(function(){animate();},500);
    }


    // Hero class
    function Hero(context,img,spriteDefs) {
        this.context=context;
        this.spriteDefs=spriteDefs;
        this.img = img;
        this.xpos = 0;
        this.ypos = 0;
        this.srcX = 0;
        this.srcY = 0;
        this.width = img.width;
        this.height = img.height;
        this.scaleX = img.width;
        this.scaleY = img.height;
        this.isUpKey;
        this.isDownKey;
        this.isLeftKey;
        this.isRightKey;

        this.speed = 2;
        this.defspeed = 3.5;
        this.dir = 'right';
    }
    // Hero.set()
    Hero.prototype.set = function(spriteNumber,x,y){
        // pull the specified sprite
        var sprite=this.spriteDefs[spriteNumber];
        this.srcX=sprite.x;
        this.srcY=sprite.y;
        this.width=sprite.width;
        this.height=sprite.height;
        // default scale to 100%
        this.scaleX=sprite.width;
        this.scaleY=sprite.height;
        this.xpos=x;
        this.ypos=y;
    }
    // Hero.scale()
    Hero.prototype.scale = function(scaleX,scaleY){
        this.scaleX=scaleX;
        this.scaleY=scaleY;
    }
    // Hero.draw()
    Hero.prototype.draw = function() {
        this.context.drawImage(this.img,
            this.srcX,this.srcY,this.width,this.height,
            this.xpos,this.ypos,this.scaleX,this.scaleY);
    }


    // Entity class
    function Entity(context,img,x,y){
        this.context=context;
        this.img = img;
        this.xpos = x;
        this.ypos = y;
        this.width = img.width;
        this.height = img.height;
        this.scaleX = img.width;
        this.scaleY = img.height;
    }
    // Entity.set()
    Entity.prototype.set = function(x,y){
        this.xpos=x;
        this.ypos=y;
    }
    // Entity.scale()
    Entity.prototype.scale = function(scaleX,scaleY){
        this.scaleX=scaleX;
        this.scaleY=scaleY;
    }
    // Entity.draw()
    Entity.prototype.draw = function(){
        this.context.drawImage(this.img,
            0,0,this.width,this.height,
            this.xpos,this.ypos,this.scaleX,this.scaleY);
    }

}); // end $(function(){});
</script>

</head>

<body>
    <h3>Watch out Kitty!</h3><br>
    <div id="wrapper">
        <canvas id="bg" width=350 height=400></canvas>
        <canvas id="stage" width=350 height=400></canvas>
        <canvas id="entities" width=350 height=400></canvas>
    </div>
</body>
</html>
于 2013-08-18T21:28:09.387 に答える