2016-05-15 115 views
0

我正在制作一个小型马里奥游戏。手写体精灵动画

但我不知道如何动画精灵。按照实施例,我有一个运行mario.gif文件(马里奥未在GIF捉迷藏)

Click here for the mario picture.

图片是60×20个像素。目前,这是我的代码。

class Character { 

    public y_: number; 
    public x_: number; 
    public nFrames: number = 30; 

    constructor(public _x: number, public _y: number) { 
     this._x = _x; 
     this._y = _y; 
    }; 

sprite: HTMLImageElement; 

    setSpriteUrl(input: string) : void { 
     this.sprite = new Image(); 
     this.sprite.src = input; 
    } 

drawSprite(): void { 
     ctx.save(); 
     ctx.beginPath(); 
     ctx.drawImage(this.sprite, 0, 0, 15, 20, this._x, this._y, 20, 20); 
      ctx.restore; 
     } 
} 

var mario = new Character(40, 50); 
mario.setSpriteUrl("graphics/mario/small/Running-mario.gif"); 

画面的宽度之后是60个像素,有4个运行马里奥的图像。图片的高度也是20像素。
60/4 = 15

ctx.drawImage(this.sprite, 0, 0, 15, 20, this._x, this._y, 20, 20); 

这会让我觉得它我可以从15到30,它会选择下一个马里奥的形象。相反,它让我从图片中跑出2个马里奥。
它是如何工作的?如何选择马里奥的每个运行阶段?


如果这样做了,精灵应该用for循环和定时器来动画吗?对我来说,这似乎不是最好的做法..因为我有更多的精灵动画,然后只有马里奥和跑步。

+0

考虑到你试图在画布上画一个GIF,我想你的问题可能是这个问题的重复http://stackoverflow.com/questions/3062229/animated-gif-in-html5-canvas – toskv

+1

在这个问题中,这个人问起他的动画gif。我的gif文件不是动画,而是一幅普通的图片(请参阅链接)。此人也可以回答图书馆。我不是在寻找一个图书馆,我想了解(教育目的) – Romano

+0

感谢您的澄清,我会收回我的近距离投票。 :) – toskv

回答

0
class Character { 

    frameWidth: number; 
    frameHeight: number; 
    tickCount: number; 
    ticksPerFrame: number = 1; 
    frameIndex: number; 
    jump: boolean; 

    constructor(public position: Vector, public numberOfFrames : number) {} 

    sprite: HTMLImageElement; 


    setSpriteUrl(input: string) : void { 
     this.sprite = new Image(); 
     this.sprite.src = input; 
    } 

    addGravity(): void { 

     this.position.y += downForce; 
     if (this.position.y >= 415) 
      this.position.y = 415; 
    } 

    drawSprite(): void { 

     this.tickCount = this.ticksPerFrame; 

     if (this.tickCount >= this.ticksPerFrame) { 
      this.tickCount = 0; 
      if (this.frameIndex < this.numberOfFrames - 1) { 
       this.frameIndex += 1; 
      } else { 
       this.frameIndex = 0; 
      } 
     } 

     this.frameHeight = this.sprite.height; 
     this.frameWidth = this.sprite.width/this.numberOfFrames; 

     this.position.setWidth(this.frameWidth); 
     this.position.getHeight(this.frameHeight); 
     ctx.drawImage(this.sprite, 
      this.frameIndex * this.frameWidth, 0, // Start of slice 
      this.frameWidth, this.frameHeight, // Size of slice 
      this.position.x, this.position.y, 15, 20); 
    } 

} 

通过使用精灵this.sprite.heightthis.sprite.width我可以有大小动态。这样我可以加载任何精灵。

和设置马里奥

var mario = new Character(new Vector(40,50), 4); 
mario.setSpriteUrl("graphics/mario/small/Standing-mario.gif"); 
mario.numberOfFrames = 1; 

numberOfFrames在这种情况下,只有1。由于站在马里奥GIF只有1中它的画面。

但是,如果马里奥正在运行。

function keyboardInput(event: KeyboardEvent) { 


    switch (event.keyCode) { 
     case 65: case 37: //a 
      mario.setSpriteUrl("graphics/mario/small/Running-mario-left.gif"); 
      mario.numberOfFrames = 4; 
      mario.position.x -= 10; 
      break; 

     case 38: case 87: //w 
      mario.numberOfFrames = 1; 
      mario.setSpriteUrl("graphics/mario/small/Jumping-mario.gif"); 
      if(mario.position.y < 415) { 
       return false; 
      } 
      mario.position.y -= 30; 
      break; 
     case 39: case 68: //d 
      mario.setSpriteUrl("graphics/mario/small/Running-mario.gif"); 
      mario.numberOfFrames = 4; 
      mario.position.x += 10; 
      break; 
     case 40: case 83: //s 
      mario.position.y += 20; 
      break; 
     case 32: //space 
      break; 
     default: 
      mario.setSpriteUrl("graphics/mario/small/Standing-mario.gif"); 
      mario.numberOfFrames = 1; 
      break;  
    } 

} 

如果马里奥正在运行,则使用另一个帧数。运行马里奥在gif内有4张图片。制作数字帧4.

0

drawImage签名是

ctx.drawImage(image, dx, dy) 
ctx.drawImage(image, dx, dy, dWidth, dHeight) 
ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy) 
ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) 

(sx, sy)是从哪里开始复印的源图像中的切片的开始位置。 (sWidth × sHeight)是该切片的大小。

由于你的精灵帧是水平的,所以你需要增加sx的值来绘制下一帧。

class Character { 

    frameWidth: number = 15; 
    frameHeight: number = 20; 

    constructor(
     public x: number, 
     public y: number) { } 

    sprite: HTMLImageElement; 

    setSpriteUrl(input: string) : void { 
     this.sprite = new Image(); 
     this.sprite.src = input; 
    } 

    drawSprite(frameIndex: number): void { 
     ctx.save(); 
     ctx.beginPath(); 
     ctx.drawImage(this.sprite, 
      frameIndex * this.frameWidth, 0, // Start of slice 
      this.frameWidth, this.frameHeight, // Size of slice 
      this.x, this.y);     // Destination position 
     ctx.restore(); 
    } 
} 
+0

函数'drawSprite'中的'ctx.save','beginPath'和'restore'函数没有做任何事情,并且在函数的任务方面是重用的。这些函数可能会增加相当大的开销,这在某些情况下会比调用drawImage要长很多。 – Blindman67

+0

谢谢!这帮了很多。我得到了动画的工作。我会将其作为最终答案发布。谢谢您的帮助 – Romano