Yearly Archives: 2009

2009-04-24

Visual Studio 2008でファイルを閉じるのが遅い

とある大きめのプロジェクトで、開いているドキュメントを閉じるのが大変遅くて困っている。プロジェクト内のソースコードでも、新規で作成したテキストファイルでも、Ctrl+F4や×ボタンを押してから消えるまでに7秒くらいかかる。沢山ファイルを開いた状態で「すべてのドキュメントを閉じる」や「終了」を選んだときなどは、もう我慢できないくらい待たされる。仕方ないので終了するときはすべて保存してからプロセスを強制終了させることにした。

ソリューションエクスプローラ内のプロジェクトを一つ一つアンロード状態にしていくと、徐々に閉じる時間が短くなる。でもアンロードしたままだとビルドも出来ないじゃん。

もしやと思いノートンのAuto-Protectを無効にしてみる。すると先ほどまでの遅さがウソのように軽くなった。有効にしたときだけ遅くなるので、原因はこれのようだ。しかし無効にしているとセキュリティーリスクありの赤マークが目立つので鬱陶しい。Auto-Protectは有効にして、「スキャンの除外」設定にプロジェクトのディレクトリを指定した結果、無効にしたのと同じ結果が得られた。

今後、アンチウィルスソフトと開発環境の相性はちゃんと確認すべきかもしれない。例えば、アンチウィルスソフトの有無でコンパイルにかかる時間が変わるかどうかとかも調べてみたい。

2009-04-16

excanvas.jsのtransform

IEでcanvas要素を使えるようにするexcanvas.js。r3以降、transformメソッドが実装されているようなので最新のをtrunkから取ってきて試してみた。おお、ちゃんと倉庫番が表示された。……でもむちゃくちゃ重いよ。一マス動くのに何秒かかっているのか計りたくもない。あまりの重さにタスクマネージャを開いてみたら、仮想メモリサイズ欄が800MB!! これはダメだ……。

クロスブラウザでこういうことをやるんだったらFlash(Flex SDK)でやるべきだよなぁ。手軽さは減るけど。

2009-04-15

JavaScriptでcanvas要素内にマウスでお絵かき

マウスの要素内座標が取れるようになったので、簡単な例を一つ。

function getElementAbsPos(elem)
{
  var x = 0;
  var y = 0;
  while(elem){
    x += elem.offsetLeft;
    y += elem.offsetTop;
    elem = elem.offsetParent;
  }
  return {x:x, y:y};
}

function getMousePosOnElement(elem, ev)
{
  if(!ev){ ev = event;}//for IE
  if(elem.getBoundingClientRect){
    var bcr = elem.getBoundingClientRect();
    var x = ev.clientX - bcr.left;
    var y = ev.clientY - bcr.top;
    return {x:x, y:y};
  }
  else if(typeof(ev.pageX) == "number" && typeof(ev.pageY) == "number"){
    var pos = getElementAbsPos(elem);
    return {x:ev.pageX-pos.x, y:ev.pageY-pos.y};
  }
  else{
    return {x:0, y:0};
  }
}


var BORDER_WIDTH = 10;
var cv = document.createElement("canvas");
cv.setAttribute("width", "320");
cv.setAttribute("height", "240");
cv.style.cssText = "border: "+BORDER_WIDTH+"px solid;";
document.body.appendChild(cv);
var lastPoint = null;

cv.onmousedown = function(ev) {
  lastPoint = getMousePosOnElement(cv, ev);
  lastPoint.x -= BORDER_WIDTH;
  lastPoint.y -= BORDER_WIDTH;
}
cv.onmousemove = function(ev) {
  if(lastPoint){
    var currPoint = getMousePosOnElement(cv, ev);
    currPoint.x -= BORDER_WIDTH;
    currPoint.y -= BORDER_WIDTH;
    var ctx = cv.getContext("2d");
    ctx.beginPath();
    ctx.moveTo(lastPoint.x, lastPoint.y);
    ctx.lineTo(currPoint.x, currPoint.y);
    ctx.stroke();
    lastPoint = currPoint;
  }
}
cv.onmouseup = function(ev) {
  lastPoint = null;
}
cv.onmouseout = function(ev) {
  lastPoint = null;
}

例によってインタラクティブコンソールへ貼り付けて実行可能。

getMousePosOnElementより上は昨日書いたとおり。

borderを太くするとその分座標がずれてしまうので、そのあたりは適切に補正してやる必要がありました。

2009-04-14

JavaScriptで要素上のマウスカーソル座標を求める

マウスイベントオブジェクトから得られる座標をある要素上の座標系へ変換したいのだが、これがなかなか簡単にはいかない。

色々調べてみるとgetBoundingClientRectというものがIEやFirefox、Operaでは使えるようなので、それを使うことにした。WebKitはつい最近実装したばかりのようだ。なので、getBoundingClientRectが使えればそれとclientX,clientYとの差分で求める。使えなければ、要素の絶対座標を適当に推測して、pageX,pageYとの差分で求める(IEはpageX,pageYをサポートしていないがgetBoundingClientRectの方を使うので問題ない)。

function getElementAbsPos(elem)
{
  var x = 0;
  var y = 0;
  while(elem){
    x += elem.offsetLeft;
    y += elem.offsetTop;
    elem = elem.offsetParent;
  }
  return {x:x, y:y};
}

function getMousePosOnElement(elem, ev)
{
  if(!ev){ ev = event;}
  if(elem.getBoundingClientRect){
    var cr = elem.getBoundingClientRect();
    var x = ev.clientX - cr.left;
    var y = ev.clientY - cr.top;
    return {x:x, y:y};
  }
  else if(typeof(ev.pageX) == "number" && typeof(ev.pageY) == "number"){
    var pos = getElementAbsPos(elem);
    return {x:ev.pageX-pos.x, y:ev.pageY-pos.y};
  }
  else{
    return {x:0, y:0};
  }
}

function onClick(elem, ev)
{
  var pos = getMousePosOnElement(elem, ev);
  alert(pos.x + "," + pos.y);
}

var elem = document.getElementById( ???? );
elem.onclick = function(ev) { onClick(elem, ev);}

とりあえず簡単なスクロール込みのhtmlでテストした感じでは大丈夫っぽい。CSSの指定によってはgetElementAbsPosあたりが怪しいけど。

マウスの要素内座標が簡単に求められないなんて、本当にどうかしていると思う。

2009-04-14 ,

JavaScript倉庫番の問題を作る

今日もテキトーに問題を一つ作りました。

#######...
#OO   #...
#OO   #...
#     #...
#  @  ####
#        #
####  B  #
...#  BB #
...#  B  #
...#     #
...#######

ひょうたん型の地形が作りたかっただけです。こういう簡単なの、でも順序に少しだけ制約があって、あとは誤操作は気をつけなければならない程度の問題も良いですね。

ところで倉庫番って商標みたいなんですけど、言い換えってないんですかね。オセロに対するリバーシみたいな。

2009-04-13 ,

JavaScript倉庫番の問題を作る

というわけで、一応動くようになったわけですが、別に倉庫番がやりたかったわけではなくて、倉庫番の問題を作りたかったんですね。倉庫番の問題というのはどうやって作るのか。どんな問題が良くて、どんな問題が良くないのか。

とりあえず一番単純なの。プレイは枠内をクリック。

########
#O B @ #
########

単純すぎ。

適当に五つほど箱を置いてみた。

##############
#OO   #   OOO#
####  B  #   #
#  #  ###  B##
# B#   #     #
#    @ #  #  #
#  ### #B #B #
#         #  #
##############

うーん、クリア不可能だ(と思う)。あと、やはり単純というか、すぐに結果が見えてしまうところも気になる。

ここで、最初から作り直すか、それとも、修正してみるか。

##############
#OO   #   OOO#
# ##  B  #   #
#  #  ###  B##
# B#   #     #
#    @    #  #
#  ### #B #B #
#         #  #
##############

クリアできるように修正してみた。壁に一つ穴を開けてはプレイしてクリアできるかどうか考えた。二つ開けて箱を動かしながら少し考えた時点でクリアできることに気がついた。気がつくとちょっと嬉しい。意外と難しくね?

というわけで、今日発見した制作メソッド。

  1. 適当に配置してクリアできない状況を作る。
  2. 任意の考慮時間N[秒]を決める。
  3. 壁に穴を一つ開ける。
  4. クリアできるかどうか、N秒間考える。
  5. N秒経ってもクリアできなければ3へ。
  6. クリアできたら難易度N[秒]の問題(俺基準)が完成。
2009-04-10 ,

JavaScript倉庫番

もはやIEのことは全く考えておりません。

上のテキスト領域はキーフォーカス固定用。他に良い方法が分からなかったので仕方なく。