|
|
2007/6/14(Thu) 16:49:25|NO.8918
懐中電灯を照らした時のような処理はどうやったらできますか?
例えば、見下ろしがたのマップで、90度の範囲だけ見えて、
また途中に障害物があったら、障害物の後ろには光がいかないようにしたいです。
サンプルをくれると嬉しいです。
|
|
2007/6/16(Sat) 06:39:38|NO.8967
ばけものさん、はじめまして。
基本的には通常のアクションゲームの描画処理で良いと思いますが、マップデータを照合しながら「どこまで光が届くか?」を調べて光が当たる部分だけマップを描画すれば良いと思います。
扇型はいろいろと処理がややこしくなるので、まず一直線に進む(レーザーのような)光を考えてみてはいかがでしょうか。
|
|
2007/6/18(Mon) 00:34:22|NO.9005
>例えば、見下ろしがたのマップで、90度の範囲だけ見えて、
>また途中に障害物があったら、障害物の後ろには光がいかないようにしたいです。
gsquareを使うと色々な形を塗り潰す事が出来るので、使えるかもしれない
(画像の半透明コピーじゃ無ければ処理も軽いし)
//指定角度の範囲外をマスクしたり影を出したりのモジュール
#module "l_s"
#define global PI 3.1415926535897932384626433832795 //180度
#define global HPI 1.5707963267948966192313216916398 //90度
#define global QPI 0.78539816339744830961566084581988 //45度
#define LMS 1200 //ライトマスクのサイズ(ウィンドウより大きくしないとマスクされない所が出る)
#deffunc light int id,int px,int py,double r,double rw,int tsx,int tsy,int sw
sx=int(sin(r-rw/2)*LMS+px),int(sin(r-HPI*((rw>0)-(rw<0)))*LMS+px),int(-sin(r)*LMS+px),int(px)
sy=int(cos(r-rw/2)*LMS+py),int(cos(r-HPI*((rw>0)-(rw<0)))*LMS+py),int(-cos(r)*LMS+py),int(py)
if id<0 {gsquare -1,sx,sy}else{es=0,tsx,tsx,0 :ey=0,0,tsy,tsy :gsquare id,sx,sy,ex,ey}
if sw=0 {light id,px,py,r,-rw,,,1} //反対側の処理
return
#deffunc shadow int id,int bx,int by,double w,double h,int px,int py,int tsx,int tsy
dx=bx-px :dy=by-py :r=atan(-dx,-dy) //ライト位置から障害物の方向(r)収得
wx=sin(r+HPI)*w :wy=cos(r+HPI)*w //影を発生させる左右の大きさを収得
r1=atan(-wx-dx,-wy-dy) :r2=atan(wx-dx,wy-dy) //影の広がる角度(ライト位置から影が発生する位置の角度)
xl=bx+wx :xr=bx-wx :yl=by+wy :yr=by-wy //影の発生位置
sx=int(xl-sin(r1)*h),int(xr-sin(r2)*h),xr,xl //影のx座標(先端左,先端右,根元右,根元左)
sy=int(yl-cos(r1)*h),int(yr-cos(r2)*h),yr,yl //影のy座標(先端左,先端右,根元右,根元左)
if id<0 {gsquare -1,sx,sy}else{es=0,tsx,tsx,0 :ey=0,0,tsy,tsy :gsquare id,sx,sy,ex,ey}
return
#global
//モジュールここまで
//モジュール使用例
randomize 1245
buffer 1 :picload dir_exe+"\\sample\\hgimg3\\testchr.bmp":gzoom 128,64,1,0,0,256,128,1
//lang=ライトの向き(0.0で真下ラジアン単位) lx:ly=ライトの座標 bw=影の最小幅 bh=影の高さ
lang=PI :lx=320 :ly=300 :bw=18 :bh=1200
dim map,20,16
repeat 13,1:cnty=cnt:repeat 17,1:map(cnt,cnty)=rnd(20)=0:loop:loop
gsel 0,1:mouse ginfo(4)+lx,ginfo(5)+ly
repeat //メインループ
bmax=0
gmode 1,32,32
repeat 16
cnty=cnt
repeat 20
pos cnt*32,cnty*32 :gcopy 1,32*(2+map(cnt,cnty)),0
if map(cnt,cnty)=1 {bx(bmax)=cnt*32+16 :by(bmax)=cnty*32+16 :bmax++} //障害物の中心座標代入
loop
loop
gmode 3,,,100 :color //半透明で黒に設定
repeat bmax
//shadow -1(塗り潰し), 障害物の座標中心座標x, y, 影の最小幅, 影の高さ, ライトの座標x, y
shadow -1,bx(cnt),by(cnt),bw,bh,lx,ly //p1,p2で指定した座標から影を発生させる
loop
gmode 3,,,150 :color 80//shadowとの違いが分かるように半透明で赤に設定
//light -1(塗り潰し), ライトの座標x, y, 向き, 広がる角度
light -1,lx,ly,lang,HPI //指定座標、向きから p5に設定された範囲以外を塗り潰す(p5は180度まで(ラジアン単位))
redraw 1 :await 10 :redraw 0
lx=mousex :ly=mousey :lang+=0.001454*mousew //マウスでライト移動、ホイール回転でライト回転
stick k,$fff
if k&256{lang+0.02}else{if k&512{lang-0.02}} //左右クリックでライト回転
loop
何をするために必要な処理なのか分からないので
演出として使う事しか考えてません・・・
| |
|
2007/6/18(Mon) 20:17:58|NO.9019
驚愕しました。ありがとうございます。
|
|
2007/6/18(Mon) 21:10:15|NO.9021
ちょっとモジュール内に間違いがありました。(NO.9005のサンプルを実行するだけなら問題無いけど)
light命令とshadow命令内の
> if id<0 {gsquare -1,sx,sy}else{es=0,tsx,tsx,0 :ey=0,0,tsy,tsy :gsquare id,sx,sy,ex,ey}
この部分(一箇所ずつあります)と
if id<0 {gsquare -1,sx,sy}else{ex=0,tsx,tsx,0 :ey=0,0,tsy,tsy :gsquare id,sx,sy,ex,ey}
を置き換え
light命令内の
> if sw=0 {light id,px,py,r,-rw,,,1} //反対側の処理
これを
if sw=0 {light id,px,py,r,-rw,tsy,tsy,1} //反対側の処理
これに置き換えてきださい
オマケのサンプル(NO.9005のモジュールを修正して使用するのが前提)
グラデーションを付けた画像を色減算合成して影の根元の輪郭をぼやかしてみる
(根元以外は普通の塗り潰し)
//モジュール(l_s)を使う事が前提のマクロ
#define global _gsquare(%1,%2,%3,%4,%5) \
if %1<0 {gsquare -1,%2,%3}else{ex@tmp=0,%4,%4,0:ey@tmp=0,0,%5,%5 :gsquare %1,%2,%3,ex@tmp,ey@tmp}
#define global extra_shadow(%1,%2,%3=0,%4=0) \
sx@tmp=int(-sin(r1@l_s)*(%2)+sx@l_s),int(-sin(r2@l_s)*(%2)+sx@l_s(1)),sx@l_s(1),sx@l_s:\
sy@tmp=int(-cos(r1@l_s)*(%2)+sy@l_s),int(-cos(r2@l_s)*(%2)+sy@l_s(1)),sy@l_s(1),sy@l_s:\
_gsquare %1,sx@tmp,sy@tmp,%3,%4
//マクロここまで
screen 2,100,100,8,0,0 //影用グラデーション画像用意
repeat 64:c=limit(255-cnt*10,0,255):color c,c,c:circle -10,cnt*2+20,108,180,1:loop
randomize
//lx:ly=ライトの座標 bw=影の最小幅 bh=影の高さ bmax=ブロックの数
lx=320 :ly=300 :bw=20 :bh=1200 :bmax=20
repeat bmax :bx(cnt)=(rnd(17)+1)*32 :by(cnt)=(rnd(13)+1)*32 :loop
gsel 0,1:mouse ginfo(4)+lx,ginfo(5)+ly
repeat //メインループ
color 0,80,80 :boxf :color 200
repeat bmax :boxf bx(cnt)-16,by(cnt)-16,bx(cnt)+16,by(cnt)+16 :loop
repeat bmax
gmode 6,,,255 //色減算合設定
//shadow ウィンドウID, 障害物の中心座標x, y, 影の最小幅, 影の高さ, ライトの座標x, y, 影に使う元画像のサイズx, y
shadow 2,bx(cnt),by(cnt),bw,bw*2,lx,ly,99,99 //グラデーションの画像を影に使用
gmode 0 :color //不透明で黒に設定
//shadow2 -1(塗り潰し),影の高さ
extra_shadow -1,bh //shadowで作った影に繋げて伸ばす(影全部に半透明合成した画像を使うと重くなるので)
loop
redraw 1 :await 15 :redraw 0 :lx=mousex :ly=mousey
loop
これを、NO.9005の //モジュール使用例 より下全部置き換えてみてください
・命令の説明
「モジュール名 l_s 内の各命令書式」
[ライトの範囲以外をマスク描画]
light p1,p2,p3,p4,p5,p6,p7,p8
p1= コピー元ウィンドウID(-1=塗り潰し)
p2= ライト座標x
p3= ライト座標y
p4= ライトの向き(ラジアン単位)
p5= ライトの広がる角度(0.0〜3.1415……)
p6= p1が-1以外の時コピー元の幅(画像は座標0,0から使われる)
p7= p1が-1以外の時コピー元の高さ
p8= 半分だけマスクしたい時に1(通常指定する必要なし)
1にした場合p6がマイナスかプラスで左右の選択
[ライトから障害物の影幅を元にした方向に障害物から陰を伸ばす]
shadow p1,p2,p3,p4,p5,p6,p7,p8,p9
p1= コピー元ウィンドウID(-1=塗り潰し)
p2= 障害物の中心座標x
p3= 障害物の中心座標y
p4= 影の最小幅
p5= 影の高さ
p6= ライト座標x
p7= ライト座標y
p8= p1が-1以外の時コピー元の幅(画像は座標0,0から使われる)
p9= p1が-1以外の時コピー元の高さ
「マクロ命令書式(モジュールl_sを使用する前提)」
[shadowで作った影に繋げて影を伸ばす(注:必ずshadowの後に使用)]
extra_shadow %1,%2,%3,%4
%1= コピー元ウィンドウID(-1=塗り潰し)
%2= 影の高さ
%3= %1が-1以外の時コピー元の幅(画像は座標0,0から使われる)
%4= %1が-1以外の時コピー元の高さ
| |
|