第22回【シューティング制作.2】


まずは動画を見てくださいね!
JavaScriptでシューティング制作です!
今回は骨格となるゲームループを作って星を表示させています。

ゲームループを作り星を動かします

//ゲームスピード(ms)
const GAME_SPEED = 1000/60;
...
...
setInterval( gameLoop , GAME_SPEED );
...
//ゲームループ
function gameLoop()
{
	//移動処理
	
	for(let i=0;i<STAR_MAX;i++)star[i].update();
	
	//描画処理
	
	con.fillStyle="black";
	con.fillRect(0,0,SCREEN_W,SCREEN_H);
	
	for(let i=0;i<STAR_MAX;i++)star[i].draw();
}
秒間60回の間隔でgameLoop関数を呼び出します。
この関数内ですべての処理を行うようにしています。
まずは星の移動と星の描画を置いて、星が動くようになりました。

仮想画面を作って転送する

//フィールド(仮想画面)
let vcan = document.createElement("canvas");
let vcon = vcan.getContext("2d");
vcan.width  = FIELD_W;
vcan.height = FIELD_H;
今までのcanとconと同様に、vcanとvconを作ります。
HTMLで作っていないcanvasなので、createElementで作ります。

...
		vcon.fillStyle=rand(0,2)!=0?"66f":"#8af";
		vcon.fillRect(x>>8,y>>8,this.sz,this.sz);
...
	vcon.fillStyle="black";
	vcon.fillRect(0,0,SCREEN_W,SCREEN_H);
...
星の描画、画面のクリアでconに描画していた所を、vconに変更しました。

	//仮想画面から実際のキャンバスにコピー
	con.drawImage( vcan ,0,0,SCREEN_W,SCREEN_H,
		0,0,CANVAS_W,CANVAS_H);
仮想画面に描画しただけでは画面に何も表示されないので、仮想画面からキャンバスへ転送します。


スクリーン(カメラ)の座標を作ります

//カメラの座標
let camera_x = 0;
let camera_y = 0;
...
		let x=this.x>>8;
		let y=this.y>>8;
		
		if( x<camera_x || x>=camera_x+SCREEN_W 
			|| y<camera_y || y>=camera_y+SCREEN_H )return;
		
		vcon.fillStyle=rand(0,2)!=0?"66f":"#8af";
		vcon.fillRect(x,y,this.sz,this.sz);
...
//仮想画面から実際のキャンバスにコピー
	con.drawImage( vcan ,camera_x,camera_y,SCREEN_W,SCREEN_H,
		0,0,CANVAS_W,CANVAS_H);
...
カメラの位置からスクリーンをキャンバスに転送しています。
ついでに無駄を省くため星がカメラの範囲外だった時は描画しないようにしてます。

次は自機を描画していきます。
続く...


ここまでのソースコード

main.js

//ゲームスピード(ms)
const GAME_SPEED = 1000/60;

//画面サイズ
const SCREEN_W = 180;
const SCREEN_H = 320;

//キャンバスサイズ
const CANVAS_W = SCREEN_W *2;
const CANVAS_H = SCREEN_H *2;

//フィールドサイズ
const FIELD_W = SCREEN_W *2;
const FIELD_H = SCREEN_H *2;

//星の数
const STAR_MAX =300;

//キャンバス
let can = document.getElementById("can");
let con = can.getContext("2d");
can.width  = CANVAS_W;
can.height = CANVAS_H;

//フィールド(仮想画面)
let vcan = document.createElement("canvas");
let vcon = vcan.getContext("2d");
vcan.width  = FIELD_W;
vcan.height = FIELD_H;

//カメラの座標
let camera_x = 0;
let camera_y = 0;

//星の実体
let star=[];

//整数のランダムを作る
function rand(min,max)
{
	return Math.floor( Math.random()*(max-min+1) )+min;
}

//星クラス
class Star
{
	constructor()
	{
		this.x  = rand(0,FIELD_W)<<8;
		this.y  = rand(0,FIELD_H)<<8;
		this.vx = 0;
		this.vy = rand(30,200);
		this.sz = rand(1,2);
	}
	
	draw()
	{
		let x=this.x>>8;
		let y=this.y>>8;
		
		if( x<camera_x || x>=camera_x+SCREEN_W 
			|| y<camera_y || y>=camera_y+SCREEN_H )return;
		
		vcon.fillStyle=rand(0,2)!=0?"66f":"#8af";
		vcon.fillRect(x,y,this.sz,this.sz);
		
	}
	
	update()
	{
		this.x += this.vx;
		this.y += this.vy;
		if( this.y>FIELD_H<<8 )
		{
			this.y=0;
			this.x=rand(0,FIELD_W)<<8;
		}
	}
	
}

//ゲーム初期化
function gameInit()
{
	for(let i=0;i<STAR_MAX;i++)star[i]= new Star();
	setInterval( gameLoop , GAME_SPEED );
}
//ゲームループ
function gameLoop()
{
	//移動の処理
	
	for(let i=0;i<STAR_MAX;i++)star[i].update();
	
	//描画の処理
	
	vcon.fillStyle="black";
	vcon.fillRect(0,0,SCREEN_W,SCREEN_H);
	
	for(let i=0;i<STAR_MAX;i++)star[i].draw();
	
	//仮想画面から実際のキャンバスにコピー
	
	con.drawImage( vcan ,camera_x,camera_y,SCREEN_W,SCREEN_H,
		0,0,CANVAS_W,CANVAS_H);
}

//オンロードでゲーム開始
window.onload=function()
{
	gameInit();
}




akichon/あきちょん
Youtubeでプログラミング講座やってるゲーム好きの(元?)プログラマ...
>>open profile...
■Twitter始めました
https://twitter.com/ak1chon
■Youtubeチャンネルはこちら
akichon(Youtube)