代码之家  ›  专栏  ›  技术社区  ›  Romano

Typescript精灵动画

  •  0
  • Romano  · 技术社区  · 10 年前

    我正在制作一款小型马里奥游戏。

    但我不知道如何制作精灵动画。例如,我有一只正在奔跑的马里奥。gif文件(mario不在gif中运行)

    Click here for the mario picture.

    图片是60 x 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,它会选择下一个马里奥图像。相反,它给了我两张照片中的马里奥跑鞋。
    它是如何工作的?如何选择马里奥的每个跑步阶段?


    如果完成了,是否应该使用for循环和计时器来设置精灵的动画?对我来说,这似乎不是最好的做法。因为我有更多的精灵需要动画,而只有马里奥和跑步。

    2 回复  |  直到 10 年前
        1
  •  1
  •   Markus Jarderot    10 年前

    签名: 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();
        }
    }
    
        2
  •  0
  •   Romano    10 年前
        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);
        }
    
    }
    

    通过使用sprite this.sprite.height this.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;      
        }
    
    }
    

    如果Mario正在运行,则使用另一个帧数。运行mario在gif中有4个图像。将numberOfFrames设为4。

    推荐文章