简体   繁体   English

如何创建在画布上绘制精灵的函数?

[英]How can I create a function to draw a sprite on canvas?

I need to create function sprite() with canvas in javascript I have 2 codes this to create a sprite : 我需要使用javascriptcanvas中创建功能sprite() ,我有2个代码来创建sprite:

var width = 40,
    height = 28,
    frames = 2,

    currentFrame = 0,

    canvas = document.getElementById("myCanvas");
    ctx = canvas.getContext("2d");
    image = new Image()
    image.src = 'http://s28.postimg.org/k90gybbtl/bird_Sprite.png';

var draw = function(){
    ctx.clearRect(0, 0, width, height);
    ctx.drawImage(image, 0, height * currentFrame, width, height, 0, 0, width, height);

    if (currentFrame == frames) {
      currentFrame = 0;
    } else {
      currentFrame++;
    }
}

setInterval(draw, 120);

I have another code for simple game : 我还有另一个简单游戏的代码:

function startGame() {
    myGamePiece = new component(30, 30, "red", 10, 120);
    myGamePiece.gravity = 0.05;
    myScore = new component("30px", "Consolas", "black", 280, 40, "text");
    myUpBtn = new component(canvasWidth, canvasHeight, "rgba(0, 0, 0, 0)", 0, 0); 
    myGameArea.start();
}

function component(width, height, color, x, y, type) {
    this.type = type;
    if (type == "image") {
      this.image = new Image();
      this.image.src = color;
    }
    this.score = 0;
    this.width = width;
    this.height = height;
    this.speedX = 0;
    this.speedY = 0;    
    this.x = x;
    this.y = y;
    this.gravity = 0;
    this.gravitySpeed = 0;
    this.update = function() {
        ctx = myGameArea.context;
        if (this.type == "text") {
            ctx.font = this.width + " " + this.height;
            ctx.fillStyle = color;
            ctx.fillText(this.text, this.x, this.y);
        } else {
                if (type == "image") {
                    ctx.drawImage(this.image, 
                    this.x, 
                    this.y,
                    this.width, this.height);
                } else {
            ctx.fillStyle = color;
            ctx.fillRect(this.x, this.y, this.width, this.height);
            }
        }
    }
        this.clicked = function() {
        var mytop = this.y;

        var clicked = true;
        if (mytop > myGameArea.y) {
            clicked = false;
        }
        return clicked;
    }
    this.newPos = function() {
        this.gravitySpeed += this.gravity;
        this.x += this.speedX;
        this.y += this.speedY + this.gravitySpeed;
        this.hitBottom();
    }
    this.hitBottom = function() {
        var rockbottom = myGameArea.canvas.height - this.height;
        if (this.y > rockbottom) {
            this.y = rockbottom;
            this.gravitySpeed = 0;
        }
    }
    this.crashWith = function(otherobj) {
        var myleft = this.x;
        var myright = this.x + (this.width);
        var mytop = this.y;
        var mybottom = this.y + (this.height);
        var otherleft = otherobj.x;
        var otherright = otherobj.x + (otherobj.width);
        var othertop = otherobj.y;
        var otherbottom = otherobj.y + (otherobj.height);
        var crash = true;
        if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) {
            crash = false;
        }
        return crash;
    }
} // https://www.w3schools.com/graphics/game_images.asp

etc... now the problem is ... 等等...现在的问题是...

I can't make the 2 codes together 我不能一起写两个代码

can anyone help me? 谁能帮我?

thank you :) 谢谢 :)

The following code adds your sprite to the game code from W3 Schools: 以下代码将您的Sprite添加到W3 Schools的游戏代码中:

 var myGamePiece; var myObstacles = []; var myScore; function startGame() { myGamePiece = new component(40, 28, "red", 10, 120, "sprite"); myGamePiece.gravity = 0.05; myScore = new component("30px", "Consolas", "black", 280, 40, "text"); myGameArea.start(); } var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.frameNo = 0; this.interval = setInterval(updateGameArea, 20); }, clear : function() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y, type) { this.type = type; this.score = 0; this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.gravity = 0; this.gravitySpeed = 0; if (type === "sprite") { this.currentFrame = 0; this.frames = 2; this.tickCount = 0; this.ticksPerFrame = 4; this.image = new Image(); this.image.src = 'http://s28.postimg.org/k90gybbtl/bird_Sprite.png'; } this.update = function() { ctx = myGameArea.context; if (this.type == "text") { ctx.font = this.width + " " + this.height; ctx.fillStyle = color; ctx.fillText(this.text, this.x, this.y); } else if (this.type == "sprite") { if (this.tickCount > this.ticksPerFrame) { ctx.drawImage(this.image, 0, this.height * this.currentFrame, this.width, this.height, this.x, this.y, this.width, this.height); this.tickCount = 0; if (this.currentFrame == this.frames) { this.currentFrame = 0; } else { this.currentFrame++; } } else { ctx.drawImage(this.image, 0, this.height * this.currentFrame, this.width, this.height, this.x, this.y, this.width, this.height); this.tickCount++; } } else { ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } } this.newPos = function() { this.gravitySpeed += this.gravity; this.x += this.speedX; this.y += this.speedY + this.gravitySpeed; this.hitBottom(); } this.hitBottom = function() { var rockbottom = myGameArea.canvas.height - this.height; if (this.y > rockbottom) { this.y = rockbottom; this.gravitySpeed = 0; } } this.crashWith = function(otherobj) { var myleft = this.x; var myright = this.x + (this.width); var mytop = this.y; var mybottom = this.y + (this.height); var otherleft = otherobj.x; var otherright = otherobj.x + (otherobj.width); var othertop = otherobj.y; var otherbottom = otherobj.y + (otherobj.height); var crash = true; if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) { crash = false; } return crash; } } function updateGameArea() { var x, height, gap, minHeight, maxHeight, minGap, maxGap; for (i = 0; i < myObstacles.length; i += 1) { if (myGamePiece.crashWith(myObstacles[i])) { return; } } myGameArea.clear(); myGameArea.frameNo += 1; if (myGameArea.frameNo == 1 || everyinterval(150)) { x = myGameArea.canvas.width; minHeight = 20; maxHeight = 200; height = Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight); minGap = 50; maxGap = 200; gap = Math.floor(Math.random()*(maxGap-minGap+1)+minGap); myObstacles.push(new component(10, height, "green", x, 0)); myObstacles.push(new component(10, x - height - gap, "green", x, height + gap)); } for (i = 0; i < myObstacles.length; i += 1) { myObstacles[i].x += -1; myObstacles[i].update(); } myScore.text="SCORE: " + myGameArea.frameNo; myScore.update(); myGamePiece.newPos(); myGamePiece.update(); } function everyinterval(n) { if ((myGameArea.frameNo / n) % 1 == 0) {return true;} return false; } function accelerate(n) { myGamePiece.gravity = n; } 
 canvas { border:1px solid #d3d3d3; background-color: #f1f1f1; } 
 <body onload="startGame()"> <br> <button onmousedown="accelerate(-0.2)" onmouseup="accelerate(0.05)">ACCELERATE</button> <p>Use the ACCELERATE button to stay in the air</p> <p>How long can you stay alive?</p> </body> 

In summary: 综上所述:

  • Within the component function we initialise variables to handle the sprite animation if the type parameter is set to sprite 如果type参数设置为sprite则在component函数中我们初始化变量以处理sprite动画
  • Within the update function we only draw the next frame of the sprite animation every 4th time update is called. update函数中,我们仅在每4次调用一次update绘制一次sprite动画的下一帧。 This ensures that the sprite animation doesn't play to quickly 这样可以确保精灵动画不会快速播放
  • We then increment or reset the currentFrame count the same as you did before in your original code 然后,我们以与原始代码相同的方式递增或重置currentFrame计数
  • If we're not ready to display the next frame in the sprite animation, we just display the existing frame again. 如果我们不准备在Sprite动画中显示下一帧,则只需再次显示现有帧。

To take it further you might want to consider refactoring my solution so that the sprite is a separate "class" which inherits it's core functionality from component . 为了更进一步,您可能需要考虑重构我的解决方案,以使Sprite是一个单独的“类”,该类从component继承其核心功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM