JavaScript:雪が降る(canvasで複数画像を回転)

JavaScript:雪が降る(canvasで複数画像を回転) JavaScript

前回の記事「JavaScript:canvasで画像のみその場で回転させる」を参考にcanvas上で複数の雪の画像を回転させるJavaScriptを作った。

前回の記事

JavaScript:canvasで画像のみその場で回転させる
canvasで画像のみその場で回転させ、他の要素はそのまま表示させるJavaScriptプログラム。

サンプルを見る

基本的に雪クラス(Snow関数)に機能を集約してある。
オブジェクト作成時に落下速度やゆれ具合をランダム設定している。回転の向き(右回りか左回りか)もランダム設定。

/*
 * 雪クラス
 */
var Snow = function(sx, sy, _image){
	var speed = Math.floor(Math.random() * 5) + 1;	// 落下速度 1~5
	var yure = Math.floor(Math.random() * 3) + 1;	// ゆれ 1~3
	// 雪の初期位置
	var x = sx;
	var y = sy;
	var _angle = Math.floor(Math.random() * 2) ? yure : -yure;	// 回転角度はゆれに応じる(向きはランダム)
	var angle = _angle;
	var rad = 0;		// ラジアンに変換用
	var image = new Image();
	image = _image;
	// 雪が降る
	this.move = function(){
		// 角度をラジアンに変換
		rad = angle * Math.PI/180; 
		// 今の状態を保存する
		g.save();
		// 回転の中心点を計算
		var cx = x + _image.width/2;
		var cy = y + _image.height/2;
		// 画像を中心にして回転
		g.setTransform(Math.cos(rad), Math.sin(rad), -Math.sin(rad), Math.cos(rad),cx-cx*Math.cos(rad)+cy*Math.sin(rad),cy-cx*Math.sin(rad)-cy*Math.cos(rad));
		// 雪を描く
		g.drawImage(_image, x, y);

		g.restore();
		
		// 回転角を変化させる
		angle += _angle;
		if(angle > 360) angle = 0;

		// 雪の軌跡を計算
		x = x + Math.sin((y + speed) * Math.PI/180) * yure;
		y = y + speed;
		if(y > SCREEN_HEIGHT){
			return false;
		}
		return true;
	};
};

ソースコード全体
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="snow.js"></script>
<title>snowy3</title>
<style>
#canvas {
	border: solid 1px #000;
	margin: 32px;
}
</style>
 
</head>
<body>
	<canvas id="canvas" width="320" height="480"></canvas>
</body>
</html>

JavaScript

// -------------------------------------------------------------------------
// snow.js 雪がたくさん降る3(画像を回転させて落下)
//
// 					created at 2014-1-7 on torisky.com
// -------------------------------------------------------------------------

/*
 * グローバル変数
 */
var canvas = null;					// キャンバス
var g = null;						// コンテキスト
var $id = function(id){ return document.getElementById(id); };
var title;							// タイトル文字列
var objectList = [];				// 雪オブジェクト管理用
var probability;					// 雪の発生確率
var imgSnow = new Image();		// 雪の画像用
var imgButa = new Image();		// ブタの画像用

/*
 * 定数
 */
var SCREEN_WIDTH = 320;
var SCREEN_HEIGHT = 480;
var TICK = 1000/30;
var IMG_SNOW = "snow32.png";
var IMG_BUTA = "buta.png";

/*
 * リセット関数
 */
var reset = function(){
	title = "snowy";
	objectList = [];
	probability = 0.95;	// 雪の発生確率
	// 雪の画像生成
	imgSnow.src = IMG_SNOW;
	imgSnow.onload = function(){
		g.drawImage(imgSnow, -1000, -1000);
	};
	// ブタの画像生成(おまけ)
	imgButa.src = IMG_BUTA;
	imgButa.onload = function(){
		g.drawImage(imgButa, -1000, -1000);
	};
	
	g.clearRect(0, 0, canvas.width, canvas.height);
};

/*
 * 情報表示
 */
var showInformation = function(){
	g.fillStyle = "rgba(0, 0, 0, 0.5)";
	g.fillText(title, 145, SCREEN_HEIGHT/ 2);
	g.fillText("ObjectList: " + objectList.length, 24, 24);
	var kakuritu = Math.floor(100-(probability*100));
	g.fillText(kakuritu + "%     <- Click to change!", 24, 48);
};

/*
 * オブジェクト追加関数
 */
var addObject = function(obj){
	for(var i=0; i<objectList.length+1; i++){
		if(objectList[i] == null){
			objectList[i] = obj;
			console.log("addObject() " + i);
			break;
		}
	}
};

/*
 * 雪クラス
 */
var Snow = function(sx, sy, _image){
	var speed = Math.floor(Math.random() * 5) + 1;	// 落下速度 1~5
	var yure = Math.floor(Math.random() * 3) + 1;	// ゆれ 1~3
	// 雪の初期位置
	var x = sx;
	var y = sy;
	var _angle = Math.floor(Math.random() * 2) ? yure : -yure;	// 回転角度はゆれに応じる(向きはランダム)
	var angle = _angle;
	var rad = 0;		// ラジアンに変換用
	var image = new Image();
	image = _image;
	// 雪が降る
	this.move = function(){
		// 角度をラジアンに変換
		rad = angle * Math.PI/180; 
		// 今の状態を保存する
		g.save();
		// 回転の中心点を計算
		var cx = x + _image.width/2;
		var cy = y + _image.height/2;
		// 画像を中心にして回転
		g.setTransform(Math.cos(rad), Math.sin(rad), -Math.sin(rad), Math.cos(rad),cx-cx*Math.cos(rad)+cy*Math.sin(rad),cy-cx*Math.sin(rad)-cy*Math.cos(rad));
		// 雪を描く
		g.drawImage(_image, x, y);

		g.restore();
		
		// 回転角を変化させる
		angle += _angle;
		if(angle > 360) angle = 0;

		// 雪の軌跡を計算
		x = x + Math.sin((y + speed) * Math.PI/180) * yure;
		y = y + speed;
		if(y > SCREEN_HEIGHT){
			return false;
		}
		return true;
	};
};

/*
 * マウスクリック/タッチ時の処理
 */
var ontouch = function(x, y){
	var kakuritu = Math.floor(Math.random() * 100) + 1;
	kakuritu /= 100;
	probability = kakuritu;
};

/*
 * メイン処理
 */
var mainLoop = function(){
	g.fillStyle = "rgb(200, 200, 200)";
	g.fillRect(0, 0, canvas.width, canvas.height);
	showInformation();
	// オブジェクトの動作と消去
	for(var i=0; i<objectList.length; i++){
		var obj = objectList[i];
		if(obj && !obj.move()){
			delete objectList[i];
		}
	}
	// 雪の生成
	if(Math.random() > probability){
		if(Math.random() > 0.99){		// ときどきブタ!
			addObject(new Snow(Math.random() * SCREEN_WIDTH, 0-Math.random()*150, imgButa));
		}
		else{
			addObject(new Snow(Math.random() * SCREEN_WIDTH, 0-Math.random()*150, imgSnow));
		}
	}
	setTimeout(mainLoop, TICK);
};

/*
 * 起動処理
 */
window.onload = function(){
	// キャンバス情報取得
	canvas = $id("canvas");
	g = canvas.getContext("2d");

	// 雪を降らせる
	reset();
	mainLoop();
	// タッチイベント処理
	canvas.onmousedown = function(e){
		ontouch(e.clientX, e.clientY);
	};
	canvas.ontouchstart = function(e){
		if(e.touches[0]){
			ontouch(e.touches[0].clientX, e.touches[0].clientY);
		}
		e.preventDefault();
	};

};

コメント

タイトルとURLをコピーしました