質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.78%

配列の表示する範囲を変えたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 219

nano_09

score 8

前提・実現したいこと

forで配列を全部読みこんだ上で、canvasの表示範囲を変えずに、配列の中の左上の5から右下の5で囲んだ四角形の範囲を表示することって可能でしょうか。
ご教授よろしくお願いします。

該当のソースコード

<!DOCTYPE html>
<html>
    <head>
       <meta charset="utf-8">
        <title>sample</title>
        <script src="../../jquery-3.5.1.min.js"></script>    
    </head>
    <body>
        <canvas id="canvas"></canvas>
        <script type="text/javascript" src="main.js"></script>
    </body>
</html>
var map = [
     [ 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 5],
];


function main(){
    var canvas = document.getElementById('canvas');
    canvas.width = 928;
    canvas.height = 448;

    var ctx = canvas.getContext('2d');

    var ground = new Image();
    ground.src = 'img/yuka1.png';

    ctx.fillStyle = "rgb( 0, 0, 0 )";

    ctx.fillRect(0, 0, 1056, 448);

        for (var y=0; y<map.length; y++) {
        for (var x=0; x<map[y].length; x++) {
            if (map[y][x] === 0)
                ctx.drawImage(ground,0,0,32,32,32*x,32*y,32,32);
        }
        }


    window.requestAnimationFrame( main );   
}
window.addEventListener('load', main(), false);

試したこと

当たり前ですがfor文のyやxの値を変えて、表示範囲がずれる訳ではなくただ指定されなかった部分が表示されないだけでした…。
表示範囲を変える関数やら変数を作ろうと思いましたが、よくわかりませんでした。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • firegrape

    2020/10/16 22:40

    id = 'canvas'
    の部分のhtmlはありますでしょうか。

    キャンセル

  • nano_09

    2020/10/16 22:45

    htmlはcanvasだけになります。

    キャンセル

回答 1

checkベストアンサー

+1

配列の中の左上の5から右下の5で囲んだ四角形の範囲を表示することって可能でしょうか。

可能です。

反復処理の練習にちょうどよい題材に思いましたので、直接的な回答は避けますが、
MAP全体のデータ(二次元配列)から、表示したい指定範囲の二次元配列を抽出して複製する関数を作れば対応しやすいのではないでしょうか。

map[Y][X] とアクセスされる場合、次のような関数で目的範囲のMAPデータを取得することができます。

const
  X_MAX = 33,
  Y_MAX = 14
;

function getSubMap( left, top, width=3, height=3 ) {
  let rect = [], tmp;
  if( top > Y_MAX - height ) {
    top = Y_MAX - height;
  }
  if( left > X_MAX - width ) {
    left = X_MAX - width;
  }

  for( let y = top; y < top+height; ++y ) {
    for( let x = left; x < left+width; ++x ) {
      if( x == left ) { rect.push(tmp=[]); }
      tmp.push( map[y][x] );
    }
  }
  return rect;
}

// 右方向の index 3, 下方向の index 0 から 3 x 3 の範囲を抽出する例
getSubMap( 3, 0 )
/*
=> [
  [0, 5, 0],
  [0, 0, 0],
  [0, 0, 0]
]
 */

追記)

getSubMap()をどう活用していいのかがいまいちわかっておりません

ご質問のコードでは、計算済みの値をハードコードしていますが、
変化しうる値は、変数やオブジェクトにするなどしてコンピュータに計算させます。
(単純計算はコンピュータの得意とするところです)。

ご質問の main() 関数をいじってみました。

var CHIP_WIDTH = 32;
var CHIP_HEIGHT = 32;
var IMG_CACHE = {}; // Image

var MAP_WIDTH = 8; // 928; = 32 * 29 だが、ここでは 8
var MAP_HEIGHT= 8; // 448 = 32 * 14 だが、ここでは 8

function main() {
  var canvas = document.getElementById('canvas');
  canvas.width = CHIP_WIDTH * MAP_WIDTH;
  canvas.height = CHIP_HEIGHT * MAP_HEIGHT;

  var ctx = canvas.getContext('2d');
      // canvas の width, height を受け付いだサイズ

  //var ground = IMG_CACHE["ground"];
  //ground.src = 'img/yuka1.png';
  if( ! "ground" in IMG_CACHE ) {
    IMG_CACHE["ground"] = new Image();
    IMG_CACHE["ground"].src = 'img/yuka1.png'; // サーバー問い合わせが起こる
  }

  // 黒色で完全に塗りつぶす
  ctx.fillStyle = "rgb( 0, 0, 0 )";
  ctx.fillRect(0, 0, CHIP_WIDTH*32, CHIP_HEIGHT*32);

  // (3,0)-(8,8) の範囲のマップデータを抽出する
  sub = getSubMap( 3, 0, MAP_WIDTH, MAP_HEIGHT );

  for (var y=0; y<sub.length; y++) {
    for (var x=0; x<sub[y].length; x++) {
      if (sub[y][x] === 0)
      ctx.drawImage(IMG_CACHE["ground"],
        0, 0,CHIP_WIDTH, CHIP_HEIGHT,
        CHIP_WIDTH*x,CHIP_HEIGHT*y,CHIP_WIDTH,CHIP_HEIGHT);
    }
  }

  window.requestAnimationFrame( main );
}

map はグローバルに宣言されていますので、 sub という変数で抽出したMAPデータを扱い、既にできていた2重の for ループのコードは、抽出したMAPの範囲で描画します。
他にも、グローバルに宣言した変数を増やしています。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/10/20 09:47

    上下移動に対応することって可能でしょうか。

    キャンセル

  • 2020/10/20 12:20

    できますよ。関数の引数に着目します。

    キャンセル

  • 2020/10/20 13:18

    sub = getSubMap( 3, 0, MAP_WIDTH, MAP_HEIGHT );
    の0の値を正に増加させると変わらなく、負の増加させると真っ暗になります。

    ここではないのでしょうか。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る