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