幾何学計算アニメーションを作ってみよう

第1回 PHPで作る!簡単幾何学アニメ─不思議なプロペラ動画の作り方

この記事を読むのに必要な時間:およそ 4 分

プログラムですが,白の背景に,黒の長方形を描画しています。長方形を120°ずつ3回回転させると,次のようになります。これでプロペラができました。角度を変えれば,何枚羽根のプロペラでも作れますね。

画像 画像 画像

リスト2 プロペラの回転サンプル(rotate_2.php)

<?php

$frame = @$_GET["frame"] + 0;
if (($frame < 0)||($frame > 100))
	$frame = 0;
switch (@$_GET["mode"]) {
	case	"image":
		break;
	default:
		$nextframe = $frame + 1;
		print <<<EOO
<HTML><HEAD><TITLE>rotate.php</TITLE></HEAD><BODY>
<H1>rotate.php</H1>

<A href="?frame={$nextframe}"><IMG src="?frame={$frame}&mode=image"></A>

<HR>
</BODY></HTML>
EOO;
		die();
}

$width = 400;
$height = 400;
$g = imagecreate($width, $height);
$c0 = imagecolorresolve($g, 255, 255, 255);
$c1 = imagecolorresolve($g, 0, 0, 0);
imagefilledrectangle($g, 0, 0, $width, $height, $c0);

function	drawblade($g, $color, $a)
{
	global	$width, $height;
	
	$cx = $width / 2;
	$cy = $height / 2;
	$list = array(
		array(-20, -180), 
		array(20, -180), 
		array(20, 0), 
		array(-20, 0)
	);
	$points = array();
	$sin = sin($a * 3.14159 / 180);
	$cos = cos($a * 3.14159 / 180);
	foreach ($list as $p) {
		list($x, $y) = $p;
		$points[] = round($cx + $x * $cos - $y * $sin);
		$points[] = round($cy + $x * $sin + $y * $cos);
	}
	imagefilledpolygon($g, $points, count($points) / 2, $color);
}


drawblade($g, $c1, $frame * 10);
drawblade($g, $c1, $frame * 10 + 120);
drawblade($g, $c1, $frame * 10 + 240);

header("Content-Type: image/png");
imagepng($g);
imagedestroy($g);
?>

ちなみに,コマ送りの画像ができたら,ImageMagickなどを使うと動画ファイルに変換することができます。たとえば,

convert -delay 20 *.png test.mpeg

とすれば,200ミリ秒間隔のコマ送り動画ができます。数字は10ミリ秒単位で,出力を.gifにするとアニメーションGIFも作れます。またWindows専用ですが,JPG2AVIのようなフリーソフトも利用できると思います。

プロペラ回転+切り出しアニメの作成

では,いよいよ本命の,プロペラ回転+切り出しです。今回は時間がかかってもいいので,簡単な方法を選びました。

画像 画像 画像

リスト3 プロペラが回転しながら切り出されるサンプル(rotate_3.php)

<?php

$width = 400;
$height = 400;

$frame = @$_GET["frame"] + 0;
if (($frame < 0)||($frame > 100))
	$frame = 0;
switch (@$_GET["mode"]) {
	case	"image":
		break;
	default:
		$nextframe = $frame + 1;
		print <<<EOO
<HTML><HEAD><TITLE>rotate.php</TITLE></HEAD><BODY>
<H1>rotate.php</H1>

<A href="?frame={$nextframe}"><IMG src="?frame={$frame}&mode=image" width={$width} height={$height}></A>

<HR>
</BODY></HTML>
EOO;
		die();
}

$g = imagecreatetruecolor($width, $height);
$c0 = imagecolorresolve($g, 255, 255, 255);
$c1 = imagecolorresolve($g, 0, 0, 0);
imagefilledrectangle($g, 0, 0, $width, $height, $c0);

function	drawblade($g, $color, $a)
{
	global	$width, $height;
	
	$cx = $width / 2;
	$cy = $height / 2;
	$list = array(
		array(-20, -180), 
		array(20, -180), 
		array(20, 0), 
		array(-20, 0)
	);
	$points = array();
	$sin = sin($a * 3.14159 / 180);
	$cos = cos($a * 3.14159 / 180);
	foreach ($list as $p) {
		list($x, $y) = $p;
		$points[] = round($cx + $x * $cos - $y * $sin);
		$points[] = round($cy + $x * $sin + $y * $cos);
	}
	imagefilledpolygon($g, $points, count($points) / 2, $color);
}

$gb = imagecreatetruecolor($width, $height);
$cb0 = imagecolorresolve($gb, 255, 255, 255);
$cb1 = imagecolorresolve($gb, 0, 0, 0);
for ($pos=0; $pos<=$frame; $pos++) {
	imagefilledrectangle($gb, 0, 0, $width, $height, $cb0);
	
	$a = $pos * 10;
	drawblade($gb, $cb1, $a);
	drawblade($gb, $cb1, $a + 120);
	drawblade($gb, $cb1, $a + 240);
	
	$y = $pos * 5;
	imagecopy($g, $gb, 0, $y, 0, $y, $width, $height - $y);
	$y += 5;
	imageline($g, 0, $y, $width, $y, $c1);
}
imagedestroy($gb);

header("Content-Type: image/png");
imagepng($g);
imagedestroy($g);
?>

まず,さきほどのプロペラの画像の1コマ目を用意します。この画像は,縦横400ドットのビットマップです。同じ大きさのビットマップを用意して,1コマ目全体をそちらにコピーします。

続いて2コマ目です。2コマ目は上端の20ドットは1コマ目のものを残し,そこから下はプロペラ画像の2コマ目をコピーします。つまり,プロペラ画像の上端の20ドットはコピーせず,1コマ目のものを残します。

3コマ目は,上端の40ドットはそのままにして,そこから下にプロペラ画像の3コマ目をコピーします。

Webブラウザからアクセスした場合,後半のコマほど生成に時間がかかってしまいますが,とりあえず画像はできました。あとは全部のファイルを出力して,先に紹介したImageMagickなどで動画に変換すれば,解説動画として動画サイトなどにアップロードできるはずです。

rotate_3.phpの実行結果(ここではgifアニメにしてあります)

rotate3.phpの実行結果

今回は,あらかじめプログラムした動きを,動画に出力しました。実際には,マウス操作のような動きを使いたいこともあるでしょう。そこで次回は,JavaScriptを使い,ブラウザ側の動きを読みとってサーバ側で動画にする,というのをやってみようと思います。ご期待ください。

著者プロフィール

木元峰之(きもとみねゆき)

独立系ソフトハウスに8年間勤務,パッケージソフトの開発や記事執筆などを行う。現在はフリーのコンサルタント。SWESTなどのワークショップで分科会のコーディネータを務める。デジタル回路設計歴30年,プログラミング歴27年。

きもと特急電子設計
URL:http://business.pa-i.org/