静岡理工科大学 菅沼ホーム JavaScript 目次 基礎技術目次 索引

背景(マップ)

  1. マップの使用

      アニメーションやゲームにおいて,背景画像上で様々なターゲットを移動させたいような場合が存在します.その際,ターゲットと共に背景画像自体を移動するような場合も少なくありません.それを実現する一つの方法は,大きな背景画像を準備し,それを背景として使用することです.しかし,そのようにすると,ターゲットと背景画像の位置関係を明確にするのが面倒になります.

      そこでよく使用されるのが,全体を格子状に区切り,区切られた各ブロックに適切な画像を配置したり,画像を描画することによって背景を構成する方法です.このようにすれば,ターゲットが格子内のどこに存在するかによって,背景画像との位置関係を知ることができ,障害物等に対する処理も容易になります.

      背景の例は,12 行 × 26 列の格子内に 2 種類の画像は配置し,横方向に移動した例です.以下にそのプログラムを示します.このプログラムは,跳ね返りと乱数の章におけるもう一つの例と同様,新しいオブジェクトを生成し,変数や関数をそのオブジェクト内で定義し,それらをグローバル変数のような形では直接参照できないようにしています.

    01	<!DOCTYPE HTML>
    02	<HTML>
    03	<HEAD>
    04		<TITLE>背景(マップ)</TITLE>
    05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    06		<LINK REL="stylesheet" TYPE="text/css" HREF="../../master.css">
    07		<SCRIPT TYPE="text/javascript">
    08			canvas  = null;
    09			ctx     = null;
    10			mp      = null;
    11			timerID = -1;
    12	
    13			function start()
    14			{
    15								// キャンバス情報
    16				canvas = document.getElementById('canvas_e');   // キャンバス要素の取得
    17				ctx    = canvas.getContext('2d');   // キャンバスからコンテキストを取得
    18								// Map オブジェクト
    19				mp = new Map();
    20								// タイマーのスタート
    21				timerID = setInterval('draw()', 30);
    22			}
    23						// 描画
    24			function draw()
    25			{
    26								// キャンバスのクリア
    27				ctx.clearRect(0, 0, canvas.width, canvas.height);
    28								// 移動
    29				mp.x += mp.v_x;
    30								// 背景の描画
    31				for (var i1 = 0; i1 < mp.col; i1++) {
    32					var x = mp.x + mp.width * i1;
    33					if (x + mp.width >= 0 && x <= canvas.width) {
    34						for (var i2 = 0; i2 < mp.row; i2++) {
    35							if (mp.map[i2][i1] > 0) {
    36								var y = i2 * mp.height;
    37								ctx.drawImage(mp.image[mp.map[i2][i1]-1], x, y);
    38							}
    39						}
    40					}
    41				}
    42			}
    43						// Map オブジェクト(プロパティ)
    44			function Map()
    45			{
    46								// 画像の配置
    47				this.map = new Array();
    48				this.map[0] = new Array(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);
    49				this.map[1] = new Array(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);
    50				this.map[2] = new Array(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);
    51				this.map[3] = new Array(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);
    52				this.map[4] = new Array(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);
    53				this.map[5] = new Array(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);
    54				this.map[6] = new Array(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);
    55				this.map[7] = new Array(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);
    56				this.map[8] = new Array(1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2);
    57				this.map[9] = new Array(1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2);
    58				this.map[10] = new Array(1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2);
    59				this.map[11] = new Array(1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2);
    60				this.image = new Array();   // ブロック画像
    61				this.row = 12;   // ブロックの行数
    62				this.col = 26;   // ブロックの列数
    63				this.x = 0;   // 背景の位置
    64				this.v_x = -2;   // 背景の水平方向移動速度
    65				this.width = 25;   // ブロックの幅
    66				this.height = 25;   // ブロックの高さ
    67						// ブロック画像の読み込み
    68				this.image[0] = new Image();
    69				this.image[0].src = "obj1.jpg";
    70				this.image[1] = new Image();
    71				this.image[1].src = "obj2.jpg";
    72			}
    73		</SCRIPT>
    74	</HEAD>
    75	<BODY CLASS="white" STYLE="text-align: center" onLoad="start()">
    76		<H1>背景(マップ)</H1>
    77		<CANVAS ID="canvas_e" STYLE="background-color: #eeffee;" WIDTH="400" HEIGHT="300"></CANVAS>
    78	</BODY>
    79	</HTML>
    			
    19 行目

      Map オブジェクトを生成し,変数 mp に代入しています.

    29 行目

      マップを左に 2 ピクセル移動しています.このように,Map オブジェクトのプロパティは,mp.x,mp.v_x などのように,「 mp. 」を付加した形だけで参照可能です.

    31 行目

      この for 文によって,マップの各列に対して 32 行目~ 40 行目の処理が繰り返されます.

    32 行目

      i1 列にあるブロックの左端の x 座標です.

    33 行目

      この if 文で,i1 列にあるブロックがキャンバス内に存在するか否かをチェックしています.存在する場合は,以下の処理が実行されます.

    34 行目

      この for 文によって,マップの各行に対して 35 行目~ 38 行目の処理が繰り返されます.

    35 行目~ 38 行目

      マップのブロックの値が正である箇所に,指定された画像を描画しています.

    47 行目~ 59 行目

      12 行 26 列のマップを 2 次元配列を使用して定義しています.このように,配列を定義し( 47 行目),その各要素を再び配列として定義する(この例の場合は,初期設定も行っている)ことによって,2 次元配列を定義することができます.値が 0 の箇所には何も表示されず,1 または 2 の箇所には,画像が表示されます.

    61 行目~ 62 行目

      マップの行数と列数です.

    64 行目

      マップの移動速度です.

    65 行目~ 66 行目

      マップを構成するブロックの大きさです.

    68 行目~ 71 行目

      マップに必要な画像を読み込んでいます.

  2. もう一つの例

      この例では,マップを,繰り返し,切れ目なく表示しています.基本的には,同じマップを 2 つ用意して,それらの表示・非表示,及び,その位置を制御することによって実現しています.

    01	<!DOCTYPE HTML>
    02	<HTML>
    03	<HEAD>
    04		<TITLE>背景(マップ)</TITLE>
    05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    06		<LINK REL="stylesheet" TYPE="text/css" HREF="../../master.css">
    07		<SCRIPT TYPE="text/javascript">
    08			canvas  = null;
    09			ctx     = null;
    10			mp      = new Array();
    11			timerID = -1;
    12			dsp     = new Array(1, 0);
    13	
    14			function start()
    15			{
    16								// キャンバス情報
    17				canvas = document.getElementById('canvas_e');   // キャンバス要素の取得
    18				ctx    = canvas.getContext('2d');   // キャンバスからコンテキストを取得
    19								// Map オブジェクト
    20				mp[0]   = new Map();
    21				mp[1]   = new Map();
    22				mp[1].x = canvas.width;
    23								// タイマーのスタート
    24				timerID = setInterval('draw()', 30);
    25			}
    26						// 描画
    27			function draw()
    28			{
    29								// キャンバスのクリア
    30				ctx.clearRect(0, 0, canvas.width, canvas.height);
    31								// 移動
    32				for (var i1 = 0; i1 < 2; i1++) {
    33					var k = (i1 + 1) % 2;
    34					if (dsp[i1] > 0) {
    35						mp[i1].x += mp[i1].v_x;
    36						if (mp[i1].x + mp[i1].width * mp[i1].col <= canvas.width) {
    37							mp[k].x = mp[i1].x + mp[i1].width * mp[i1].col;
    38							dsp[k]  = 1;
    39						}
    40						else if (mp[i1].x + mp[i1].width * mp[i1].col <= 0)
    41							dsp[i1] = 0;
    42					}
    43				}
    44								// 背景の描画
    45				for (var i0 = 0; i0 < 2; i0 ++) {
    46					if (dsp[i0] > 0) {
    47						for (var i1 = 0; i1 < mp[i0].col; i1++) {
    48							var x = mp[i0].x + mp[i0].width * i1;
    49							if (x + mp[i0].width >= 0 && x <= canvas.width) {
    50								for (var i2 = 0; i2 < mp[i0].row; i2++) {
    51									if (mp[i0].map[i2][i1] > 0) {
    52										var y = i2 * mp[i0].height;
    53										ctx.drawImage(mp[i0].image[mp[i0].map[i2][i1]-1], x, y);
    54									}
    55								}
    56							}
    57						}
    58					}
    59				}
    60			}
    61						// Map オブジェクト(プロパティ)
    62			function Map()
    63			{
    64								// 画像の配置
    65				this.map = new Array();
    66				this.map[0] = new Array(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);
    67				this.map[1] = new Array(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);
    68				this.map[2] = new Array(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);
    69				this.map[3] = new Array(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);
    70				this.map[4] = new Array(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);
    71				this.map[5] = new Array(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);
    72				this.map[6] = new Array(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);
    73				this.map[7] = new Array(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);
    74				this.map[8] = new Array(1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2);
    75				this.map[9] = new Array(1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2);
    76				this.map[10] = new Array(1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2);
    77				this.map[11] = new Array(1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2);
    78				this.image = new Array();   // ブロック画像
    79				this.row = 12;   // ブロックの行数
    80				this.col = 26;   // ブロックの列数
    81				this.x = 0;   // 背景の位置
    82				this.v_x = -2;   // 背景の水平方向移動速度
    83				this.width = 25;   // ブロックの幅
    84				this.height = 25;   // ブロックの高さ
    85						// ブロック画像の読み込み
    86				this.image[0] = new Image();
    87				this.image[0].src = "obj1.jpg";
    88				this.image[1] = new Image();
    89				this.image[1].src = "obj2.jpg";
    90			}
    91		</SCRIPT>
    92	</HEAD>
    93	<BODY CLASS="white" STYLE="text-align: center" onLoad="start()">
    94		<H1>背景(マップ)</H1>
    95		<CANVAS ID="canvas_e" STYLE="background-color: #eeffee;" WIDTH="400" HEIGHT="300"></CANVAS>
    96	</BODY>
    97	</HTML>
    			
    10 行目

      2 つのマップを記憶するための配列です.

    12 行目

      各マップが表示されているか否かを表すための配列です(各要素を,1 と 0 で初期設定).1 が表示,0 が非表示状態であることを表します.初期状態では,ここに示すように,1 番目のマップだけが表示状態となっています.

    20 行目~ 22 行目

      同じ内容の 2 つの Map オブジェクトを生成し,配列 mp の各要素に代入し,2 番目のマップの位置をキャンバスの右外に設定しています.同じ内容のマップであるからと言って,

      mp[0] = new Map();
      mp[1] = mp[0];

    のようには記述しないでください.mp[0] に代入されるのは,生成されたオブジェクトのアドレスです.従って,上のように記述すると,mp[0] と mp[1] は,全く同じマップを示すことになってしまいます.ここで記憶したいのは,内容は同じであっても,異なるマップ(データ)である必要があります.さもないと,各マップの表示・非表示や位置を独立に制御できません.

    32 行目

      この for 文によって,各マップの表示・非表示や位置を制御しています.

    33 行目

      変数 k の値は,i1 が 0 の時は 1,1 の時は 0 になります.

    34 行目

      この if 文によって,マップ i1 が表示されているとき,35 行目~ 41 行目の処理が実行されます.

    36 行目~ 39 行目

      表示されているマップの右端がキャンバス内に入ったとき,あと一つのマップの位置をキャンバスの右端とし,表示状態にします.

    40 行目~ 41 行目

      表示されているマップの右端がキャンバスの左外に出たとき,マップを非表示状態にします.

    45 行目~ 59 行目

      表示されているマップに対してだけ,先ほどの例と同様,各ブロックに指定された画像を表示します.

静岡理工科大学 菅沼ホーム JavaScript 目次 基礎技術目次 索引