HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2006
0805
うおラインオブサイトについて教えてください8解決


うお

リンク

2006/8/5(Sat) 12:39:13|NO.1799

ローグ系のRPGみたいに、自分を中心に視野の範囲だけ
マップのタイルを表示するスクリプトを書きたいんですが、上手くいきません。

長いプログラムで恐縮です。
下のように、視野が広がっていく軌跡をlosX,losYで予め指定しています。
このlosX,losYは90度分なので、vectorでx方向とy方向を変え、
4回(360度分)実行しています。

しかし、この方法だと視野の範囲が大きくなると対応できず
またプログラムとしてもなんだか無様です。
よろしくお願いします。


dim losX,10,10 dim losY,10,10 losY(0,0)=-1,-1,-1,-1,-1,-1 losX(0,0)= 0 ,1 ,0 ,0 ,0 ,0 losY(0,1)=-1,-1,-1,-1,-1, 1 losX(0,1)= 1 ,1 ,0 ,0 ,0 ,1 losY(0,2)=-1,-1,-1,-1 ,1 ,0 losX(0,2)= 0 ,1 ,1 ,1 ,0 ,0 losY(0,3)= 0,-1,-1,-1 ,0 ,0 losX(0,3)= 1 ,1 ,1 ,1 ,-1 ,0 losY(0,4)=-1,-1 ,0 ,0 ,0 ,1 losX(0,4)= 1 ,1 ,1 ,1 ,1 ,-1 losY(0,5)= 0,-1 ,0 ,0 ,0 ,0 losX(0,5)= 1 ,1 ,1 ,1 ,1 ,1 repeat 4 if cnt=0:vector=1,1 if cnt=1:vector=1,-1 if cnt=2:vector=-1,1 if cnt=3:vector=-1,-1 repeat 6 x=10:y=10 cnt2=cnt repeat 6 x+=losX(cnt,cnt2)*vector(0) y+=losY(cnt,cnt2)*vector(1) pos x*16,y*16:mes"○" loop loop loop



この記事に返信する


GENKI

リンク

2006/8/5(Sat) 18:33:33|NO.1805

 マップを全部描画しておいて、あとから不要な部分を黒で塗りつぶすというのもありかと思います。
このほうが綺麗に仕上がると思います。

でもとりあえずちょっと作ってみました。こんな感じですか?

dim map,10,10 dim chrxy,2 map(0,0) = 0,0,0,1,0,0,0,0,0,0 ;マップデータ map(0,1) = 0,0,0,0,1,0,0,0,0,0 map(0,2) = 0,0,0,0,0,1,0,0,0,0 map(0,3) = 0,0,0,0,0,0,1,0,0,0 map(0,4) = 0,0,0,0,0,1,0,0,0,1 map(0,5) = 0,0,0,0,1,0,0,0,1,0 map(0,6) = 0,0,0,1,0,0,0,1,0,0 map(0,7) = 0,0,1,0,0,0,1,0,0,0 map(0,8) = 0,0,0,1,0,1,0,0,0,0 map(0,9) = 0,0,0,0,1,0,0,0,0,0 chrxy(0) = 5,5 ;キャラクタ座標 r = 5 ;視界半径 muki = 1 ;向き *main redraw 1 : await 16 : redraw 0 : color 255,255,255 : boxf : color 0,0,0 stick key if key&1 : chrxy(0)-- : chrxy(1)++ : muki = 3 ;↓向きのイメージ if key&2 : chrxy(1)-- : chrxy(0)-- : muki = 2 ; 2│1 if key&4 : chrxy(0)++ : chrxy(1)-- : muki = 1 ;─┼─ if key&8 : chrxy(1)++ : chrxy(0)++ : muki = 4 ; 3│4 if key&128 : end title ""+muki repeat 10 xx = cnt - chrxy(0) ;PCからのマップの相対座標 x = cnt repeat 10 yy = cnt - chrxy(1) ;PCからのマップの相対座標 y = cnt if (x>=0)&(y>=0){ if map(x,y)=1 { ;ここの行をコメントアウトした方が描画範囲は確認しやすい ;マップ描画(描画範囲は扇状) if (xx*xx+yy*yy) <= r*r { ;描画範囲を円形に絞込み ;さらに描画範囲を絞り込んで扇状にする。 f = 0 if muki = 1 : if (chrxy(0)<=x)&(chrxy(1)>=y) : f = 1 if muki = 2 : if (chrxy(0)>=x)&(chrxy(1)>=y) : f = 1 if muki = 3 : if (chrxy(0)>=x)&(chrxy(1)<=y) : f = 1 if muki = 4 : if (chrxy(0)<=x)&(chrxy(1)<=y) : f = 1 if f = 1 : pos x*16,y*16 : mes "○" } } } loop loop pos chrxy(0)*16,chrxy(1)*16 : mes "●" ;PCの描画 goto *main



うお

リンク

2006/8/5(Sat) 18:59:11|NO.1807

すいません。言葉足らずでした。
自分を中心に外に向かってマップの表示をしているのは、
途中に壁や人などの障害があった時に、それ以降のマップを表示させないためです。
基本的には全方位見えていて、障害物があった時は、その先は見えないような感じです。

スクリーンショットでわかるかわかりませんが、
http://ivan.sourceforge.net/screenshots.html
このゲームみたいな感じです。

円形に絞り込むところのスクリプトは参考になりました。
ありがとうございます。



GENKI

リンク

2006/8/5(Sat) 21:45:21|NO.1808

> 下のように、視野が広がっていく軌跡をlosX,losYで予め指定しています。

 これの意味がなんとなくわかったような気がします。
losX,losYに書いた順番で調べていって途中に壁があったら以降を描画しないという感じでしょうか。


> しかし、この方法だと視野の範囲が大きくなると対応できず

 なるほどマップを大きくすると対応が面倒ですね。
手作業なので「途中」の判定基準もあいまいになりそう。



 参考になるかどうか分かりませんが、線分と矩形の衝突判定のサンプルをどうぞ。
http://hspwiki.nm.land.to/?%BE%D7%C6%CD%C8%BD%C4%EA
例えば壁とPCの間に線分を引いてその間に壁があったら、線分の一端側の壁は描画しない…とか。



うお

リンク

2006/8/7(Mon) 11:46:12|NO.1839

ネットを探していて、スパイラルパスという方法を見つけました。
http://www.roguelikedevelopment.org/php/article/showArticle.php?path=development/LOS/articles/&article=Spiral%20Path%20FOV%20-%20Ray%20Dillinger.txt

やり方はわかるのですが、スクリプトになおすための規則性みたい
なのが頭が固くてわからないので、
もしわかる方がいましたら教えてください。

I J8H K927G LA3@16F MB45E NCD 0

上の図で@がプレイヤーです。
1から0(0ではなくアルファベットのo)までが、
表示されるマップタイルの順番です。

まずプレイヤーの上下左右の1,2,3,4をチェックします。
1の場所に障害物がなければ、5,6,7を表示します。
2の場所に障害物がなければ、7,8,9を表示します。
3の場所に障害物がなければ、9,A,Bを表示します。
4の場所に障害物がなければ、B,C,5を表示します。

そして、表示されたタイルを元に、視界の広さ分だけ、
以下の作業をリピートします。*はチェックするタイルです。

表示されたタイルが右方向なら:
3
@1
2
の順番に新しいタイルをチェックする。
例えば最初の図でいうと、6が表示さえたらF,E,Gをチェックします。
表示されたタイルが右上なら
2
*1
をチェックします。左下なら
*1
2
とチェックします。

このような作業の繰り返しです。
長くなってすいません。



かきしす

リンク

2006/8/8(Tue) 13:57:20|NO.1865

面白そうなのでチャレンジしてみました。
『スパイラルパス』とは異なるので、うおさんの希望に副えるものかどうかは微妙ですが・・・

マウスの左クリックで壁を描き、右クリックで壁を消せます。

中心から最外周ブロックに向けて、壁に当たるまで 光を描いて行く方式です。
速度は まずまずなんじゃないかと思いますが、どうでしょう?


dim map,43,43; 障害物記録用バッファ ; バッファは都合により正方形が効率がよい。 ; そのため、画面上下に使用しない領域も含めて確保する。 screen 0,640,480 ;################################################################### *メイン stick key,256+512 if (key & 256):tmpx=mousex/16+1: tmpy=mousey/16+6: map(tmpx,tmpy)=1 if (key & 512):tmpx=mousex/16+1: tmpy=mousey/16+6: map(tmpx,tmpy)=0 ;       ↑マウスの左クリックで障害物を置き、右クリックで消す。 gosub *視界チェック redraw 0 color 0,0,50:boxf 0,0,640,480 repeat 30:cnty=cnt repeat 40:cntx=cnt tmpx1=cntx*16:tmpx2=tmpx1+16:tmpy1=cnty*16:tmpy2=tmpy1+16 if buf(cntx+1,cnty+6)=0{;  『可視』の時のみ・・・ color 255,255,100:boxf tmpx1,tmpy1,tmpx2,tmpy2 ;  ↑地面を明るく描く。 if map(cntx+1,cnty+6)=1{; 壁の表示 color 128,128,128:boxf tmpx1,tmpy1,tmpx2,tmpy2 } } loop loop redraw 1:await 30 goto *メイン ;################################################################## *視界チェック dim buf,43,43; 視界バッファを『不可視』で初期化 buf(21,21)=0 repeat 43:dxy=1.0*(cnt-21)*16/21 ; ↑最外周ブロック(一辺分)についてのループ flg1=0: flg2=0: flg3=0: flg4=0 repeat 21:tmp2=cnt ; ↑中心から最外周に向かってのループ dxy2=dxy*tmp2: tmp3=21+int(dxy2/16) buf(tmp3,21-tmp2)=flg1 if map(tmp3,21-tmp2)=1:flg1=1 buf(tmp3,21+tmp2)=flg2 if map(tmp3,21+tmp2)=1:flg2=1 buf(21-tmp2,tmp3)=flg3 if map(21-tmp2,tmp3)=1:flg3=1 buf(21+tmp2,tmp3)=flg4 if map(21+tmp2,tmp3)=1:flg4=1 loop loop return



かきしす

リンク

2006/8/8(Tue) 15:18:15|NO.1868

すみません。ちょっと修正します。

壁の向こうの『壁無し』が存在して初めて影になるようにしました。
これにより、壁が必要以上に不可視になるのを防いでいます。
その分ちょっと処理が重くなりました。


dim map,43,43; 障害物記録用バッファ ; バッファは都合により正方形が効率がよい。 ; そのため、画面上下に使用しない領域も含めて確保する。 screen 0,640,480 ddim dxy,43 repeat 43 dxy(cnt)=(1.0*(cnt-21)*16)/21 loop; チェック用変数。あらかじめ計算しておく。 ;################################################################### *メイン stick key,256+512 if (key & 256):tmpx=mousex/16+1: tmpy=mousey/16+6: map(tmpx,tmpy)=1 if (key & 512):tmpx=mousex/16+1: tmpy=mousey/16+6: map(tmpx,tmpy)=0 ;       ↑マウスの左クリックで障害物を置き、右クリックで消す。 gosub *視界チェック redraw 0 color 0,0,50:boxf 0,0,640,480 repeat 30:cnty=cnt repeat 40:cntx=cnt tmpx1=cntx*16:tmpx2=tmpx1+16:tmpy1=cnty*16:tmpy2=tmpy1+16 if buf(cntx+1,cnty+6)<2{;  『可視』の時のみ・・・ color 255,255,100:boxf tmpx1,tmpy1,tmpx2,tmpy2 ;  ↑地面を明るく描く。 if map(cntx+1,cnty+6)=1{; 壁の表示 color 128,128,128:boxf tmpx1,tmpy1,tmpx2,tmpy2 } } loop loop redraw 1:await 30 goto *メイン ;################################################################## *視界チェック dim buf,43,43; 視界バッファを『不可視』で初期化 buf(21,21)=0 repeat 43:tmp1=cnt ; ↑最外周ブロック(一辺分)についてのループ flg1=0: flg2=0: flg3=0: flg4=0 repeat 21:tmp2=cnt ; ↑中心から最外周に向かってのループ dxy2=dxy(tmp1)*tmp2: tmp3=21+int(dxy2/16) if (flg1=1)and(map(tmp3,21-tmp2)=0):flg1=2 buf(tmp3,21-tmp2)=flg1 if map(tmp3,21-tmp2)=1:flg1=1 if (flg2=1)and(map(tmp3,21+tmp2)=0):flg2=2 buf(tmp3,21+tmp2)=flg2 if map(tmp3,21+tmp2)=1:flg2=1 if (flg3=1)and(map(21-tmp2,tmp3)=0):flg3=2 buf(21-tmp2,tmp3)=flg3 if map(21-tmp2,tmp3)=1:flg3=1 if (flg4=1)and(map(21+tmp2,tmp3)=0):flg4=2 buf(21+tmp2,tmp3)=flg4 if map(21+tmp2,tmp3)=1:flg4=1 loop loop return



かきしす

リンク

2006/8/8(Tue) 16:10:23|NO.1872

たびたびすみません。
視界チェックのところの

視界バッファを『不可視』で初期化 は、『可視』で初期化の誤りです。
最初、『不可視のときは0』で作っていて、途中で変更したのを忘れてました。



うお

リンク

2006/8/9(Wed) 14:48:08|NO.1902

投稿ありがとうございます。
かきしすさんのスクリプトを早速いじってみました。
シンプルなのに、視界の処理が感じがいいですね。

そのままゲームに組み込めそうになかったので
Cで書かれたLOSのソースを幾つかHSPになおして、
やっと動作するようになりました。

本命は再帰シャドウキャスティングという処理だったんですが、
苦労して打ち込んだのに動きませんでした。



ONION software Copyright 1997-2023(c) All rights reserved.