 
;
;	衝突判定サンプル(v.2.61)
;	勝手に Ver 3.x 化 by inovia
;
;矩形同士の判定、矩形と線分の判定を行います。
;
 
 
;#################################################################################
;
;	判定とかもろもろのモジュール
;
 
#module
 
;----------------------------------------
;矩形の枠のみを描画する
;	パラメータはboxfと同じ
#deffunc boxl int x1, int y1, int x2, int y2
 
    line x1, y1, x2, y1
    line x2, y1, x2, y2
    line x2, y2, x1, y2
    line x1, y2, x1, y1
    return
 
;----------------------------------------
;矩形と矩形との衝突判定
;mgetcoli_bb p1, p2[, p3]
;	矩形限定です。bbはBoxとBoxの略。
;	配列変数の中は、矩形の対角２点の座標が(x1,y1)-(x2,y2)だった場合、
;		p1.0 = x1
;		p1.1 = y1
;		p1.2 = x2
;		p1.3 = y2
;	としてください。（boxfのパラメータをそのまま順に配列にしするだけです。）
;	p2も同様です。
;	p3に0以外を指定すると、対角２点の位置関係を無視して処理します。0のときこれを考慮します。
;	statに判定結果が返されます。
;		0 : 衝突していない
;		1 : 衝突している
#deffunc mgetcoli_bb var bp1, var bp2, int fsw

    outstat = 0
 
    dim bpsw,4,2    ;bp1,bp2を書き換えないための処置
    memcpy bpsw, bp1, 16
    memcpy bpsw, bp2, 16, 16
    //dialog
    if fsw {
        ;強制的に左上-右下座標になるよう入れ替えます。
        repeat 2
            if bpsw.0.cnt>bpsw.2.cnt : bpsw.0.cnt+=bpsw.2.cnt : bpsw.2.cnt=bpsw.0.cnt-bpsw.2.cnt : bpsw.0.cnt-=bpsw.2.cnt
            if bpsw.1.cnt>bpsw.3.cnt : bpsw.1.cnt+=bpsw.3.cnt : bpsw.3.cnt=bpsw.1.cnt-bpsw.3.cnt : bpsw.1.cnt-=bpsw.3.cnt
        loop
    }
    ; 自分の四隅が対象より外でなければ当たっている（外にいれば１となるので!で否定しています）
    ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if ((bpsw.0.0>bpsw.2.1) | (bpsw.2.0<bpsw.0.1) | (bpsw.1.0>bpsw.3.1) | (bpsw.3.0<bpsw.1.1)) ! 1 : outstat=1
    return outstat
 
 
;----------------------------------------
;矩形と線分の衝突判定
;	矩形限定です。blはBoxとLineの略。
;mgetcoli_bl p1, x1, y1, x2, y2
;	p1:矩形の対角２点を指定した配列変数。(p1.0〜p1.3)
;	線分の両端座標：(x1, y1) - (x2, y2)
;	statに判定結果が返されます。
;		0 : 衝突していない
;		1 : 衝突している
#deffunc mgetcoli_bl array crpos, int x1, int y1, int x2, int y2

    outstat = 0
 
    ;線分の範囲内に矩形が存在するかチェック
    dim crpos2, 4
    crpos2 = x1, y1, x2, y2
    mgetcoli_bb crpos, crpos2, 1
    if stat=0 : return outstat
 
    ;４点のラインに対する位置をチェック
    ht = 0
    a = crpos.0 : b1 = crpos.1 : b2 = crpos.3
    gosub *hantei
    a = crpos.2 : b1 = crpos.1 : b2 = crpos.3
    gosub *hantei
 
    ;当たり判定
    if (ht=4)|(ht=-4) {
        outstat = 0        ;全て一致（はずれている）
    } else {
        outstat = 1        ;どれかひとつでも一致しなかった（重なっている）
    }
 
    return outstat
 
*hantei
    if x1!x2 {
        ;x座標がaの時の直線のy座標(bb)を求める。
        ;bb = ( (y1-y2)*a + (x1*y2)-(x2*y1) ) / (x1-x2)
        bb = ((y1-y2)*a + (x1*y2)-(x2*y1)) / (x1-x2)
        ;x座標が同じ2点が線に対して上にあるか下にあるか調べる。
        if bb>b1 : ht += -1    ;上（線より）
        if bb<b1 : ht += 1    ;下
        if bb>b2 : ht += -1    ;上（線より）
        if bb<b2 : ht += 1    ;下
    } else {
        if x1>a : ht += -1    ;左
        if x1<a : ht += 1    ;右
    }
    return
 
#global
;#################################################################################
 
;
;	初期化
;
title "衝突判定サンプル"
;自機
#define JIKIMV 3    ;自機の移動量
dim intJikiPos, 2    ;自機の場所
dim intJikiHitA, 2    ;自機の当たり判定サイズ
dim hanteiA, 4
intJikiPos = ginfo_winx/2, ginfo_winy/2
intJikiHitA = 30, 40
 
;敵
dim intTekiA, 4
intTekiA = 50,50, 100,100
 
;レーザー
dim lz, 4    ;ライン座標（始点と終点）
lz = ginfo_winx/2, 100, 0, ginfo_winy-100
dlz = 1
 
 
;
;	メイン
;
*main
	;title ""+fhit
    redraw 0
    ;
    ;	画面の初期化
    ;
    color 255,255,255 : boxf : color 0,0,0
 
    ;
    ;	移動処理
    ;
    stick key, 255
    gosub *keiinput
 
    ;レーザーの移動
    if lz.2>=ginfo_winx : dlz = -1
    if lz.2<=0 : dlz = 1
    lz.2+= dlz*3
 
    ;
    ;	衝突判定
    ;
    fhit = 0    ;判定フラグ
    ;自機とレーザーの衝突判定
    hanteiA = intJikiPos.0, intJikiPos.1, intJikiPos.0 + intJikiHitA.0, intJikiPos.1 + intJikiHitA.1
    mgetcoli_bl hanteiA, lz.0, lz.1, lz.2, lz.3
    if stat : fhit = 1
    ;自機と敵との衝突判定と敵の描画
    mgetcoli_bb hanteiA, intTekiA, 1
    if stat : fhit = 1
    ;自機と領域との衝突判定と領域描画
    ff=200,50,ginfo_winx-100,30
    mgetcoli_bb ff, hanteiA
    if stat : fhit = 1
 
    ;
    ;	オブジェクト描画
    ;
    ;レーザー描画
    line lz.0, lz.1, lz.2, lz.3
    pos lz.0-32, lz.1-16 : mes "レーザー"
    ;敵描画
    boxl intTekiA.0, intTekiA.1, intTekiA.2, intTekiA.3        ;敵の衝突領域
    pos intTekiA.0, intTekiA.1 : mes "敵"
    ;領域描画
    boxl ff.0, ff.1, ff.2, ff.3
 
    ;自機の衝突判定領域を描画
    if fhit=1 : color 255,0,0
    boxl hanteiA.0, hanteiA.1, hanteiA.2, hanteiA.3
    pos hanteiA.0, hanteiA.1 : mes "自機"
 
    redraw 1
    await 5
goto *main
 
stop
 
 
 
;###########################
;サブルーチン
;###########################
 
;キー入力
*keiinput
    if key&1 : addx = -JIKIMV
    if key&2 : addy = -JIKIMV
    if key&4 : addx =  JIKIMV
    if key&8 : addy =  JIKIMV
    if key&128 : end
 
    ;自機移動量設定
    intJikiPos.0+= addx
    intJikiPos.1+= addy
    addx = 0 : addy = 0
 
return