お知らせ

ただいま、シンタックスハイライターの設定を見直しております。
プログラムが見にくくなっているページがありますが、ご容赦ください。

JavaScriptで雪を降らせてみた

プログラミング

あけましておめでとうございます。本年もよろしくお願いいたします。

絵心がなくうまく絵が描けないので、JavaScriptで絵を描いて見ることにしました。今回はほとんど解説なしです。

画面上で雪を降らせてみた

実際の雪の動きには近くないのですが、揺れながら降ってくる様子を出してみました。下のリンクから実際に動くページがみられると思います。ちなみに放置すると、雪が積もってしまいます。

雪を降らせてみた

雪を降らせるプログラム

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Snow man</title>
		<style>
			#canvas {
				background: #000;
			}
		</style>
	</head>
	<body>
		<canvas id="canvas" width="640" height="480"></canvas>
		<form id="form">
			雪の数:<span id="countOfSnow">500</span>
			<input type="button" value="↓" onclick="snow(-10)">
			<input type="button" value="↑" onclick="snow(+10)"> <br />

			風:<span id="windSpeed">0</span>
			<input type="button" value="←" onclick="wind(-1)">
			<input type="button" value="→" onclick="wind(+1)">
		</form>

		<script>
			var canvas = document.getElementById('canvas');
			var ctx = canvas.getContext('2d');
			var canvasWidth = canvas.width;
			var canvasHeight = canvas.height;

			var itvEvt;
			var fps = 60;
			
			var snowCount;
			var arrayImage = [];
			var maxSnow = 1000;
			var fallSnow = 0;

			var windSpeed;
			var maxWind = 20;

			init();

			function init(){
				snowCount = parseInt(
					document.getElementById('countOfSnow').textContent);
				windSpeed = parseInt(
					document.getElementById('windSpeed').textContent);

				for( var i=0; i<snowCount; i++ ){
					arrayImage.push({
						"x" : Math.random() * canvasWidth,
						"y" : Math.random() * canvasHeight,
					});
				}
				clearInterval( itvEvt );
				itvEvt = setInterval( draw, 1000/fps );
			}

			function draw(){
				ctx.clearRect( 0, 0, canvasWidth, canvasHeight );
				drawSnowman();
				ctx.fillStyle = 'rgb( 255, 255, 255 )';
				ctx.fillRect( 0, canvasHeight-fallSnow/100, canvasWidth, fallSnow/100 );
				drawSnow();
			}

			function drawSnow() {
				ctx.fillStyle = 'rgb( 255, 255, 255 )';
				for( var i=0; i<snowCount; i++ ){
					arrayImage[i].x += Math.random()*2 -1 +windSpeed;
					arrayImage[i].y += Math.random()*1.5;

					arrayImage[i].x = ( arrayImage[i].x +canvasWidth ) % canvasWidth;

					if( arrayImage[i].y > canvasHeight ){
						arrayImage[i].x = Math.random() * canvasWidth;
						arrayImage[i].y = -3;
						fallSnow++;
					}

					ctx.beginPath();
					ctx.arc( arrayImage[i].x, arrayImage[i].y, 3, 0, 2*Math.PI, false );
					ctx.fill();
				}
			}

			function drawSnowman(){
				ctx.beginPath();
				ctx.fillStyle = 'rgb( 255, 255, 255)';
				ctx.arc( 500, 350, 50, 0, 2*Math.PI, false );	//頭
				ctx.arc( 500, 440, 70, 0, 2*Math.PI, false );	//胴
				ctx.fill();

				ctx.beginPath();
				ctx.fillStyle = 'rgb( 231, 126, 49 )';
				ctx.arc( 500, 350, 7, 7, 0, 2*Math.PI, false );//鼻
				ctx.fill();

				ctx.beginPath();
				ctx.lineWidth = 3;
				ctx.strokeStyle = 'rgb( 0, 0, 0 )';
				ctx.arc( 485, 335, 5 , 0, Math.PI, true );		//左目
				ctx.stroke();

				ctx.beginPath();
				ctx.strokeStyle = 'rgb( 0, 0, 0 )';
				ctx.arc( 515, 335, 5 , 0, Math.PI, true );		//右目
				ctx.stroke();

				ctx.beginPath();
				ctx.lineWidth = 5;
				ctx.strokeStyle = 'rgb( 255, 0, 0 )';					//口
				ctx.arc( 500, 350, 25 , 45*Math.PI/180, 135*Math.PI/180, false );
				ctx.stroke();

				ctx.translate( 500, 350 );
				ctx.rotate( 15 * Math.PI/180 );
				ctx.fillStyle = 'rgb( 0, 0, 255 )';
				ctx.fillRect( -30, -57, 60, 14 );		//バケツのふち
				ctx.fillRect( -20, -87, 40, 30 );		//バケツ本体
				ctx.rotate( -15 * Math.PI/180 );
				ctx.translate( -500, -350 );
			}

			function snow( num ){
				if( 0<=snowCount+num && snowCount+num<=maxSnow ){
					snowCount += num;
					document.getElementById('countOfSnow').innerHTML = snowCount;
					init();
				}
			}

			function wind( num ){
				if( -maxWind<=windSpeed+num && windSpeed+num<=maxWind ){
					windSpeed += num;
					document.getElementById('windSpeed').innerHTML = windSpeed;
					init();
				}
			}

		</script>
	</body>
</html>

長いように見えるけれど、87~123行目で雪だるまを描いていて、これが36行もあるのが原因のような気がします。

今回はこれでおしまいにします。それでは、また。

この記事を書いた人
春日井 優

高校で情報科という教科を担当しています。以前は数学科も担当していました。(今でも数学科の教員免許状は有効です。)プログラムを覚えたのは、「ゲームセンターあらし」という漫画のキャラクターがBASICを解説する「こんにちはマイコン」を読んだことがきっかけでした。

Posted by kasugai