フリーソフト超激辛ゲームレビュー様でHSPで作られたと思われる素晴らしいゲームが紹介されていました。Elonaというローグライクゲームです。詳しくは製作者様のサイトをご覧ください。
ローグ系はやったことも作ったこともあまり無いので処理内容の大半はよく分からないのですが、視野の計算がちょっと気になった&イメージが湧いたのでサンプルスクリプトを作成してみました。
左右非対称だったりと不完全ではありますが、充分実用に耐えうるのではないかと思われます。#const CHIP_SIZE 16 // マップチップの大きさ
#const WINX 320 // ウィンドウの大きさ
#const WINY 320
#const AREA_W WINX / CHIP_SIZE // マップの大きさ
#const AREA_H WINY / CHIP_SIZE
#const OBSTACLE_W 3 // 障害物の大きさ
#const OBSTACLE_H 2
//
// 数学関数
#define ctype max( %1, %2 ) ( %1 * ( %1 > %2 ) + %2 * ( %1 <= %2 ) )
#define ctype round( %1 ) double(strf("%%0.0f", %1))
//
// マップ描画用マクロ
#define draw_chip( %1, %2 ) boxf CHIP_SIZE * %1, CHIP_SIZE * %2, CHIP_SIZE * ( %1 + 1 ) - 2, CHIP_SIZE * ( %2 + 1 ) - 2
screen 0, WINX, WINY
randomize
sdim map, AREA_W * AREA_H
sdim shadow, AREA_W * AREA_H // 影を記録する変数。0なら明るい地点、それ以外は影。
gosub *make_blocks
onclick gosub *make_blocks
//
// メインループ
*main
if ( light_x != mousex / CHIP_SIZE ) | ( light_y != mousey / CHIP_SIZE ) {
renew = 1
}
if renew {
renew = 0
light_x = mousex / CHIP_SIZE
light_y = mousey / CHIP_SIZE
gosub *calc
gosub *draw
}
wait 2
goto *main
//
// 視野の計算
*calc
memset shadow, 2, AREA_W * AREA_H // 2...未検査
repeat AREA_H
y = cnt
dy = abs( y - light_y )
repeat AREA_W
if peek( shadow, y * AREA_W + cnt ) != 2 : continue
x = cnt
dx = abs( x - light_x )
// コメントアウトを解除すると、距離も考慮に入れるようになる
; if ( dx*dx+dy*dy > 48 ) {
; poke shadow, y * AREA_W + x, 1 // 1...検査済み(影)
; continue
; }
m = max( dx, dy )
repeat m
// 内分点の公式を使い、調査地点と光源の間にあるマス全てを調べる
_x = int(round(double( light_x * cnt + x * ( m - cnt ) ) / m))
_y = int(round(double( light_y * cnt + y * ( m - cnt ) ) / m))
if peek( map, _y * AREA_W + _x ) {
// 障害物を見つけた場合、今まで調べた地点はすべて影とする
repeat cnt + 1
_x = int(round(double( light_x * cnt + x * ( m - cnt ) ) / m))
_y = int(round(double( light_y * cnt + y * ( m - cnt ) ) / m))
poke shadow, _y * AREA_W + _x, 1 // 1...検査済み(影)
loop
break
}
poke shadow, _y * AREA_W + _x, 0 // 0...検査済み(明るい地点)
loop
loop
loop
return
//
// 各種描画処理
*draw
redraw 0
gosub *draw_map
gosub *draw_light
redraw 1
return
//
// マップを描画
*draw_map
color : boxf
repeat AREA_H
y = cnt
repeat AREA_W
if peek( map, y * AREA_W + cnt ) == 0 {
if peek( shadow, y * AREA_W + cnt ) {
color 192, 192, 192
} else {
color 255, 255, 255
}
draw_chip cnt, y
}
loop
loop
return
//
// 光源を描く
*draw_light
color 255, 128, 0
draw_chip light_x, light_y
return
//
// ブロックをランダムに配置
*make_blocks
memset map, 0, AREA_W * AREA_H
// 10個障害物を作成
repeat 10
poke map, rnd( AREA_W * AREA_H ), 1
loop
// 1個大きな障害物(OBSTACLE_WxOBSTACLE_H)を作成
x = rnd( AREA_W + 1 - OBSTACLE_W )
y = rnd( AREA_H + 1 - OBSTACLE_H )
repeat OBSTACLE_H
memset map, 1, OBSTACLE_W, ( y + cnt ) * AREA_W + x
loop
renew = 1
return
2007年8月16日木曜日
障害物のあるマップで視野を求める
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿