2017-11-19 3 views
0

私は、タイル張りの背景を必要とするミニゲーム、私がpngタイルセット(16x16タイル)から選択するタイルに取り組んでいます。タイルが16x16であっても、スプライトシートのキャンバスに32x32のタイルとして表示されます(下のコードを参照)。 タイルのサイズを人為的に大きくすると、隣にあるタイルの小さな部分が必要になると思われます。画像は言葉よりも良いそれを記述するかもしれません:あなたは水の一部で見ることができるタイルがキャンバスに正しく表示されない

Zoom on the background

を、ここではすべきではないピンクがかったラインは、そこにある(私は、タイルセットには分離がなかったことを確認0,0は私が信じる正しい場所にあります)。私も、バックグラウンドのために、タイルのネイティブサイズ(代わりに32×32の16×16)を使用しようとした、何のピンクの線が見られないし、また、灰色のグリッドが消えた:

ので、私はそれはから来ていると思います

loadImage('/img/dungeon.png') 
.then(image => { 
    const sprites = new SpriteSheet(image, 16, 16); 
    sprites.define('stone_floor', 1, 0, 32, 32); 
    sprites.define('water', 2, 7, 32, 32); 
    sprites.define('wall_top', 2, 0, 32, 32); 
    sprites.define('void', 0, 0, 32, 32); 
    sprites.define('stone_floor&water', 3, 7, 32, 32); 

    loadLevel('1-2') 
    .then(level => { 
    drawBackground(level.background, context, sprites); 
    }) 
}); 

SpriteSheetクラス:

class SpriteSheet { 
    constructor(image, width, height, offset = 0){ 
    this.image = image; 
    this.width = width; 
    this.height = height; 
    this.offset = offset; 
    this.tiles = new Map(); 
    } 
    define(name, x, y, imgw, imgh){ 
    const buffer = document.createElement('canvas'); 
    buffer.width = imgw; 
    buffer.height = imgh; 
    buffer 
     .getContext('2d') 
     .drawImage(this.image, 
        x * this.width + x*this.offset, y * this.height + y*this.offset, 
        this.width, this.height, 
        0, 0, imgw, imgh); 
    this.tiles.set(name, buffer); 
    } 
    draw(name, context, x, y){ 
    const buffer = this.tiles.get(name); 
    context.drawImage(buffer, x, y); 
    } 
    drawTile(name, context, x, y){ 
    const buffer = this.tiles.get(name); 
    context.drawImage(buffer, x * buffer.width, y * buffer.height); 
    } 
} 
×32、しかし、私はそれを修正する方法が分からない... ここでは、私はタイルセットをロードし、背景を表示するために使用したコードです

PS:このプロジェクトは非常にMethMethMethodのチュートリアルに基づいています。Blindman67さんのコメント@に基づいてvideo

+1

隣接するタイルからのブリードは、タイルを拡大縮小するときの双線形フィルタリングによるものです。簡単な解決策は、タイルの双線形フィルタリングを切り替えることです。 'ctx.imageSmoothingEnabled = false;'フィルタリングを維持したいのであれば、唯一の選択肢は、タイルの周りに縁の色を合わせるために境界線を追加することによって、タイルのサイズを18倍に増やすことです。あなたはまだ16 * 16のタイルをレンダリングするだけですが、フィルタリングは隣接するタイルではなく境界ピクセルからサンプリングされます – Blindman67

+0

@ Blindman67にコメントしてくれてありがとう、私は両方の方法を試してみると思います。より複雑な実装に!バイリニアフィルタリングをオフにすることには、顕著な欠点がありますか? – Alivanar

+0

外見とは別に欠点はなく、あなたのゲームスタイルに合っているかどうかを見なければなりません。スムージングの最悪のFXは、エイリアシングアーティファクトを取得し始めるときにイメージサイズを小さくするときです。いくつかの(下端)ハードウェアでは、スムーズにするとパフォーマンスが少し向上します。 – Blindman67

答えて

0

:あなたがタイルアップを拡張する際

隣接タイルからの出血が原因バイリニアフィルタリングにあります。簡単な解決策は、タイルの双線形フィルタリングを切り替えることです。 ctx.imageSmoothingEnabled = false;フィルタリングを維持したい場合は、唯一の方法は、タイルの周りにエッジカラーを合わせるためにタイルの周りに境界線を追加することによって、タイルサイズを18で18に増やすことです。それでも16 * 16のタイルをレンダリングするだけですが、フィルタリングは隣接するタイルではなく境界ピクセルからサンプリングされます。

提案された最初のオプションは機能しませんでした(イメージスムージングをオフにする)が、問題を解決できました。私はそれが最初に同じタイル、16×16で1枚の18×18のタイルを重ねることによって18x18pxバッファ・イメージを作成しますように、私のspriteSheetクラスを変更するために管理し、センタリング:

defineTile(name, x, y, imgw, imgh) { 
    const img_buffer = document.createElement('canvas'); 
    img_buffer.width = this.width + 4; 
    img_buffer.height = this.height + 4; 
    img_buffer 
     .getContext('2d') 
     .drawImage(this.image, 
     x * this.width + x * this.offset, y * this.height + y * this.offset, 
     this.width, this.height, 
     0, 0, this.width + 4, this.height + 4); 
    img_buffer 
     .getContext('2d') 
     .drawImage(this.image, 
     x * this.width + x * this.offset, y * this.height + y * this.offset, 
     this.width, this.height, 
     2, 2, this.width, this.height); 

    const buffer = document.createElement('canvas'); 
    buffer.width = imgw; 
    buffer.height = imgh; 
    buffer 
     .getContext('2d') 
     .drawImage(img_buffer, 
     2, 2, 
     this.width, this.height, 
     0, 0, imgw, imgh); 
    this.tiles.set(name, buffer); 
    } 

を、これはほとんどの場合、私は知らないにもかかわらず、それを行う最適化された方法、それはうまくやっている!私はこの部分をもちろんより良いものにすることができる提案には開放されていますが、私は問題が解決したと考えています。

関連する問題