2011年6月28日火曜日

HTML5 - Canvas マウスイベント時の座標取得について(座標は小数点以下があるらしい)

こんな感じでマウスクリック時の座標を検知する。

var mouseX;
var mouseY;

//イベントリスナーの登録
canvas.addEventListener("mousedown", mouseDownHandler, false);

function mouseDownHandler(e) {
 var rect = e.target.getBoundingClientRect();
 mouseX =  Math.floor(e.clientX - rect.left);
 mouseY =  Math.floor(e.clientY - rect.top);
}

2011年6月26日日曜日

HTML5 - Canvas アニメーション ゲーム(2)

ゲーム(1)の改良版。右左で移動できて、上でジャンプできます。敵の熊達をよけながら、GUNで敵を全部倒せばクリアです。GUNはAボタンで撃てます。Blog上ではうまく動かないので、リンクはります。動作確認はパソコンのChrome,Firefoxで確認済みです。

http://endo-yuta2.appspot.com/practice3

code

HTML5 Canvas - 上からボールを落として跳ね返る

上からボールを落として跳ね返る様。重力があり跳ね返り係数があるのだ。オランダの科学者が重力はないといっており、他の著名科学者、物理学者が一定の賛同をしているようだ。これが本当なら重力がある前提で全ての物理の教科書がつくられている現代において、コロンブス並みの大発見になるかもとのことだ。僕は今覚えたばかりの重力を前提に跳ね返らせているわけだが、それでも自然にみえるものだ。何が正しくて何が本質かなどということはわからないものじゃ。

2011年6月21日火曜日

HTML5 - Canvas 自然なジャンプをする四角形

地球には重力がありますので、飛んでもしまいには落ちます。飛ぶときは初速度がありますが、この速度は毎秒9.8m/s2重力によって減速します。当然落下中は毎秒9.8m/s2速度が増します。この9.8m/s2を重力加速度といいます。9.8m/s2というのは大体の数値で、場所や色々な条件によってこの速度は微妙に変わります。この自然界の掟をプログラムのジャンプに反映させると、いかにも自然なジャンプに見えるのであります。

2011年6月20日月曜日

HTML5 - Canvas アニメーション ゲーム(1)

若干ゲームっぽくなってきたHTML5のCanvasアニメーションです。プレイヤーは青いボールに顔が書いてあるやつで、彼はカーソルキーで動かせます。上を押すとジャンプします。しかしジャンプしだしたら天井にぶつかって帰ってくるまで止まりません。右左を押すと右左に移動します。ジャンプ中も移動できます。敵はくま達です。くま達にぶつかった時点でゲームオーバーです。得点などはございません。ゲームオーバーになったらリロードするまでもはや動きません。

2011年6月18日土曜日

HTML5 - Canvas アニメーション くま(2)

くまのアニメーション2。ランダムでキャラ選ぶ。ランダムで向きと速度決める。ブログのトップページだと表示されない。。。見るときは単一ページからお願いします。

HTML5 - Canvas アニメーション くま(1)

くまのアニメーション。端までいったら跳ね返る。なぜかブログのトップページだと、くまが消えない。。見るときは単一ページに飛んでください。

2011年6月13日月曜日

HTML5 - Canvas パックマンのモンスターを描くJavaScript関数(2)

x,y座標ともに指定できるモンスター関数です。

サンプル



HTML5 - Canvas パックマンのモンスターを描くJavaScript関数(1)

パックマンを描くスクリプトを調べてモンスター関数を作成します。

xだけをインプットして、yは勝ってに決まってしまういけていないモンスター関数です。

サンプル



モンスター関数(1)の使い方

monster(ctx,x,collor)

モンスター関数(1)

function monster(ctx,x,collor){
    ctx.fillStyle = collor;
    ctx.beginPath();
    ctx.moveTo(x,x+33);
    ctx.lineTo(x,x+19);
    ctx.bezierCurveTo(x,x+11,x+6,x+5,x+14,x+5);
    ctx.bezierCurveTo(x+22,x+5,x+28,x+11,x+28,x+19);
    ctx.lineTo(x+28,x+33);
    ctx.lineTo(x+23.333,x+28.333);
    ctx.lineTo(x+18.666,x+33);
    ctx.lineTo(x+14,x+28.333);
    ctx.lineTo(x+9.333,x+33);
    ctx.lineTo(x+4.666,x+28.333);
    ctx.lineTo(x,x+33);
    ctx.fill();
    ctx.fillStyle = "white";
    ctx.beginPath();
    ctx.moveTo(x+8,x+13);
    ctx.bezierCurveTo(x+5,x+13,x+4,x+16,x+4,x+18);
    ctx.bezierCurveTo(x+4,x+20,x+5,x+23,x+8,x+23);
    ctx.bezierCurveTo(x+11,x+23,x+12,x+20,x+12,x+18);
    ctx.bezierCurveTo(x+12,x+16,x+11,x+13,x+8,x+13);
    ctx.moveTo(x+20,x+13);
    ctx.bezierCurveTo(x+17,x+13,x+16,x+16,x+16,x+18);
    ctx.bezierCurveTo(x+16,x+20,x+17,x+23,x+20,x+23);
    ctx.bezierCurveTo(x+23,x+23,x+24,x+20,x+24,x+18);
    ctx.bezierCurveTo(x+24,x+16,x+23,x+13,x+20,x+13);
    ctx.fill();
    ctx.fillStyle = "black";
    ctx.beginPath();
    ctx.arc(x+18,x+19,2,0,Math.PI*2,true);
    ctx.fill();
    ctx.beginPath();
    ctx.arc(x+6,x+19,2,0,Math.PI*2,true);
    ctx.fill();
}

ちなみにgoogleのPac-Manです。

2011年6月12日日曜日

HTML5 - Canvasで色々な絵をかく(ハートマークからパックマンまで)

Canvasリファレンスや、MDC Docsというやつのチュートリアルを参考に色々な絵をCanvasを使って書いてみよう。下の絵は全部他のサイトからパクってきたものだよ。ちゃんとパクリ先は明示しておきますよ。パクってきたのは、上2つのサイトですよ。HTML5 Canvasを使えば、ハートマークもマンガの吹き出しも、パックマンまでJavascript1つで描けるのだ。これでJavaScriptのTimer使えば、JavaScriptだけでアニメーションがつくれるのだ。もうFlashなんて不要だ。しかし、Canvasにはアニメーション機能がないので、Timerを使いながらすべてを消して全てを一から描写するというプロセスをアニメーションのコマ数分続けなくてはいけない為、あまり膨大なアニメーションをつくるのはお勧めできないらしい。膨大ってどのくらいなのかは分かりませんが、ゲームを作ろうと思ってもちょっと難しいのではないでしょうか?といっても、こんなことや、こんなこともできるらしい!すごい。

線を描く



<canvas id="canvas2" width="50" height="50"></canvas>
<script type="text/javascript">
    var canvas = document.getElementById("canvas2");
    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(0, 40);
    ctx.lineTo(40, 40);
    ctx.lineTo(40, 0);
    ctx.closePath();
    ctx.stroke();
</script>

四角を描く



<canvas id="canvas3" width="50" height="50"></canvas>
<script type="text/javascript">
    var canvas = document.getElementById("canvas3");
    var ctx = canvas.getContext("2d");
    ctx.fillRect(0,0,40,40);
</script>

ハートマークを描く



<canvas id="canvas4" width="140" height="140"></canvas>
<script type="text/javascript">
    var canvas = document.getElementById("canvas4");
    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.moveTo(75,40);
    ctx.bezierCurveTo(75,37,70,25,50,25);
    ctx.bezierCurveTo(20,25,20,62.5,20,62.5);
    ctx.bezierCurveTo(20,80,40,102,75,120);
    ctx.bezierCurveTo(110,102,130,80,130,62.5);
    ctx.bezierCurveTo(130,62.5,130,25,100,25);
    ctx.bezierCurveTo(85,25,75,37,75,40);
    ctx.fill();
</script>

マンガの吹き出しを描く



<canvas id="canvas5" width="140" height="140"></canvas>
<script type="text/javascript">
    var canvas = document.getElementById("canvas5");
    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.moveTo(75,25);
    ctx.quadraticCurveTo(25,25,25,62.5);
    ctx.quadraticCurveTo(25,100,50,100);
    ctx.quadraticCurveTo(50,120,30,125);
    ctx.quadraticCurveTo(60,120,65,100);
    ctx.quadraticCurveTo(125,100,125,62.5);
    ctx.quadraticCurveTo(125,25,75,25);
    ctx.stroke();
</script>

パックマンを描く


<canvas id="canvas6" width="150" height="150"></canvas>
<script type="text/javascript">
    var canvas = document.getElementById("canvas6");
    var ctx = canvas.getContext("2d");
    roundedRect(ctx,12,12,150,150,15);
    roundedRect(ctx,19,19,150,150,9);
    roundedRect(ctx,53,53,49,33,10);
    roundedRect(ctx,53,119,49,16,6);
    roundedRect(ctx,135,53,49,33,10);
    roundedRect(ctx,135,119,25,49,10);

    // Character 1
    ctx.beginPath();
    ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false);
    ctx.lineTo(34,37);
    ctx.fill();

    // blocks
    for(i=0;i<8;i++){
      ctx.fillRect(51+i*16,35,4,4);
    }
    for(i=0;i<6;i++){
      ctx.fillRect(115,51+i*16,4,4);
    }
    for(i=0;i<8;i++){
      ctx.fillRect(51+i*16,99,4,4);
    }

    // character 2
    ctx.beginPath();
    ctx.moveTo(83,116);
    ctx.lineTo(83,102);
    ctx.bezierCurveTo(83,94,89,88,97,88);
    ctx.bezierCurveTo(105,88,111,94,111,102);
    ctx.lineTo(111,116);
    ctx.lineTo(106.333,111.333);
    ctx.lineTo(101.666,116);
    ctx.lineTo(97,111.333);
    ctx.lineTo(92.333,116);
    ctx.lineTo(87.666,111.333);
    ctx.lineTo(83,116);
    ctx.fill();
    ctx.fillStyle = "white";
    ctx.beginPath();
    ctx.moveTo(91,96);
    ctx.bezierCurveTo(88,96,87,99,87,101);
    ctx.bezierCurveTo(87,103,88,106,91,106);
    ctx.bezierCurveTo(94,106,95,103,95,101);
    ctx.bezierCurveTo(95,99,94,96,91,96);
    ctx.moveTo(103,96);
    ctx.bezierCurveTo(100,96,99,99,99,101);
    ctx.bezierCurveTo(99,103,100,106,103,106);
    ctx.bezierCurveTo(106,106,107,103,107,101);
    ctx.bezierCurveTo(107,99,106,96,103,96);
    ctx.fill();
    ctx.fillStyle = "black";
    ctx.beginPath();
    ctx.arc(101,102,2,0,Math.PI*2,true);
    ctx.fill();
    ctx.beginPath();
    ctx.arc(89,102,2,0,Math.PI*2,true);
    ctx.fill();

function roundedRect(ctx,x,y,width,height,radius){
  ctx.beginPath();
  ctx.moveTo(x,y+radius);
  ctx.lineTo(x,y+height-radius);
  ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
  ctx.lineTo(x+width-radius,y+height);
  ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
  ctx.lineTo(x+width,y+radius);
  ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
  ctx.lineTo(x+radius,y);
  ctx.quadraticCurveTo(x,y,x,y+radius);
  ctx.stroke();
}
</script>

BloggerでHTML5のCanvasのテスト

bloggerはHTML5使えるようなので、Google Chart Apiだけでなく、HTML5のCanvasで絵を書いていこうと思う。CanvasならJavaScriptのTimerを使えば簡単にアニメーションも作れるようだ。

とりあえずHTML5 Canvasのテスト




<canvas id="canvas1" width="50" height="50"></canvas>
<script type="text/javascript">
    var canvas = document.getElementById("canvas1");
    var context = canvas.getContext("2d");
    context.fillRect(0,0,40,40);
</script>

Canvasを勉強するためのサイト

2011年6月6日月曜日

google chart api Visualizationでフェルマー(2次関数の包絡線)

フェルマーでやりたかったのはこれだ。フェルマーは色々なことを発見したらしいが、これもフェルマーが発見したそうだ。下記グラフに描かれているのは、61本の直線ですが、全てy=x^2のグラフ上のある点の接線であります。結果的に、y=x^2のグラフが浮かび上がってくるのだ。こういうのを包絡線ともいうらしい。

y=x^2のグラフ上のある点を(a,a^2)とすると、その点の接線のy切片は、(0,-a^2)となるのだ。これはどの点をとってもそうなっているのだ!とフェルマーが発見したそうだ。すごいですね。この接線の傾きは、(a^2+a^2)/a = 2a^2/a = 2a ということで、2aになるのだ。
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
      google.load("visualization", "1", {packages:["corechart"]});
      google.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = new google.visualization.DataTable();
        
        var i ;
        var x;
        var y;
        var z = 0;
        var max = 61;
        var a;
        var c = 0;

        for(i=0; i<max;i++){
            data.addColumn('number', i);
        }

        data.addRows(max);
  
        for (a = -30; a < 31; a = a +1){
          for(x = -30; x < 31; x = x +1){
            y = 2*a*x-a*a;
            data.setValue(z, c, y);
            z = z+1;
          }
          z=0;
          c= c+1;
        }  
 
      new google.visualization.LineChart(document.getElementById('chart_div4')).
      draw(data, {width: 500, height: 400,vAxis: {maxValue: 10},legend:'none'});
}
</script>
<div id="chart_div4">
</div>

google chart api Visualizationの使い方

Visualizationを覚えよう。やはりjavascriptを使うようだが、若干複雑になっている。


上記は最初のサンプルになっている。普通のgoogle chart apiの最初のサンプルより、ちょっと奇麗で豪華になっている。ソースは下記だ。

<script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load("visualization", "1", {packages:["corechart"]});
      google.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Year');
        data.addColumn('number', 'Sales');
        data.addColumn('number', 'Expenses');
        data.addRows(4);
        data.setValue(0, 0, '2004');
        data.setValue(0, 1, 1000);
        data.setValue(0, 2, 400);
        data.setValue(1, 0, '2005');
        data.setValue(1, 1, 1170);
        data.setValue(1, 2, 460);
        data.setValue(2, 0, '2006');
        data.setValue(2, 1, 860);
        data.setValue(2, 2, 580);
        data.setValue(3, 0, '2007');
        data.setValue(3, 1, 1030);
        data.setValue(3, 2, 540);

        var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
        chart.draw(data, {width: 400, height: 240, title: 'Company Performance'});
      }
</script>
<div id="chart_div"></div>

シンプルにしてみよう。



二次関数のグラフを作ってみよう
できた!すばらしい。ソースはこれ。
<script type="text/javascript">
      google.load("visualization", "1", {packages:["corechart"]});
      google.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = new google.visualization.DataTable();
        data.addColumn('number', 'y');
        
        var x;
        var y;
        var z = 0;
        var max = 1001;

        data.addRows(max);
  
        for (x = -500; x < 501; x = x +1){
          y = x*x;
          data.setValue(z, 0, y);
          z = z+1;
        }  
 
      new google.visualization.LineChart(document.getElementById('chart_div3')).
      draw(data, {width: 500, height: 400,vAxis: {maxValue: 10}});
}
</script>
<div id="chart_div3">
</div>
これでフェルマーも作れるはずだ。

2011年6月5日日曜日

フェルマー

せっかくだからなんかグラフにしようと思う。フェルマーが発見したのは、y=xの2乗のグラフ上のある点(a,a2乗)の接線のy切片は、-a2乗になるということだ。これはどの点をとってもそうなるらしい。google chart apiの問題は数値を0〜100しか扱えないことだ。なんとマイナスが扱えないらしい。本当か。。。それじゃあそもそもフェルマーの確認ができないじゃないか。不便な世の中だ。

念のためgoogle chart apiを試してみよう。y=-3x+10という数式のグラフを作ってみよう。xは1〜10まで1ずつアップさせることにしよう。そうするとyは、7,4,1,-2,-5,......という風になる。xが4以降は残念な全部0という結果を想定している。



なんとマイナスの数値は表示されないのだ。残念だ。念のため、マイナスにならない1次関数グラフを作ってみよう。y=3x+10だ。



でも、y=-3x+10をx=10までグラフ化するだけなら、擬似的に見せることは可能だ。x=10なら、y=-20だから、y=-3x+30のグラフをプロットして、目盛をいじればいいのだ。



上記と同じように、全ての値に50を足して 、目盛で-50すりゃいいのだ。



・・・これじゃあx=7までしか表示できない。なんて使えないapiなんだ。。こうなったら、x=-3〜3までにしよう。そりゃそうだ。そうじゃないと放物線にならないし。



google chart apiはおらをばかにしているのか??あくまでy軸は内部的には0-100の範囲で表示するのか?人類が使用する数字は0-100でマイナスはないと思っているのか?それとも俺がその活用法をしらないだけなのか?あるいは、何か少しでもまともに使おうとすると、もう一ランク上のVisualizationを使う必要があるのか??

google chart apiは0-100ではなく、0-4095まで扱えるそうだ。しかしマイナスは扱えないし、4095を扱おうとすれば独自表記を覚えないといけないし、変換するプログラムを書かないといけない。これはもう速やかにVisualizationというのを覚えよう。

フェルマーは、Visualizationを覚えてからだな。

Google chart apiのURLを作るJavaScript

Google chart apiのURLを作るpythonスクリプトを今日中につくるぞ。やりたいのは、超低レベルなんだけど、本当に2次関数というのは放物線を描くのかを自分でデータをつくってグラフ化して試したいのだ。一次関数が一直線なのは当たり前に分かるからな。

Google chart apiはURLを決められたルールで生成し、それにアクセスすることでグラフのイメージデータが返ってくる仕組みだ。グラフの種類、色、目盛、数値などをルールに沿っていれていけばいい。getだとURLの長さが結構制限が強いみたいだけど、Postで呼び出せばその制限は緩和されるようだ。postでどうやって呼び出すのかは、今のところわかっていない。getでどの程度の数の数値データを扱えるのかも分からない。

y=2x+4というのは一次関数だべよ。これは単純だ。x=0のときy=4で後は正比例のまっすぐなグラフになるのは一目瞭然だ。y=2x2(二乗)+4というのは2次関数だべよ。これはx=0のときy=4だけど、その後の動きが分からないのだ。100〜1000個くらいのデータをぶち込んで滑らかな放物線を描いてみたい。

どうやらGoogle chat apiには、数値データを一個一個ぶち込む方法と、数式をぶち込む方法の2種類あるように思える。

https://chart.googleapis.com/chart?cht=lc&chd=t:-1&chs=250x150&chco=FF0000&chfd=0,x,0,11,0.1,sin(x)*50%2b50&chxt=x,y

これは非常に短いURLだが、sin(x)*・・・・という数式めいたものが入っており、イメージ出力するとこうなる。



なんて便利なツールなんだ。そして奇麗な曲線が一瞬で描かれるのだ。すばらしい。
数式でグラフを作れるのは便利だけど、俺はその数式からくるグラフが本当なのかを実感したいので、数式をインプットするのは今の俺にとっては無意味だ。だから、数式のxをずらしながら、100ないし1000のyを出して、インプットしたxとアウトプットしたyの組み合わせを100ないし、1000作るのだ。その組み合わせを元にURLを自動生成するプログラムをpythonで作るのだ。

Google Chart APIのURLの仕組み

仕組みを試しながらマスターしよう。https://chart.googleapis.com/chart?が基本URLのようだ。cht=lcはチャートの種類を指定しているようだ。2次関数にせよグラフはラインチャートでOKなんで、cht=lcでOKだ。円グラフや地図の国別の色の濃さで国別シェアなんかも可視化できるようだ。今度試そう。

http://code.google.com/intl/ja/apis/chart/image/docs/gallery/line_charts.html

このページにいろいろと詳しい説明がのっているようだ。

https://chart.googleapis.com/chart?cht=lc&chs=200x125&chd=t:40,60,60,45,47,75,70,72

これは恐らく最もシンプルなchartApiの使いかただろう。chs=200x125というのは、画像の大きさのようだ。イメージ出力するとこうなる。



ためしに、chs=500x250にするとこうなる。



chd=t:40,60,60,45,47,75,70,72というのは、数値データそのものだ。8個あるとおり、グラフの点も8個あるのだ。t:というのはよくわからないので後で調べよう。これはすなわちy軸の数値データであり、x軸の数値データは記載がない。xは一定間隔という前提で、yの値のみインプットしているのだ。二次関数のグラフの形を確認するにあたっては、xの値を明示する必要がないから、はっきりいって、このシンプルな形態にそって、データを1000個いれさえすれば終わりだ。なんて簡単なんだ。xが-500〜500まで(1刻み)のyをプロットすればいいのだ。こういうのをきっとプロットというのだろう。

まあpythonで作るのは結構なことだけど、javascriptでつくっちゃえば、このBlog上で全てを完結できるので、せっかくだから、javascriptでやるか。まずはy=x2乗を出すぞ。

<script type="text/javascript">
<!--
var x;
var y;
var txt = '';

for (x = -500; x < 501; x = x +1){
    y = x*x;
    if(txt == ''){txt = y;}
    else{txt = txt+','+y;}
}
document.write('<img src="https://chart.googleapis.com/chart?cht=lc&chs=500x250&chd=t:',txt,' "/>');
// -->
</script>

これで1000個のデータをプロットしてみたけど、エラーになった。
too largeだそうだ。ということは数を減らしてみよう。そして、postでアクセスする方法も調べよう。



300個のデータならいけるらしい。上記はxが-150〜150までの、y=x2乗のグラフだ。しかし、何か天井にひっかかっているようだ。嘘のグラフを表示するとは何事。。恐らく、目盛を明示しないとこういったバグが生じるんだろう。最大数値を150*150=22500を与えれば天井のつっかかりはなくなるはずだ。



なくならない。理由が分かった。google chart apiは数字は0-100までしか扱えないらしい。100以上は100として扱うらしい。よって、天井ができるのだ。。。めんどうだ。扱う数値は、係数100/22500をかけることにしよう。

100/22500の係数をかけると、数字1つ1つの文字列数が多くなるので、エラーになる。数字の数で制限してるわけではなく、URLの長さで制限しているからだ。POSTでどの程度緩和されるのか分からないけど、結構めんどうな仕組みだ。よって、-50〜50のxを元に、グラフを作った。yは、0.04 の係数をかけて出している。よって、x=50のときのy2500が100になるのだ。

<script type="text/javascript">
<!--
var x;
var y;
var z = 0.04;
var txt = '';

for (x = -50; x < 51; x = x +1){
    y = x*x*z;
    if(txt == ''){txt = y;}
    else{txt = txt+','+y;}
}
document.write('<img src="https://chart.googleapis.com/chart?chxt=x,y&chxr=0,-50,50|1,0,100&cht=lc&chs=500x250&chd=t:',txt,' "/>');
// -->
</script>




Google Chart ApiをPOSTで使う

POSTで使う方法はここに詳細が載っている。

GETで使う場合は超お手軽だが、2kしか許されない。POSTは若干めんどくさいが、16Kまで許されるのだ。URLの長さが8倍までいいってことだろう。また数字を短縮する独自の表記法もあるようで、それを使えばもっとたくさんのデータを扱ってグラフを作ることができるだろう。ただ独自の表記を覚えるのがめんどくさそうだし、小数点以下にも対応していなそうだ。(多分)

pythonでPNGを吐き出すchart.pyをつくって、htmlから<img src="chart.py" />というように使うのだ。
これなら入力値に応じたグラフをリアルタイムに表示することも可能だ。データも8倍使えるしな。でもいずれにせよ制限があるから、使い方によっては、matplotlibのがやっぱりいいのかもしれない。ただ、GAEでmatplotlibが使えるのかは不明だ。