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


HSPTV!掲示板


未解決 解決 停止 削除要請

2006
0809
うお(!長文!)Cからの移植スクリプトがうまく動かず5解決


うお

リンク

2006/8/9(Wed) 15:13:35|NO.1903

RPGのマップの処理で、以下のフリーのC言語のソース(デモ尽き)を
HSPに移植したかったんですが、なんとか動作はするものの
視界の表示がおかしいです。

http://www.roguelikedevelopment.org/development/LOS/files/rscfovdemo.zip

原因はおそらく再帰の時のローカル変数にあると思います。
ローカル変数を付け加えたり、色々といじって見ましたが、どうにも解決しません。
掲載したスクリプトは、いじる前の、Cのソースとほぼ同じ状態のものです。
'startSlope='の部分だけ'startSlopeCopy'に変えています。
関数のパラメータであるstartSlopeに代入していてエラーになるからです。
注釈は上記の元のソースに大量に書かれているので省いています。

ソースのほとんどは、同じ処理を東西南北に変数を変えて繰り返されたものです。
なので、一つの方向さえ上手くできれば、残りの方向も同じように
書き換えるだけで動くはずです。

英語の説明を読まないとたぶん処理の意味がわからないし、
ソースを理解するだでも大変だと思います。
駄目もとで、もしおかしい部分がわかる方がいましたら、
指摘してもらえると助かります。






#define MAPWIDTH 40 #define MAPHEIGHT 40 #define tile 0 #define seen 1 randomize 5 goto *main #defcfunc map_onMap int dx,int dy if dx<0:return 0 if dy<0:return 0 if dx>=MAPWIDTH@:return 0 if dy>=MAPHEIGHT@:return 0 return 1 #defcfunc map_blockLOS int dx,int dy if map_onMap(dx,dy)=0 :return 0 if (map@(dx,dy,tile@) = '#'):return 1 return 0 #deffunc map_setSeen int dx, int dy if map_onMap(dx,dy)=0 :return map@(dx,dy,seen@)=1 return #module #defcfunc fov_scanCell int x, int y return map_blockLOS(x,y) #deffunc fov_applyCell int x, int y map_setSeen x,y return #defcfunc fov_slope double x1, double y1, double x2, double y2 xDiff=double(x1-x2) yDiff=double(y1-y2) if yDiff!0 :return double(xDiff/yDiff) :else: return 0 #defcfunc fov_invSlope double x1, double y1, double x2, double y2 slope=double(fov_slope(x1,y1,x2,y2)) if slope!0:return double(1/slope):else:return 0 #deffunc fov_scanNW2N int xCenter, int yCenter, int distance, int maxRadius, double startSlope, double endSlope if distance>maxRadius:return xStart =int(double(xCenter + 0.5 - (startSlope * distance))) xEnd =int(double(xCenter + 0.5 - (endSlope * distance))) yCheck =int(yCenter - distance) if xStart ! xCenter-(1*distance):fov_applyCell xStart,yCheck prevBlocked=fov_scanCell(xStart,yCheck) xCheck=int(xStart+1) while xCheck<=xEnd if xCheck!xCenter:fov_applyCell xCheck,yCheck if fov_scanCell(xCheck,yCheck){ if prevBlocked=0{ fov_scanNW2N xCenter,yCenter,distance+1,maxRadius,startSlope,fov_slope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck-0.000001),double(yCheck+0.999999)) } prevBlocked=1 }else{ if prevBlocked{ startSlopeCopy=fov_slope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck),double(yCheck)) } prevBlocked=0 } xCheck++:wend if prevBlocked=0{ fov_scanNW2N xCenter,yCenter,distance+1,maxRadius,startSlope,endSlope } return #deffunc fov_scanNE2N int xCenter, int yCenter, int distance, int maxRadius, double startSlope, double endSlope if distance>maxRadius:return xStart =int(double(xCenter + 0.5 - (startSlope * distance))) xEnd =int(double(xCenter + 0.5 - (endSlope * distance))) yCheck =int(yCenter - distance) if xStart!xCenter-(-1*distance):fov_applyCell xStart,yCheck prevBlocked=fov_scanCell(xStart,yCheck) xCheck=int(xStart-1) while xCheck>=xEnd if xCheck!xCenter:fov_applyCell xCheck,yCheck if fov_scanCell(xCheck,yCheck){ if prevBlocked=0{ fov_scanNE2N xCenter,yCenter,distance+1,maxRadius,startSlope,fov_slope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck+1),double(yCheck+0.99999)) } prevBlocked=1 }else{ if prevBlocked{ startSlopeCopy=fov_slope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck+0.9999999),double(yCheck)) } prevBlocked=0 } xCheck--:wend if prevBlocked=0:fov_scanNE2N xCenter,yCenter,distance+1,maxRadius,startSlope,endSlope return #deffunc fov_scanNW2W int xCenter, int yCenter, int distance, int maxRadius, double startSlope, double endSlope if distance>maxRadius:return yStart =int(double(yCenter + 0.5 - (startSlope * distance))) yEnd =int(double(yCenter + 0.5 - (endSlope * distance))) xCheck =int(xCenter - distance) if yStart!yCenter-(1*distance):fov_applyCell xCheck,yStart prevBlocked=fov_scanCell(xCheck,yStart) yCheck=int(yStart+1) while yCheck<=yEnd if yCheck!yCenter:fov_applyCell xCheck,yCheck if fov_scanCell(xCheck,yCheck){ if prevBlocked=0{ fov_scanNW2W xCenter,yCenter,distance+1,maxRadius,startSlope,fov_invSlope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck+0.99999),double(yCheck-0.00001)) } prevBlocked=1 }else{ if prevBlocked{ startSlopeCopy=fov_invSlope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck),double(yCheck)) } prevBlocked=0 } yCheck++:wend if prevBlocked=0:fov_scanNW2W xCenter,yCenter,distance+1,maxRadius,startSlope,endSlope return #deffunc fov_scanSW2W int xCenter, int yCenter, int distance, int maxRadius, double startSlope, double endSlope if distance>maxRadius:return yStart =int(double(yCenter + 0.5 - (startSlope * distance))) yEnd =int(double(yCenter + 0.5 - (endSlope * distance))) xCheck =int(xCenter - distance) if yStart!yCenter-(-1*distance):fov_applyCell xCheck,yStart prevBlocked=fov_scanCell(xCheck,yStart) yCheck=int(yStart-1) while yCheck>=yEnd if yCheck!yCenter:fov_applyCell xCheck,yCheck if fov_scanCell(xCheck,yCheck){ if prevBlocked=0{ fov_scanSW2W xCenter,yCenter,distance+1,maxRadius,startSlope,fov_invSlope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck+0.99999),double(yCheck+1)) } prevBlocked=1 }else{ if prevBlocked{ startSlopeCopy=fov_invSlope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck),double(yCheck+0.99999)) } prevBlocked=0 } yCheck--:wend if prevBlocked=0:fov_scanSW2W xCenter,yCenter,distance+1,maxRadius,startSlope,endSlope return #deffunc fov_scanSW2S int xCenter, int yCenter, int distance, int maxRadius, double startSlope, double endSlope if distance>maxRadius:return xStart =int(double(xCenter + 0.5 + (startSlope * distance))) xEnd =int(double(xCenter + 0.5 + (endSlope * distance))) yCheck =int(yCenter + distance) if xStart!xCenter+(-1*distance):fov_applyCell xStart,yCheck prevBlocked=fov_scanCell(xStart,yCheck) xCheck=int(xStart+1) while xCheck<=xEnd if xCheck!xCenter:fov_applyCell xCheck,yCheck if fov_scanCell(xCheck,yCheck){ if prevBlocked=0{ fov_scanSW2S xCenter,yCenter,distance+1,maxRadius,startSlope,fov_slope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck-0.00001),double(yCheck)) } prevBlocked=1 }else{ if prevBlocked{ startSlopeCopy=fov_slope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck),double(yCheck+0.99999)) } prevBlocked=0 } xCheck++:wend if prevBlocked=0:fov_scanSW2S xCenter,yCenter,distance+1,maxRadius,startSlope,endSlope return #deffunc fov_scanSE2S int xCenter, int yCenter, int distance, int maxRadius, double startSlope, double endSlope if distance>maxRadius:return xStart =int(double(xCenter + 0.5 + (startSlope * distance))) xEnd =int(double(xCenter + 0.5 + (endSlope * distance))) yCheck =int(yCenter + distance) if xStart!xCenter+(1*distance):fov_applyCell xStart,yCheck prevBlocked=fov_scanCell(xStart,yCheck) xCheck=int(xStart-1) while xCheck>=xEnd if xCheck!xCenter:fov_applyCell xCheck,yCheck if fov_scanCell(xCheck,yCheck){ if prevBlocked=0{ fov_scanSE2S xCenter,yCenter,distance+1,maxRadius,startSlope,fov_slope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck+1),double(yCheck)) } prevBlocked=1 }else{ if prevBlocked{ startSlopeCopy=fov_slope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck+0.99999),double(yCheck+0.99999)) } prevBlocked=0 } xCheck--:wend if prevBlocked=0:fov_scanSE2S xCenter,yCenter,distance+1,maxRadius,startSlope,endSlope return #deffunc fov_scanNE2E int xCenter, int yCenter, int distance, int maxRadius, double startSlope, double endSlope if distance>maxRadius:return yStart =int(double(yCenter + 0.5 + (startSlope * distance))) yEnd =int(double(yCenter + 0.5 + (endSlope * distance))) xCheck =int(xCenter + distance) if yStart!yCenter+(-1*distance):fov_applyCell xCheck,yStart prevBlocked=fov_scanCell(xCheck,yStart) yCheck=int(yStart+1) while yCheck<=yEnd if yCheck!yCenter:fov_applyCell xCheck,yCheck if fov_scanCell(xCheck,yCheck){ if prevBlocked=0{ fov_scanNE2E xCenter,yCenter,distance+1,maxRadius,startSlope,fov_invSlope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck),double(yCheck-0.00001)) } prevBlocked=1 }else{ if prevBlocked{ startSlopeCopy=fov_invSlope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck+0.99999),double(yCheck)) } prevBlocked=0 } yCheck++:wend if prevBlocked=0:fov_scanNE2E xCenter,yCenter,distance+1,maxRadius,startSlope,endSlope return #deffunc fov_scanSE2E int xCenter, int yCenter, int distance, int maxRadius, double startSlope, double endSlope if distance>maxRadius:return yStart =int(double(yCenter + 0.5 + (startSlope * distance))) yEnd =int(double(yCenter + 0.5 + (endSlope * distance))) xCheck =int(xCenter + distance) if yStart!yCenter+(1*distance): fov_applyCell xCheck,yStart prevBlocked=fov_scanCell(xCheck,yStart) yCheck=int(yStart-1) while yCheck>=yEnd if yCheck!yCenter:fov_applyCell xCheck,yCheck if fov_scanCell(xCheck,yCheck){ if prevBlocked=0{ fov_scanSE2E xCenter,yCenter,distance+1,maxRadius,startSlope,fov_invSlope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck),double(yCheck+1)) } prevBlocked=1 }else{ if prevBlocked{ startSlopeCopy=fov_invSlope(double(xCenter+0.5),double(yCenter+0.5),double(xCheck+0.99999),double(yCheck+0.99999)) } prevBlocked=0 } yCheck--:wend if prevBlocked=0:fov_scanSE2E xCenter,yCenter,distance+1,maxRadius,startSlope,endSlope return #deffunc FOV_start int x,int y,int maxRadius fov_applyCell x,y if maxRadius>0{ nL=1 while nL<=maxRadius fov_applyCell x,y-nL if fov_scanCell(x,y-nL):_break nL++:wend neL=1 while neL<=maxRadius fov_applyCell x+neL,y-neL if fov_scanCell(x+neL,y-neL):_break neL++:wend eL=1 while eL<=maxRadius fov_applyCell x+eL,y if fov_scanCell(x+eL,y):_break eL++:wend seL=1 while seL<=maxRadius fov_applyCell x+seL,y+seL if fov_scanCell(x+seL,y+seL):_break seL++:wend sL=1 while sL<=maxRadius fov_applyCell x,y+sL if fov_scanCell(x,y+sL):_break sL++:wend swL=1 while swL<=maxRadius fov_applyCell x-swL,y+swL if fov_scanCell(x-swL,y+swL):_break swL++:wend wL=1 while wL<=maxRadius fov_applyCell x-wL,y if fov_scanCell(x-wL,y):_break wL++:wend nwL=1 while nwL<=maxRadius fov_applyCell x-nwL,y-nwL if fov_scanCell(x-nwL,y-nwL):_break nwL++:wend if(nL!=1) or (nwL!=1): fov_scanNW2N x,y,1,maxRadius,1,0 if(nL!=1) or (neL!=1): fov_scanNE2N x,y,1,maxRadius,-1,0 if(nwL!=1) or (wL!=1): fov_scanNW2W x,y,1,maxRadius,1,0 if(swL!=1) or (wL!=1): fov_scanSW2W x,y,1,maxRadius,-1,0 if(swL!=1) or (sL!=1): fov_scanSW2S x,y,1,maxRadius,-1,0 if(seL!=1) or (sL!=1): fov_scanSE2S x,y,1,maxRadius,1,0 if(neL!=1) or (eL!=1): fov_scanNE2E x,y,1,maxRadius,-1,0 if(seL!=1) or (eL!=1): fov_scanSE2E x,y,1,maxRadius,1,0 return #global *main px=5:py=5 dim map,MAPWIDTH,MAPHEIGHT,2 repeat MAPHEIGHT y=cnt repeat MAPWIDTH if rnd(30)=0:map(cnt,y,tile)='#' if (y=0)or(y=MAPHEIGHT-1)or(cnt=0)or(cnt=MAPWIDTH-1):map(cnt,y,tile)='#' loop loop *main_loop redraw 0:color 0:boxf:color 255,255,255 repeat MAPHEIGHT y=cnt repeat MAPWIDTH x=cnt pos x*16,y*16 if map(x,y,seen)!0{ if map(x,y,tile)='#':mes "#":else:mes "." } if x=px :if y=py-1:mes "@" map(x,y,seen)=0 loop loop await 50: redraw 1 fov_start px,py,10 stick a,15 if a&1:px-- if a&2:py-- if a&4:px++ if a&8:py++ goto *main_loop



この記事に返信する


かきしす

リンク

2006/8/9(Wed) 18:37:43|NO.1910

解析に挑戦してみましたが、・・・・・すみません、全くわかりませんね。
他人のコメント無しプログラムは、概ね読みづらいものですが
とくに今回のソースは、僕と相性が悪いようで。

乗りかかった船だし、今日はお客さんも少なくて暇なので
僕の方式を組み込んでみました。        ダメですか?


#define MAPWIDTH 40 #define MAPHEIGHT 40 #define tile 0 #define seen 1 #define MaxSight 10 ;最大視界距離 randomize 5 ddim dxy,MaxSight*2+1 repeat MaxSight*2+1: dxy(cnt)=(1.0*cnt-Maxsight)/MaxSight: loop; 視界計算用変数 goto *main ;################################################################## *CheckSight repeat Maxsight*2+1: t_X=cnt; 最外周ブロック(一辺分)についてのループ flg1=1: flg2=1: flg3=1: flg4=1 repeat Maxsight: t_Y=cnt;  中心から最外周に向かってのループ dxy2=dxy(t_X)*t_Y chx=px+dxy2; 『chx』『chy』はチェックする場所。 if (chx >=0)and(chx <= (MAPWIDTH-1)){ chy=py-t_y if (chy >=0){;  上方向チェック map(chx,chy,seen)=flg1 if map(chx,chy,tile)='#':flg1=0 };------------------------------ chy=py+t_y if (chy <=(MAPHEIGHT-1)){;  下方向チェック map(chx,chy,seen)=flg2 if map(chx,chy,tile)='#':flg2=0 };------------------------------ } chy=py+dxy2 if (chy >=0)and(chy <= (MAPHEIGHT-1)){ chx=px-t_y if (chx >=0){;  左方向チェック map(chx,chy,seen)=flg3 if map(chx,chy,tile)='#':flg3=0 };------------------------------ chx=px+t_y if (chx <= (MAPWIDTH-1)){;  右方向チェック map(chx,chy,seen)=flg4 if map(chx,chy,tile)='#':flg4=0 };------------------------------ } loop loop return *main px=5:py=5:gsel 0,1 dim map,MAPWIDTH,MAPHEIGHT,2 repeat MAPHEIGHT y=cnt repeat MAPWIDTH if rnd(30)=0:map(cnt,y,tile)='#' if (y=0)or(y=MAPHEIGHT-1)or(cnt=0)or(cnt=MAPWIDTH-1):map(cnt,y,tile)='#' loop loop *main_loop redraw 0:color 0:boxf:color 255,255,255 gosub *CheckSight repeat MAPHEIGHT y=cnt repeat MAPWIDTH x=cnt pos x*16,y*16 if map(x,y,seen)=1{ if map(x,y,tile)='#':mes "#":else:mes "." } if (x=px)and (y=py):pos x*16,y*16:mes "@" map(x,y,seen)=0 loop loop await 50: redraw 1 stick a,15 if a&1:px=px-(px>1) if a&2:py=py-(py>1) if a&4:px=px+(px<(MAPWIDTH-2)) if a&8:py=py+(py<(MAPHEIGHT-2)) goto *main_loop



kz3

リンク

2006/8/9(Wed) 23:37:25|NO.1919

あのですね...本文読む前に本文が長いと分かればいいというものじゃないですよ。
>1. 不要部分の多い長いスクリプトの投稿は ご遠慮ください。
って書かれているのですから遠慮して別の方法で質問するべきではないですか?



うお

リンク

2006/8/10(Thu) 18:49:00|NO.1940

かきしすさん、再びコメントありがとうございます。
長いスクリプトだったので、レスがつくとは思っていませんでした。
kz3さん、次からは気をつけます。

さきほどから小一時間ほど、かきしすさんのスクリプトを
自分のゲームに組み込むため、いじくっています。
短い記述なのに、Cの方のプログラムをほぼ再現していて
かなり驚きです。
前に投稿してもらったサンプルを、もっとよく理解していれば
わざわざCのソースを移植することもなかったですね・・
大変参考になりました。

影の処理について、質問があります。
壁から少し離れると、以下のように左右対称ではない影ができます。


+++++ +++++ ++++ +++ ++ # @

chx,chyやループの回数をいじってみたのですが、
うまく処理できません。
もし左右対称にする方法があれば、
スクリプトのどの部分に手を加えればいいか
教えて頂けませんか?
よろしくお願いします。



かきしす

リンク

2006/8/11(Fri) 09:05:36|NO.1946

ちょっと解かりにくいかもしれませんが・・・

前のコードでは、
--中心から外周に向かって『光』を描いていき、壁に当たった以降は『影』を描いていく--
という行為を 扇状の左端から右端に、なめていました。
そのため 重複してチェックされるブロックでは、
障害物の左側の時は、先に『光』が描かれたのに、後で『影』で上描きされる。
逆に障害物の右側の時は、先に『影』が描かれたのに、後で『光』で上描きされる。
・・・と言った違いが出ていました。

それを防ぐため、今回は、
--フィールド初期値は『影』。--
--中心から外周に向かって『光』を描いていき、壁に当たった以降は描かない。--
と言う方式に変えました。

他にも、
--扇形の中心から、左右に2回に分けて調べる。--
方法でもいいのですが、プログラムが長く煩雑になるので避けました。

あと、ついでに少々高速化も図ってみました。


#define MAPWIDTH 40 #define MAPHEIGHT 40 #define tile 0 #define seen 1 #define MaxSight 10 ;最大視界距離 randomize 5 dim dxy,MaxSight*2+1,MaxSight repeat MaxSight*2+1: tmpx=cnt: repeat MaxSight: tmpy=cnt dxy(tmpx,tmpy)=int((1.0*tmpx- MaxSight)*tmpy/MaxSight) loop:loop; 視界計算用配列変数 ;計算をあらかじめ行うことで、メインループを軽くする。 goto *main ;################################################################## *CheckSight repeat Maxsight*2+1: t_X=cnt; 最外周ブロック(一辺分)についてのループ flg1=1: flg2=1: flg3=1: flg4=1 repeat Maxsight: t_Y=cnt;  中心から最外周に向かってのループ dxy2=dxy(t_X, t_Y) chx=px+dxy2; 『chx』『chy』はチェックする場所。 if (chx >=0)and(chx <= (MAPWIDTH-1)){ chy=py-t_y if (chy >=0)and(flg1=1){;  上方向チェック map(chx,chy,seen)=1 if map(chx,chy,tile)='#':flg1=0 };------------------------------ chy=py+t_y if (chy <=(MAPHEIGHT-1))and(flg2=1){;  下方向チェック map(chx,chy,seen)=1 if map(chx,chy,tile)='#':flg2=0 };------------------------------ } chy=py+dxy2 if (chy >=0)and(chy <= (MAPHEIGHT-1)){ chx=px-t_y if (chx >=0)and(flg3=1){;  左方向チェック map(chx,chy,seen)=1 if map(chx,chy,tile)='#':flg3=0 };------------------------------ chx=px+t_y if (chx <= (MAPWIDTH-1))and (flg4=1){;  右方向チェック map(chx,chy,seen)=1 if map(chx,chy,tile)='#':flg4=0 };------------------------------ } loop loop return *main px=5:py=5:gsel 0,1 dim map,MAPWIDTH,MAPHEIGHT,2 repeat MAPHEIGHT y=cnt repeat MAPWIDTH if rnd(30)=0:map(cnt,y,tile)='#' if (y=0)or(y=MAPHEIGHT-1)or(cnt=0)or(cnt=MAPWIDTH-1):map(cnt,y,tile)='#' loop loop *main_loop redraw 0:color 0:boxf:color 255,255,255 gosub *CheckSight repeat MAPHEIGHT y=cnt repeat MAPWIDTH x=cnt pos x*16,y*16 if map(x,y,seen)=1{ if map(x,y,tile)='#':mes "#":else:mes "." } if (x=px)and (y=py):pos x*16,y*16:mes "@" map(x,y,seen)=0 loop loop await 50: redraw 1 stick a,15 if a&1:px=px-(px>1) if a&2:py=py-(py>1) if a&4:px=px+(px<(MAPWIDTH-2)) if a&8:py=py+(py<(MAPHEIGHT-2)) goto *main_loop



うお

リンク

2006/8/11(Fri) 23:05:32|NO.1967

こんばんは。早速スクリプトを実行してみました。
影の精度に感心しました。最初の投稿に書いたURLに、
視界処理のスクリプトが多く公開されているんですが、
結果的にかきしすさんのプログラムが一番ツボにはまった感じです。
前のプログラムと比較しながら
しばらくいろいろといじって
ゲームの描写処理を作り直してみます。
感謝です!



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