画面をコッテリ塗りつぶせの巻
語呂がいいので「コッテリ」という言葉を追加してみましたが、つまりBASICのPAINT命令に相当することをHSPでやってしまおうということです。
●え? 迷路??
いきなりですが、「迷路を勝手に作って勝手に解く」スクリプトを作ってみました。こちらです。えーと、迷路作成のアルゴリズムとかはどうでもよくって、注目してほしいのは「サーチ」と言うコメント行より後の、迷路を勝手に解く部分です。このアルゴリズムの解析をしましょう。簡単に言うと、「1歩ごとに移動できる方向をしらみ潰しに調べていく」方式です。
まず、現在地の上下左右について、移動できる方向を検索します。 | |
こうして移動可能な方向へ検索ロボット(緑)を発生させます。 | |
発生したロボットそれぞれについて上下左右を調べ、移動できる場合は元の道を戻らないように足跡(暗い青)を残しながら移動します。このとき2方向以上移動できる場合、優先順位の高い方向(ここでは右)へ移動し、残りの方向(下)へは新規にロボットを発生させます。 | |
袋小路にはまって移動不能になったロボット(中央下)は自動的に消滅します。このように増殖と消滅を繰り返しながら迷路を動き続け、ロボットが1匹になった時点で現在地を残ったロボットの位置へ移動させ、さらに検索を始めます。 |
例によって何のことかよくわからない人は、スクリプトを実行してチマチマとした迷路の中を「燃えるスチールウールの火」のごとく動き回る様をみて理解していただければよいかと思います。
●こうやって塗りつぶすのだ
ここで「これが塗りつぶしと何の関係があるんだ」とツッコミたくなるかもしれませんが、ワラワラと動き回りながら青い足跡を残していく様子をみれば勘のいい人はわかるんじゃないかと思います。そう、これを改造すれば塗りつぶしになるんです。
ランダムな線を引かれた画面を左クリックでランダムな色でコッテリと塗りつぶすプログラムを作りました。こちらです。
ではスクリプトの説明をしましょう。塗りつぶしルーチンのみを下の表に抜粋しました。なお、コメント中の番号は説明の番号に対応しています(アップロードされているスクリプトには入っていません)。
repeat redraw 2 ;----------2---------- repeat maxmem i=cnt if pa.i=0 : break if pa.i=3 : continue if pa.i=1 : pa.i=2:continue mov=0 xx=px.i yy=py.i die=0 ;----------3---------- repeat 4 j=cnt if j=pb.i : die++:continue ;----------4---------- v=xx+dix.j w=yy+diy.j pget v,w gc=(rval*65536)+(gval*256)+bval if (gc=bord)|(gc=col)|(v<0)|(v>639)|(w<0)|(w>479) : die++:continue ;----------5---------- mov++ if mov=1 : pb.i=j:px.i=v:py.i=w:pset v,w:continue if newrb=maxmem : dialog "メモリが足りません",1,"Paint Sample":end robos++ finsw=1 px.newrb=v py.newrb=w pa.newrb=1 pb.newrb=4-j pset v,w newrb++ loop ;----------6---------- if die=4 : pa.i=3:robos-- loop redraw 1 await 1 ;----------7---------- if robos<1 : break loop |
●補足・フォロー・いいわけ(笑)
ここに載せていない部分の補足になりますが、パレットモードではcolor命令はパレットの中の一番近い色で描画される仕様なので、もしも描画に使おうとしている色と実際にかかれたドットの色が違っていると一度描いた部分を再度塗りつぶそうとしてメモリを無駄に食いつぶしてしまいます。それを防ぐためにここでは一度ドットを打った後に色を取得し、描画色を再設定しています。
あまり広い面積で、かつ複雑な形をしたグラフィックを塗りつぶそうとするとメモリ不足でエラーが出るかもしれません。そのときはスクリプトのはじめの方にあるmaxmemを増やしてください。HSPは配列変数を無制限に確保できるので、大量に確保しても簡単には誤動作を起こすことはないはずです。
このスクリプトは作りが甘いので、三角形のように徐々に細くなっていくような箇所や斜線部を塗りつぶしきることができません。ただしこれを「味」と割り切ってしまえばどうってことないですが(^^;。
塗りつぶす際にメモリ制限があるのは、検索能力を失ったドットに「使用不可」のフラグを立ててそのままにしてあるからです。使用不可になったドットが使ったメモリを再利用すれば制限はほぼなくなりますが、新しいドットを発生させるたびに空いている変数を検索させるだけでもバカにならないので処理速度を優先してこのような形を取っています。もしもメモリ制限があるのがいやだという人は処理5のメモリチェックの後あたりに空いているメモリをチェックする処理をつけてみてください。しかし、描画面積が小さければその処理をつけることで確保するメモリを減らすことができ、(検索するメモリ数が減るので)処理速度が軽くなる可能性は十分にあります。
●最後に
Pentium 133MHzだとキツすぎますが、「昔のパソコンはもっとも〜っと遅かったんだよ」って自分に言い聞かせればかなりの速度に・・・感じるかボケェッ(爆)!!
●さて(2000/12/02追加)
ここに載せている塗りつぶしルーチンがあまりにも粗末なものだったので、vramへの直アクセスとルーチンの改良を施したものを用意しました。こちらです。ついでに処理速度の速さを実感してもらうために画面の解像度を半分にしています。で、肝心の速度は・・・きれいに塗りつぶすようにはなったんですが、相変わらず遅いです(涙)。あんまり変わってないですね。別に塗りつぶしがきれいになったかわりに遅くなったって事はないんですけど。てゆーかよそのサイト言ったらもっと速いルーチン組んであるとこいっぱいあるし・・・寝よう。