not good but great

プログラミング、アート、映画・本の感想について書きます。

JavascriptでKeyの同時押しを判定する

demo


codepenを見ていたら、綺麗なグラデーションでパーティクルが回るデモがあった。
Canvas Sparkle Light Trail

これを参考にシューティングゲームみたいなものを作れないかなと思った。しかし途中で挫折したww
プレイヤーから弾が出るところまでは作ったが、敵を作ったり、もっと画像などを使ってリアルにするのにはすごく時間がかかると思ってやめた。一切のゲームライブラリを使わずに作るのはしんどい。このままゴミ箱に捨てるのはもったいないので、やったことをメモしようと思う。

Keyの同時押しを判定する

・参考
018.Javascriptでキーの同時押しを制御する - West in the Far East
JavaScript Two key pressed at the same time - Stack Overflow

普通に上下左右のキーが押されたら、プレイヤーの位置を移動させるという処理を、switch文で書くと、同時押しの判定が出来ない。例えば上と右を両方押すと、先に押された方へ進む。

keyup,keydownを使う

document.addEventListener("keydown",onKeyDown,false);
document.addEventListener("keyup",onKeyUp,false);

イベントリスナを設定して、キーが押された時、離された時に関数が実行されるようにする。

pressedKeys = [],
    onKeyDown = function(e){
		switch(e.keyCode){
			case 38://up
			case 87://w
				pressedKeys[0] = true;
				break;
			case 40://down
			case 65://a
				pressedKeys[1] = true;
				break;
			case 37://left
			case 83://s
				pressedKeys[2] = true;
				break;
			case 39://right
			case 68://d
				pressedKeys[3] = true;
				break;
			case 32://shoot
				pressedKeys[4] = true;
				break;
			default:
				break;
		}
    },

矢印キーかWASDキーが押されると、用意した配列にtrueを入れる。配列の番号をkeycodeにする方法もできるけど、矢印キーとWASDキー両方が同じ操作をすることを考えると、混同するので止めることにした。4つしか操作がないので、一つずつ、ここでは設定している。

onKeyUp = function(e){
		switch(e.keyCode){
			case 38://up
			case 87://w
				pressedKeys[0] = false;
				break;
			case 40://down
			case 65://a
				pressedKeys[1] = false;
				break;
			case 37://left
			case 83://s
				pressedKeys[2] = false;
				break;
			case 39://right
			case 68://d
				pressedKeys[3] = false;
				break;
			case 32://shoot
				pressedKeys[4] = false;
				break;
			default:
				break;
		}
    },

キーが離されたら配列にflaseを代入している。

movePlayer = function(){

	    //up
	    if(pressedKeys[0] && player.y - player.radius > 0){
		    player.y -= player.speed;
	    }

	    //down
	    if(pressedKeys[1] && player.y + player.radius < ch){
		    player.y += player.speed;
	    }

	    //left
	    if(pressedKeys[2] && player.x - player.radius > 0){
		    player.x -= player.speed
	    }

	    //right
	    if(pressedKeys[3] && player.x + player.radius < cw){
		    player.x += player.speed;
	    }

	    if(pressedKeys[4]){
		    createParticles();
	    }

    },
loop = function(){
	//途中省略
	movePlayer();
	//途中省略
}

setInterval(loop, 16);

プレイヤーを動かす、movePlayer関数を作って、ループさせている。

無駄な弾丸を消す

弾丸が画面の外に出たら、必要ないので消してメモリを節約する。具体的には弾丸が入った配列の要素を消す。

spliceを使って、要素を一つだけ消して、詰めれば良い。
JavaScriptの配列の要素を削除する(delete演算子とspliceメソッド) | 山本隆の開発日誌

updateParticles = function(){
  var i = particles.length;
  while(i--){
  	var p = particles[i];
	if(p.x < cw){//画面内
		//速度の分だけ右に進む
		p.x += p.vx;
	}else{//画面外
		//配列から消去する
		particles.splice(i,1);
	}
  }
},

Canvasの新しく知った使い方

globalCompositeOperation

これは二つの図形が重ね合ったときに、どうやって描画するのか設定できる。初期設定では上塗りされるようになっている。
globalCompositeOperation プロパティ - Canvasリファレンス - HTML5.JP

ctx.globalCompositeOperation = 'xor';

例えばxorだと、重なっている部分は透明になる。

lineCap

これは線の終端の形状を決めるプロパティ。
lineCap プロパティ - Canvasリファレンス - HTML5.JP

ctx.lineCap = "round";

この場合、先が丸くなる。

個人的には先が三角にできればいいのになあと思った。