/*
###################################
#
# dxrubyex.c Ver. 1.0.4
#
###################################
*/
#include "ruby.h"
#include <memory.h>
#include <math.h>

#ifndef RSTRING_PTR
#  define RSTRING_PTR(s) (RSTRING(s)->ptr)
#endif
#ifndef RSTRING_LEN
#  define RSTRING_LEN(s) (RSTRING(s)->len)
#endif

#define DXRUBYEX_VERSION "1.0.4"

#define check_box_box(b1, b2) ( (b1)->x + (b1)->x1 <= (b2)->x + (b2)->x2 && \
                                (b1)->y + (b1)->y1 <= (b2)->y + (b2)->y2 && \
                                (b2)->x + (b2)->x1 <= (b1)->x + (b1)->x2 && \
                                (b2)->y + (b2)->y1 <= (b1)->y + (b1)->y2 )

#define check_circle_circle(c1, c2) ( ((c1)->r + (c2)->r) * ((c1)->r + (c2)->r) >= \
                                     (((c1)->x + (c1)->x1)-((c2)->x + (c2)->x1)) * (((c1)->x + (c1)->x1)-((c2)->x + (c2)->x1))+ \
                                     (((c1)->y + (c1)->y1)-((c2)->y + (c2)->y1)) * (((c1)->y + (c1)->y1)-((c2)->y + (c2)->y1)) )

#define check_box_point(b, p) ( (b)->x + (b)->x1 <= (p)->x && \
                                (b)->y + (b)->y1 <= (p)->y && \
                                (b)->x + (b)->x2 >= (p)->x && \
                                (b)->y + (b)->y2 >= (p)->y )

#define check_circle_point(c, p) ( ((c)->r * (c)->r) >= \
                                   ((c)->x + (c)->x1 - (p)->x) * ((c)->x + (c)->x1 - (p)->x) + \
                                   ((c)->y + (c)->y1 - (p)->y) * ((c)->y + (c)->y1 - (p)->y) )

#define intersect(p1, p2, p3, p4) ( (((p1)->x - (p2)->x) * ((p3)->y - (p1)->y) + ((p1)->y - (p2)->y) * ((p1)->x - (p3)->x)) * \
                                    (((p1)->x - (p2)->x) * ((p4)->y - (p1)->y) + ((p1)->y - (p2)->y) * ((p1)->x - (p4)->x)) )

#define checkline(p1, p2, p3, p4) (((((p1)->x - (p2)->x) * ((p3)->y - (p1)->y) + ((p1)->y - (p2)->y) * ((p1)->x - (p3)->x)) * \
                                    (((p1)->x - (p2)->x) * ((p4)->y - (p1)->y) + ((p1)->y - (p2)->y) * ((p1)->x - (p4)->x)) < 0) && \
                                   ((((p3)->x - (p4)->x) * ((p1)->y - (p3)->y) + ((p3)->y - (p4)->y) * ((p3)->x - (p1)->x)) * \
                                    (((p3)->x - (p4)->x) * ((p2)->y - (p3)->y) + ((p3)->y - (p4)->y) * ((p3)->x - (p2)->x)) < 0 ))

static VALUE mDXRubyExtension;  /* DXRubyExtensionモジュール */
static VALUE mCollision;        /* 当たり判定モジュール */
static VALUE mArrayExtension;   /* 拡張モジュール       */
static VALUE cCollisionBox;     /* 矩形範囲クラス       */
static VALUE cCollisionCircle;  /* 円範囲クラス         */
static VALUE cCollisionPoint;   /* 点クラス             */
static VALUE cCollisionTriangle;/* 三角クラス           */
static VALUE eDXRubyExError;    /* 例外                 */

/* 共通範囲データ */
struct CollisionData {
    VALUE self;                 /* 衝突通知先オブジェクト */
    int delflag;                /* 消えたオブジェクト */
};

/* 矩形範囲データ */
struct CollisionBox {
    VALUE self;                 /* 衝突通知先オブジェクト */
    int delflag;                /* 消えたオブジェクト */
    int x;                      /* 座標 x */
    int y;                      /* 座標 y */
    int x1;                     /* 判定範囲 左 */
    int y1;                     /* 判定範囲 上 */
    int x2;                     /* 判定範囲 右 */
    int y2;                     /* 判定範囲 下 */
};

/* 円範囲データ */
struct CollisionCircle {
    VALUE self;                 /* 衝突通知先オブジェクト */
    int delflag;                /* 消えたオブジェクト */
    int x;                      /* 座標 x */
    int y;                      /* 座標 y */
    int x1;                     /* 判定中心 x */
    int y1;                     /* 判定中心 y */
    int r;                      /* 半径 */
};

/* 点データ */
struct CollisionPoint {
    VALUE self;                 /* 衝突通知先オブジェクト */
    int delflag;                /* 消えたオブジェクト */
    int x;                      /* 座標 x */
    int y;                      /* 座標 y */
};

/* 三角データ */
struct CollisionTriangle {
    VALUE self;                 /* 衝突通知先オブジェクト */
    int delflag;                /* 消えたオブジェクト */
    float x;                       /* 座標 x */
    float y;                       /* 座標 y */
    float x1;                      /* 座標 x1 */
    float y1;                      /* 座標 y1 */
    float x2;                      /* 座標 x2 */
    float y2;                      /* 座標 y2 */
    float x3;                      /* 座標 x3 */
    float y3;                      /* 座標 y3 */
};

struct Point {
    int x;
    int y;
};
struct PointF {
    float x;
    float y;
};
struct Vector {
    int x;
    int y;
};

ID id_hit;
ID id_shot;

static void release_CollisionBox( struct CollisionBox *box );
static void release_CollisionCircle( struct CollisionCircle *circle );
static void release_CollisionPoint( struct CollisionPoint *point );
static void release_CollisionTriangle( struct CollisionTriangle *tri );

/*********************************************************************
 * Collisionモジュール
 * 当たり判定を行う。
 *********************************************************************/

/*--------------------------------------------------------------------
    (内部処理用)三角と点の判定
 ---------------------------------------------------------------------*/
/* へこんでない右回りの三角と点 */
static int checktriangle(struct PointF *p, struct PointF *p1, struct PointF *p2, struct PointF *p3)
{
    struct PointF c;

    if( (p1->x - p3->x) * (p1->y - p2->y) == (p1->x - p2->x) * (p1->y - p3->y) )
    {
        return 0;
    }

    c.x = (p1->x + p2->x + p3->x) / 3; /* 中心点x */
    c.y = (p1->y + p2->y + p3->y) / 3; /* 中心点y */

    if( intersect(p1, p2, p, &c) < 0 ||
        intersect(p2, p3, p, &c) < 0 ||
        intersect(p3, p1, p, &c) < 0 )
    {
        return 0;
    }
    return -1;
}


/*--------------------------------------------------------------------
    (内部処理用)円と線分の判定
 ---------------------------------------------------------------------*/
/* 円と線分の判定 */
static int checkCircleLine( struct CollisionCircle *ptc, struct Point *pt1, struct Point *pt2)
{
    float n1, n2, n3;
    /* vは線分始点から終点 */
    /* cは線分始点から円中心 */
    struct Vector v = {pt2->x - pt1->x, pt2->y - pt1->y};
    struct Vector c = {(ptc->x + ptc->x1) - pt1->x, (ptc->y + ptc->y1) - pt1->y};

    if( v.x == 0 && v.y == 0 )
    {
        return check_circle_point(ptc, pt1);
    }

    /* 二つのベクトルの内積を求める */
    n1 = v.x * c.x + v.y * c.y;

    if( n1 < 0 )
    {
        /* cの長さが円の半径より小さい場合は交差している */
        return c.x*c.x + c.y*c.y < ptc->r * ptc->r ? -1 : 0;
    }

    n2 = v.x * v.x + v.y * v.y;

    if( n1 > n2 )
    {
        int len;
        /* 線分の終点と円の中心の距離の二乗を求める */
        len = (pt2->x - (ptc->x + ptc->x1))*(pt2->x - (ptc->x + ptc->x1)) + (pt2->y - (ptc->y + ptc->y1))*(pt2->y - (ptc->y + ptc->y1));
        /* 円の半径の二乗よりも小さい場合は交差している */
        return  len < ptc->r * ptc->r ? -1 : 0;
    }
    else
    {
        n3 = c.x * c.x + c.y * c.y;
        return ( n3-(n1/n2)*n1 < ptc->r * ptc->r ) ? -1 : 0;
    }
    return 0;
}


/*--------------------------------------------------------------------
    (内部処理用)判定処理
 ---------------------------------------------------------------------*/
int check(struct CollisionData *data1, struct CollisionData *data2, VALUE o_data, VALUE d_data )
{
    if( RDATA(o_data)->dfree == RDATA(d_data)->dfree )
    {
        /* 同じ形同士の比較 */
        if( RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionBox )
        {
            /* 矩形による判定 */
            return check_box_box((struct CollisionBox *)data1, (struct CollisionBox *)data2);
        }
        else if( RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionCircle )
        {
            /* 円による判定 */
            return check_circle_circle((struct CollisionCircle*)data1, (struct CollisionCircle*)data2);
        }
        else if( RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionPoint )
        {
            /* 点による判定 */
            return ((struct CollisionPoint*)data1)->x == ((struct CollisionPoint*)data2)->x &&
                   ((struct CollisionPoint*)data1)->y == ((struct CollisionPoint*)data2)->y;
        }
        else if( RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionTriangle )
        {
            struct CollisionTriangle *tri1 = ((struct CollisionTriangle *)data1);
            struct CollisionTriangle *tri2 = ((struct CollisionTriangle *)data2);
            /* 三角同士による判定 */
            struct PointF pa1 = {tri1->x + tri1->x1, tri1->y + tri1->y1};
            struct PointF pa2 = {tri1->x + tri1->x2, tri1->y + tri1->y2};
            struct PointF pa3 = {tri1->x + tri1->x3, tri1->y + tri1->y3};
            struct PointF pb1 = {tri2->x + tri2->x1, tri2->y + tri2->y1};
            struct PointF pb2 = {tri2->x + tri2->x2, tri2->y + tri2->y2};
            struct PointF pb3 = {tri2->x + tri2->x3, tri2->y + tri2->y3};

            return checktriangle(&pa1, &pb1, &pb2, &pb3) || checktriangle(&pb1, &pa1, &pa2, &pa3) ||
                   checkline(&pa1, &pa2, &pb1, &pb2) || checkline(&pa1, &pa2, &pb2, &pb3) || checkline(&pa1, &pa2, &pb3, &pb1) ||
                   checkline(&pa2, &pa3, &pb1, &pb2) || checkline(&pa2, &pa3, &pb2, &pb3) || checkline(&pa2, &pa3, &pb3, &pb1) ||
                   checkline(&pa3, &pa1, &pb1, &pb2) || checkline(&pa3, &pa1, &pb2, &pb3) || checkline(&pa3, &pa1, &pb3, &pb1);
        }
        else
        {
            rb_raise( rb_eTypeError, "ありえないエラーその１" );
        }

    } /* if( RDATA(o_data)->dfree == RDATA(d_data)->dfree ) */
    else
    {
        /* 違う形の比較 */
        if( (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionBox &&
             RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionCircle ) ||
            (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionCircle &&
             RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionBox ) )
        {
            /* 矩形と円 */
            struct CollisionBox *box;
            struct CollisionCircle *circle;

            /* いれかえ */
            if( RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionBox )
            {
                box = (struct CollisionBox *)data1;
                circle = (struct CollisionCircle *)data2;
            }
            else
            {
                box = (struct CollisionBox *)data2;
                circle = (struct CollisionCircle *)data1;
            }
            {
                struct CollisionBox box1;
                struct CollisionBox box2;
                struct CollisionCircle circle1;
                struct CollisionCircle circle2;
                struct CollisionCircle circle3;
                struct CollisionCircle circle4;

                /* 点の位置 */
                struct Point point = {circle->x + circle->x1, circle->y + circle->y1};

                /* 横長の矩形 */
                box1.x = box->x;
                box1.y = box->y;
                box1.x1 = box->x1 - circle->r;
                box1.y1 = box->y1;
                box1.x2 = box->x2 + circle->r;
                box1.y2 = box->y2;
                /* 縦長の矩形 */
                box2.x = box->x;
                box2.y = box->y;
                box2.x1 = box->x1;
                box2.y1 = box->y1 - circle->r;
                box2.x2 = box->x2;
                box2.y2 = box->y2 + circle->r;
                /* 円 */
                circle1.r = circle2.r = circle3.r = circle4.r = circle->r;
                circle1.x = box->x;             /* 左上カド */
                circle1.y = box->y;
                circle1.x1 = box->x1;
                circle1.y1 = box->y1;
                circle2.x = box->x;             /* 右上カド */
                circle2.y = box->y;
                circle2.x1 = box->x2;
                circle2.y1 = box->y1;
                circle3.x = box->x;             /* 右下カド */
                circle3.y = box->y;
                circle3.x1 = box->x2;
                circle3.y1 = box->y2;
                circle4.x = box->x;             /* 左下カド */
                circle4.y = box->y;
                circle4.x1 = box->x1;
                circle4.y1 = box->y2;

                /* 判定 */
                return check_box_point(&box1, &point) || 
                       check_box_point(&box2, &point) ||
                       check_circle_point(&circle1, &point) ||
                       check_circle_point(&circle2, &point) ||
                       check_circle_point(&circle3, &point) ||
                       check_circle_point(&circle4, &point);
            }
        }
        else  if( (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionBox &&
                   RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionPoint ) ||
                  (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionPoint &&
                   RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionBox ) )
        {
            /* 矩形と点 */
            struct CollisionBox *box;
            struct CollisionPoint *point;

            /* いれかえ */
            if( RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionBox )
            {
                box = (struct CollisionBox *)data1;
                point = (struct CollisionPoint *)data2;
            }
            else
            {
                box = (struct CollisionBox *)data2;
                point = (struct CollisionPoint *)data1;
            }

            /* 判定 */
            return check_box_point(box, point);
        }
        else  if( (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionCircle &&
                   RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionPoint ) ||
                  (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionPoint &&
                   RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionCircle ) )
        {
            /* 円と点 */
            struct CollisionCircle *circle;
            struct CollisionPoint *point;

            /* いれかえ */
            if( RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionCircle )
            {
                circle = (struct CollisionCircle *)data1;
                point = (struct CollisionPoint *)data2;
            }
            else
            {
                circle = (struct CollisionCircle *)data2;
                point = (struct CollisionPoint *)data1;
            }

            /* 判定 */
            return check_circle_point(circle, point);
        }
        else  if( (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionTriangle &&
                   RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionCircle ) ||
                  (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionCircle &&
                   RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionTriangle ) )
        {
            /* 三角と円 */
            struct CollisionTriangle *tri;
            struct CollisionCircle *circle;

            /* いれかえ */
            if( RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionTriangle )
            {
                tri = (struct CollisionTriangle *)data1;
                circle = (struct CollisionCircle *)data2;
            }
            else
            {
                tri = (struct CollisionTriangle *)data2;
                circle = (struct CollisionCircle *)data1;
            }
            {
                /* 判定 */
                struct Point pt1 = {tri->x + tri->x1, tri->y + tri->y1};
                struct Point pt2 = {tri->x + tri->x2, tri->y + tri->y2};
                struct Point pt3 = {tri->x + tri->x3, tri->y + tri->y3};
                struct Point p = {circle->x + circle->x1, circle->y + circle->y1};
                struct PointF fpt1 = {tri->x + tri->x1, tri->y + tri->y1};
                struct PointF fpt2 = {tri->x + tri->x2, tri->y + tri->y2};
                struct PointF fpt3 = {tri->x + tri->x3, tri->y + tri->y3};
                struct PointF fp = {circle->x + circle->x1, circle->y + circle->y1};

                return checktriangle(&fp, &fpt1, &fpt2, &fpt3) || checkCircleLine(circle, &pt1, &pt2) ||
                       checkCircleLine(circle, &pt2, &pt3) || checkCircleLine(circle, &pt3, &pt1);
            }
        }
        else  if( (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionTriangle &&
                   RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionPoint ) ||
                  (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionPoint &&
                   RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionTriangle ) )
        {
            /* 三角と点 */
            struct CollisionTriangle *tri;
            struct CollisionPoint *point;

            /* いれかえ */
            if( RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionTriangle )
            {
                tri = (struct CollisionTriangle *)data1;
                point = (struct CollisionPoint *)data2;
            }
            else
            {
                tri = (struct CollisionTriangle *)data2;
                point = (struct CollisionPoint *)data1;
            }
            {
                /* 判定 */
                struct PointF pt1 = {tri->x + tri->x1, tri->y + tri->y1};
                struct PointF pt2 = {tri->x + tri->x2, tri->y + tri->y2};
                struct PointF pt3 = {tri->x + tri->x3, tri->y + tri->y3};
                struct PointF p = {point->x, point->y};

                return checktriangle(&p, &pt1, &pt2, &pt3);
            }
        }
        else  if( (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionBox &&
                   RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionTriangle ) ||
                  (RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionTriangle &&
                   RDATA(d_data)->dfree == (RUBY_DATA_FUNC)release_CollisionBox ) )
        {
            /* 矩形と三角 */
            struct CollisionBox *box;
            struct CollisionTriangle *tri;

            /* いれかえ */
            if( RDATA(o_data)->dfree == (RUBY_DATA_FUNC)release_CollisionBox )
            {
                box = (struct CollisionBox *)data1;
                tri = (struct CollisionTriangle *)data2;
            }
            else
            {
                box = (struct CollisionBox *)data2;
                tri = (struct CollisionTriangle *)data1;
            }

            {
                struct PointF p1 = {box->x + box->x1, box->y + box->y1};
                struct PointF p2 = {box->x + box->x2, box->y + box->y1};
                struct PointF p3 = {box->x + box->x2, box->y + box->y2};
                struct PointF p4 = {box->x + box->x1, box->y + box->y2};
                struct PointF pt1 = {tri->x + tri->x1, tri->y + tri->y1};
                struct PointF pt2 = {tri->x + tri->x2, tri->y + tri->y2};
                struct PointF pt3 = {tri->x + tri->x3, tri->y + tri->y3};
                /* 判定 */
                return checktriangle(&p1, &pt1, &pt2, &pt3) || checktriangle(&pt1, &p1, &p2, &p3) || checktriangle(&pt1, &p1, &p3, &p4) ||
                       checkline(&p1, &p2, &pt1, &pt2) || checkline(&p1, &p2, &pt2, &pt3) || checkline(&p1, &p2, &pt3, &pt1) ||
                       checkline(&p2, &p3, &pt1, &pt2) || checkline(&p2, &p3, &pt2, &pt3) || checkline(&p2, &p3, &pt3, &pt1) ||
                       checkline(&p3, &p4, &pt1, &pt2) || checkline(&p3, &p4, &pt2, &pt3) || checkline(&p3, &p4, &pt3, &pt1) ||
                       checkline(&p4, &p1, &pt1, &pt2) || checkline(&p4, &p1, &pt2, &pt3) || checkline(&p4, &p1, &pt3, &pt1);
            }
        }
        else
        {
            rb_raise( rb_eTypeError, "ありえないエラーその２" );
        }

    } /* else of if( RDATA(o_data)->dfree == RDATA(d_data)->dfree ) */
}


/*--------------------------------------------------------------------
   配列同士の判定
 ---------------------------------------------------------------------*/
static VALUE Collision_check( VALUE obj, VALUE o, VALUE d )
{
    int i, j;
    struct CollisionData *data1;
    struct CollisionData *data2;
    int flag = 0;           /* 別グループなら0、同じグループなら1 */
    VALUE hitflag = Qfalse; /* 一つでも当たったらQtrue */

    if( TYPE(o) != T_ARRAY )
    {
        o = rb_ary_new3( 1, o );
    }
    if( TYPE(d) != T_ARRAY )
    {
        d = rb_ary_new3( 1, d );
    }

    if( o == d ) flag = 1;

    /* 攻撃側オブジェクトのループ */
    for( i = 0; i < RARRAY_LEN(o) - flag; i++ )
    {
        /* 配列からデータ取得と判定 */
        VALUE o_data = RARRAY_PTR(o)[i];
        if( TYPE( o_data ) != T_DATA )
        {
            continue;
        }
        Data_Get_Struct( o_data, struct CollisionData, data1 );
        if( RDATA(o_data)->dfree != (RUBY_DATA_FUNC)release_CollisionBox &&
            RDATA(o_data)->dfree != (RUBY_DATA_FUNC)release_CollisionCircle &&
            RDATA(o_data)->dfree != (RUBY_DATA_FUNC)release_CollisionTriangle &&
            RDATA(o_data)->dfree != (RUBY_DATA_FUNC)release_CollisionPoint )
        {
            continue;
//            rb_raise( rb_eTypeError, "wrong argument type %s (expected CollisionXxx)", rb_obj_classname( o_data ) );
        }


        /* 既に消えていたら何もしない */
        if( data1->delflag == 1 ) continue;

        /* 防御側オブジェクトのループ */
        for( j = (flag == 0 ? 0 : i + 1); j < RARRAY_LEN(d); j++ )
        {
            /* 配列からデータ取得と判定 */
            VALUE d_data = RARRAY_PTR(d)[j];
            if( TYPE( d_data ) != T_DATA )
            {
                continue;
            }
            Data_Get_Struct( d_data, struct CollisionData, data2 );
            if( RDATA(d_data)->dfree != (RUBY_DATA_FUNC)release_CollisionBox &&
                RDATA(d_data)->dfree != (RUBY_DATA_FUNC)release_CollisionCircle &&
                RDATA(d_data)->dfree != (RUBY_DATA_FUNC)release_CollisionTriangle &&
                RDATA(d_data)->dfree != (RUBY_DATA_FUNC)release_CollisionPoint )
            {
                continue;
//                rb_raise( rb_eTypeError, "wrong argument type %s (expected CollisionXxx)", rb_obj_classname( d_data ) );
            }


            /* 既に消えていたら何もしない */
            if( data2->delflag == 1 ) continue;

            /* 判定 */
            if( check( data1, data2, o_data, d_data ) )
            {
                hitflag = Qtrue;

                if( data2->self != Qnil && rb_respond_to( data2->self, id_hit ) )
                {
                    rb_funcall( data2->self, id_hit, 1, data1->self );
                }

                if( flag == 0 ) /* 別グループの場合 */
                {
                    /* 攻撃側が消えたら以降の防御側ループ省略 */
                    if( data1->self != Qnil && rb_respond_to( data1->self, id_shot ) )
                    {
                        rb_funcall( data1->self, id_shot, 1, data2->self );
                        if( data1->delflag == 1 )
                        {
                            break;
                        }
                    }
                }
                else            /* 同じグループの場合 */
                {
                    /* 攻撃側が消えたら以降の防御側ループ省略 */
                    if( data1->self != Qnil && rb_respond_to( data1->self, id_hit ) )
                    {
                        rb_funcall( data1->self, id_hit, 1, data2->self );
                        if( data1->delflag == 1 )
                        {
                            break;
                        }
                    }
                }
            }
        }
    }

    return hitflag;
}


/*********************************************************************
 * CollisionBoxクラス
 *
 * 当たり判定用の矩形範囲。
 *********************************************************************/

/*--------------------------------------------------------------------
   参照されなくなったときにGCから呼ばれる関数
 ---------------------------------------------------------------------*/
static void release_CollisionBox( struct CollisionBox *box )
{
    box->delflag = 0; /* 最適化でrelease関数がまとまるのを防止するためのコード */
    free( box );
}


/*--------------------------------------------------------------------
   CollisionBoxクラスのmark。GCのマーク時に呼ばれる。
 ---------------------------------------------------------------------*/
static void CollisionBox_mark( struct CollisionBox *box )
{
    rb_gc_mark( box->self );
}


/*--------------------------------------------------------------------
   CollisionBoxクラスのallocate。メモリを確保する為にinitialize前に呼ばれる。
 ---------------------------------------------------------------------*/
static VALUE CollisionBox_allocate( VALUE klass )
{
    VALUE obj;
    struct CollisionBox *box;

    /* CollisionBoxのメモリ取得＆オブジェクト生成 */
    box = malloc( sizeof(struct CollisionBox) );
    if( box == NULL ) rb_raise( eDXRubyExError, "メモリの取得に失敗しました - CollisionBox_allocate" );
    obj = Data_Wrap_Struct( klass, CollisionBox_mark, release_CollisionBox, box );

    box->self = Qnil;

    return obj;
}


/*--------------------------------------------------------------------
   CollisionBoxクラスのInitialize
 ---------------------------------------------------------------------*/
static VALUE CollisionBox_initialize( VALUE obj, VALUE vself, VALUE vx1, VALUE vy1, VALUE vx2, VALUE vy2 )
{
    struct CollisionBox *box;

    /* CollisionBoxオブジェクト設定 */
    Data_Get_Struct( obj, struct CollisionBox, box );

    box->x = 0;
    box->y = 0;
    box->x1 = NUM2INT( vx1 );
    box->y1 = NUM2INT( vy1 );
    box->x2 = NUM2INT( vx2 );
    box->y2 = NUM2INT( vy2 );
    box->delflag = 1;
    box->self = vself;

    return obj;
}


/*--------------------------------------------------------------------
   座標セット
 ---------------------------------------------------------------------*/
static VALUE CollisionBox_set( VALUE obj, VALUE vx, VALUE vy )
{
    struct CollisionBox *box;

    /* CollisionBoxオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionBox, box );

    box->x = NUM2INT( vx );
    box->y = NUM2INT( vy );
    box->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   判定範囲変更
 ---------------------------------------------------------------------*/
static VALUE CollisionBox_setrange( VALUE obj, VALUE vx1, VALUE vy1, VALUE vx2, VALUE vy2 )
{
    struct CollisionBox *box;

    /* CollisionBoxオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionBox, box );

    box->x1 = NUM2INT( vx1 );
    box->y1 = NUM2INT( vy1 );
    box->x2 = NUM2INT( vx2 );
    box->y2 = NUM2INT( vy2 );
    box->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   オブジェクトが消えた
 ---------------------------------------------------------------------*/
static VALUE CollisionBox_delete( VALUE obj )
{
    struct CollisionBox *box;

    /* CollisionBoxオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionBox, box );

    box->delflag = 1;

    return obj;
}


/*--------------------------------------------------------------------
   判定範囲取得
 ---------------------------------------------------------------------*/
static VALUE CollisionBox_getrange( VALUE obj )
{
    struct CollisionBox *box;

    /* CollisionBoxオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionBox, box );

    return rb_ary_new3( 4, INT2FIX( box->x + box->x1 ), INT2FIX( box->y + box->y1 ), INT2FIX( box->x + box->x2 ), INT2FIX( box->y + box->y2 ) );
}


/*--------------------------------------------------------------------
   通知先取得
 ---------------------------------------------------------------------*/
static VALUE CollisionBox_notifyobject( VALUE obj )
{
    struct CollisionBox *box;

    /* CollisionBoxオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionBox, box );

    return box->self;
}



/*********************************************************************
 * CollisionCircleクラス
 *
 * 当たり判定用の円範囲。
 *********************************************************************/

/*--------------------------------------------------------------------
   参照されなくなったときにGCから呼ばれる関数
 ---------------------------------------------------------------------*/
static void release_CollisionCircle( struct CollisionCircle *circle )
{
    circle->x = 0; /* 最適化でrelease関数がまとまるのを防止するためのコード */
    free( circle );
}


/*--------------------------------------------------------------------
   CollisionCircleクラスのmark。GCのマーク時に呼ばれる。
 ---------------------------------------------------------------------*/
static void CollisionCircle_mark( struct CollisionCircle *circle )
{
    rb_gc_mark( circle->self );
}


/*--------------------------------------------------------------------
   CollisionCircleクラスのallocate。メモリを確保する為にinitialize前に呼ばれる。
 ---------------------------------------------------------------------*/
static VALUE CollisionCircle_allocate( VALUE klass )
{
    VALUE obj;
    struct CollisionCircle *circle;

    /* CollisionCircleのメモリ取得＆オブジェクト生成 */
    circle = malloc( sizeof(struct CollisionCircle) );
    if( circle == NULL ) rb_raise( eDXRubyExError, "メモリの取得に失敗しました - CollisionCircle_allocate" );
    obj = Data_Wrap_Struct( klass, CollisionCircle_mark, release_CollisionCircle, circle );

    circle->self = Qnil;

    return obj;
}


/*--------------------------------------------------------------------
   CollisionCircleクラスのInitialize
 ---------------------------------------------------------------------*/
static VALUE CollisionCircle_initialize( VALUE obj, VALUE vself, VALUE vx1, VALUE vy1, VALUE vr )
{
    struct CollisionCircle *circle;

    /* CollisionCircleオブジェクト設定 */
    Data_Get_Struct( obj, struct CollisionCircle, circle );

    circle->x = 0;
    circle->y = 0;
    circle->x1 = NUM2INT( vx1 );
    circle->y1 = NUM2INT( vy1 );
    circle->r = NUM2INT( vr );
    circle->delflag = 1;
    circle->self = vself;

    return obj;
}


/*--------------------------------------------------------------------
   座標セット
 ---------------------------------------------------------------------*/
static VALUE CollisionCircle_set( VALUE obj, VALUE vx, VALUE vy )
{
    struct CollisionCircle *circle;

    /* CollisionCircleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionCircle, circle );

    circle->x = NUM2INT( vx );
    circle->y = NUM2INT( vy );
    circle->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   判定範囲変更
 ---------------------------------------------------------------------*/
static VALUE CollisionCircle_setrange( VALUE obj, VALUE vx1, VALUE vy1, VALUE vr )
{
    struct CollisionCircle *circle;

    /* CollisionCircleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionCircle, circle );

    circle->x1 = NUM2INT( vx1 );
    circle->y1 = NUM2INT( vy1 );
    circle->r = NUM2INT( vr );
    circle->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   オブジェクトが消えた
 ---------------------------------------------------------------------*/
static VALUE CollisionCircle_delete( VALUE obj )
{
    struct CollisionCircle *circle;

    /* CollisionCircleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionCircle, circle );

    circle->delflag = 1;

    return obj;
}

/*--------------------------------------------------------------------
   判定範囲取得
 ---------------------------------------------------------------------*/
static VALUE CollisionCircle_getrange( VALUE obj )
{
    struct CollisionCircle *circle;

    /* CollisionCircleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionCircle, circle );

    return rb_ary_new3( 3, INT2FIX( circle->x + circle->x1 ), INT2FIX( circle->y + circle->y1 ), INT2FIX( circle->r ) );
}


/*--------------------------------------------------------------------
   通知先取得
 ---------------------------------------------------------------------*/
static VALUE CollisionCircle_notifyobject( VALUE obj )
{
    struct CollisionCircle *circle;

    /* CollisionCircleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionCircle, circle );

    return circle->self;
}

/*********************************************************************
 * CollisionPointクラス
 *
 * 当たり判定用の矩形範囲。
 *********************************************************************/

/*--------------------------------------------------------------------
   参照されなくなったときにGCから呼ばれる関数
 ---------------------------------------------------------------------*/
static void release_CollisionPoint( struct CollisionPoint *point )
{
    point->y = 0; /* 最適化でrelease関数がまとまるのを防止するためのコード */
    free( point );
}


/*--------------------------------------------------------------------
   CollisionPointクラスのmark。GCのマーク時に呼ばれる。
 ---------------------------------------------------------------------*/
static void CollisionPoint_mark( struct CollisionPoint *point )
{
    rb_gc_mark( point->self );
}


/*--------------------------------------------------------------------
   CollisionPointクラスのallocate。メモリを確保する為にinitialize前に呼ばれる。
 ---------------------------------------------------------------------*/
static VALUE CollisionPoint_allocate( VALUE klass )
{
    VALUE obj;
    struct CollisionPoint *point;

    /* CollisionPointのメモリ取得＆オブジェクト生成 */
    point = malloc( sizeof(struct CollisionPoint) );
    if( point == NULL ) rb_raise( eDXRubyExError, "メモリの取得に失敗しました - CollisionPoint_allocate" );
    obj = Data_Wrap_Struct( klass, CollisionPoint_mark, release_CollisionPoint, point );

    point->self = Qnil;

    return obj;
}


/*--------------------------------------------------------------------
   CollisionPointクラスのInitialize
 ---------------------------------------------------------------------*/
static VALUE CollisionPoint_initialize( VALUE obj, VALUE vself )
{
    struct CollisionPoint *point;

    /* CollisionPointオブジェクト設定 */
    Data_Get_Struct( obj, struct CollisionPoint, point );

    point->delflag = 1;
    point->self = vself;

    return obj;
}


/*--------------------------------------------------------------------
   座標セット
 ---------------------------------------------------------------------*/
static VALUE CollisionPoint_set( VALUE obj, VALUE vx, VALUE vy )
{
    struct CollisionPoint *point;

    /* CollisionPointオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionPoint, point );

    point->x = NUM2INT( vx );
    point->y = NUM2INT( vy );
    point->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   オブジェクトが消えた
 ---------------------------------------------------------------------*/
static VALUE CollisionPoint_delete( VALUE obj )
{
    struct CollisionPoint *point;

    /* CollisionPointオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionPoint, point );

    point->delflag = 1;

    return obj;
}


/*--------------------------------------------------------------------
   判定範囲取得
 ---------------------------------------------------------------------*/
static VALUE CollisionPoint_getrange( VALUE obj )
{
    struct CollisionPoint *point;

    /* CollisionPointオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionPoint, point );

    return rb_ary_new3( 2, INT2FIX( point->x ), INT2FIX( point->y ) );
}


/*--------------------------------------------------------------------
   通知先取得
 ---------------------------------------------------------------------*/
static VALUE CollisionPoint_notifyobject( VALUE obj )
{
    struct CollisionPoint *point;

    /* CollisionPointオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionPoint, point );

    return point->self;
}

/*********************************************************************
 * CollisionTriangleクラス
 *
 * 当たり判定用の矩形範囲。
 *********************************************************************/

/*--------------------------------------------------------------------
   参照されなくなったときにGCから呼ばれる関数
 ---------------------------------------------------------------------*/
static void release_CollisionTriangle( struct CollisionTriangle *tri )
{
    tri->x3 = 0; /* 最適化でrelease関数がまとまるのを防止するためのコード */
    free( tri );
}


/*--------------------------------------------------------------------
   CollisionTriangleクラスのmark。GCのマーク時に呼ばれる。
 ---------------------------------------------------------------------*/
static void CollisionTriangle_mark( struct CollisionTriangle *tri )
{
    rb_gc_mark( tri->self );
}


/*--------------------------------------------------------------------
   CollisionTriangleクラスのallocate。メモリを確保する為にinitialize前に呼ばれる。
 ---------------------------------------------------------------------*/
static VALUE CollisionTriangle_allocate( VALUE klass )
{
    VALUE obj;
    struct CollisionTriangle *tri;

    /* CollisionTriangleのメモリ取得＆オブジェクト生成 */
    tri = malloc( sizeof(struct CollisionTriangle) );
    if( tri == NULL ) rb_raise( eDXRubyExError, "メモリの取得に失敗しました - CollisionTriangle_allocate" );
    obj = Data_Wrap_Struct( klass, CollisionTriangle_mark, release_CollisionTriangle, tri );

    tri->self = Qnil;

    return obj;
}


/*--------------------------------------------------------------------
   CollisionTriangleクラスのInitialize
 ---------------------------------------------------------------------*/
static VALUE CollisionTriangle_initialize( VALUE obj, VALUE vself, VALUE vx1, VALUE vy1, VALUE vx2, VALUE vy2, VALUE vx3, VALUE vy3 )
{
    struct CollisionTriangle *tri;

    /* CollisionTriangleオブジェクト設定 */
    Data_Get_Struct( obj, struct CollisionTriangle, tri );

    tri->x = 0;
    tri->y = 0;
    tri->x1 = NUM2INT( vx1 );
    tri->y1 = NUM2INT( vy1 );
    tri->x2 = NUM2INT( vx2 );
    tri->y2 = NUM2INT( vy2 );
    tri->x3 = NUM2INT( vx3 );
    tri->y3 = NUM2INT( vy3 );
    tri->delflag = 0;
    tri->self = vself;

    return obj;
}


/*--------------------------------------------------------------------
   座標セット
 ---------------------------------------------------------------------*/
static VALUE CollisionTriangle_set( VALUE obj, VALUE vx, VALUE vy )
{
    struct CollisionTriangle *tri;

    /* CollisionTriangleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionTriangle, tri );

    tri->x = NUM2INT( vx );
    tri->y = NUM2INT( vy );
    tri->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   判定範囲変更
 ---------------------------------------------------------------------*/
static VALUE CollisionTriangle_setrange( VALUE obj, VALUE vx1, VALUE vy1, VALUE vx2, VALUE vy2, VALUE vx3, VALUE vy3 )
{
    struct CollisionTriangle *tri;

    /* CollisionTriangleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionTriangle, tri );

    tri->x1 = NUM2INT( vx1 );
    tri->y1 = NUM2INT( vy1 );
    tri->x2 = NUM2INT( vx2 );
    tri->y2 = NUM2INT( vy2 );
    tri->x3 = NUM2INT( vx3 );
    tri->y3 = NUM2INT( vy3 );
    tri->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   オブジェクトが消えた
 ---------------------------------------------------------------------*/
static VALUE CollisionTriangle_delete( VALUE obj )
{
    struct CollisionTriangle *tri;

    /* CollisionTriangleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionTriangle, tri );

    tri->delflag = 1;

    return obj;
}


/*--------------------------------------------------------------------
   判定範囲取得
 ---------------------------------------------------------------------*/
static VALUE CollisionTriangle_getrange( VALUE obj )
{
    struct CollisionTriangle *tri;

    /* CollisionTriangleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionTriangle, tri );

    return rb_ary_new3( 6, INT2FIX( tri->x + tri->x1 ), INT2FIX( tri->y + tri->y1 ), INT2FIX( tri->x + tri->x2 ),
                           INT2FIX( tri->y + tri->y2 ), INT2FIX( tri->x + tri->x3 ), INT2FIX( tri->y + tri->y3 ) );
}


/*--------------------------------------------------------------------
   通知先取得
 ---------------------------------------------------------------------*/
static VALUE CollisionTriangle_notifyobject( VALUE obj )
{
    struct CollisionTriangle *tri;

    /* CollisionTriangleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionTriangle, tri );

    return tri->self;
}

/*--------------------------------------------------------------------
   高速each
 ---------------------------------------------------------------------*/
static VALUE ArrayExtension_hseach( VALUE obj, VALUE symbol )
{
    ID id;
    int i;

    id = rb_to_id( symbol );

    for( i = 0; i < RARRAY_LEN(obj); i++ )
    {
        rb_funcall( RARRAY_PTR(obj)[i], id, 0 );
    }

    return obj;
}


/*--------------------------------------------------------------------
   高速delete_if
 ---------------------------------------------------------------------*/
static VALUE ArrayExtension_hsdeleteif( VALUE obj, VALUE symbol )
{
    ID id;
    int i, j;

    id = rb_to_id( symbol );

    for( i = 0, j = 0; i < RARRAY_LEN(obj); i++ )
    {
        VALUE temp = rb_funcall( RARRAY_PTR(obj)[i], id, 0 );
        if( temp != Qfalse && temp != Qnil )
        {
            RARRAY_PTR(obj)[i] = Qnil;
        }
    }

    rb_funcall( obj, rb_intern("compact!"), 0 );

    return obj;
}



/*
***************************************************************
*
*         Global functions
*
***************************************************************/

void Init_dxrubyex()
{
    HRESULT hr;

    /* DxrubyExtensionモジュール登録 */
    mDXRubyExtension = rb_define_module( "DXRubyExtension" );

    /* Collisionモジュール登録 */
    mCollision = rb_define_module_under( mDXRubyExtension, "Collision" );

    /* Collisionモジュールにメソッド登録 */
    rb_define_singleton_method( mCollision, "check"   , Collision_check, 2 );

    /* CollisionBoxクラス定義 */
    cCollisionBox = rb_define_class_under( mDXRubyExtension, "CollisionBox", rb_cObject );

    /* CollisionBoxクラスにメソッド登録*/
    rb_define_method( cCollisionBox, "initialize", CollisionBox_initialize, 5 );
    rb_define_method( cCollisionBox, "set"       , CollisionBox_set       , 2 );
    rb_define_method( cCollisionBox, "setRange"  , CollisionBox_setrange  , 4 );
    rb_define_method( cCollisionBox, "delete"    , CollisionBox_delete    , 0 );
    rb_define_method( cCollisionBox, "getHitRange", CollisionBox_getrange  , 0 );
    rb_define_method( cCollisionBox, "notifyObject", CollisionBox_notifyobject  , 0 );

    /* CollisionBoxオブジェクトを生成した時にinitializeの前に呼ばれるメモリ割り当て関数登録 */
    rb_define_alloc_func( cCollisionBox, CollisionBox_allocate );


    /* CollisionCircleクラス定義 */
    cCollisionCircle = rb_define_class_under( mDXRubyExtension, "CollisionCircle", rb_cObject );

    /* CollisionCircleクラスにメソッド登録*/
    rb_define_method( cCollisionCircle, "initialize", CollisionCircle_initialize, 4 );
    rb_define_method( cCollisionCircle, "set"       , CollisionCircle_set       , 2 );
    rb_define_method( cCollisionCircle, "setRange"  , CollisionCircle_setrange  , 3 );
    rb_define_method( cCollisionCircle, "delete"    , CollisionCircle_delete    , 0 );
    rb_define_method( cCollisionCircle, "getHitRange", CollisionCircle_getrange  , 0 );
    rb_define_method( cCollisionCircle, "notifyObject", CollisionCircle_notifyobject  , 0 );

    /* CollisionCircleオブジェクトを生成した時にinitializeの前に呼ばれるメモリ割り当て関数登録 */
    rb_define_alloc_func( cCollisionCircle, CollisionCircle_allocate );


    /* CollisionPointクラス定義 */
    cCollisionPoint = rb_define_class_under( mDXRubyExtension, "CollisionPoint", rb_cObject );

    /* CollisionPointクラスにメソッド登録*/
    rb_define_method( cCollisionPoint, "initialize", CollisionPoint_initialize, 1 );
    rb_define_method( cCollisionPoint, "set"       , CollisionPoint_set       , 2 );
    rb_define_method( cCollisionPoint, "delete"    , CollisionPoint_delete    , 0 );
    rb_define_method( cCollisionPoint, "getHitRange", CollisionPoint_getrange , 0 );
    rb_define_method( cCollisionPoint, "notifyObject", CollisionPoint_notifyobject  , 0 );

    /* CollisionPointオブジェクトを生成した時にinitializeの前に呼ばれるメモリ割り当て関数登録 */
    rb_define_alloc_func( cCollisionPoint, CollisionPoint_allocate );


    /* CollisionTriangleクラス定義 */
    cCollisionTriangle = rb_define_class_under( mDXRubyExtension, "CollisionTriangle", rb_cObject );

    /* CollisionTriangleクラスにメソッド登録*/
    rb_define_method( cCollisionTriangle, "initialize", CollisionTriangle_initialize, 7 );
    rb_define_method( cCollisionTriangle, "set"       , CollisionTriangle_set       , 2 );
    rb_define_method( cCollisionTriangle, "setRange"  , CollisionTriangle_setrange  , 6 );
    rb_define_method( cCollisionTriangle, "delete"    , CollisionTriangle_delete    , 0 );
    rb_define_method( cCollisionTriangle, "getHitRange", CollisionTriangle_getrange  , 0 );
    rb_define_method( cCollisionTriangle, "notifyObject", CollisionTriangle_notifyobject  , 0 );

    /* CollisionTriangleオブジェクトを生成した時にinitializeの前に呼ばれるメモリ割り当て関数登録 */
    rb_define_alloc_func( cCollisionTriangle, CollisionTriangle_allocate );


    /* ArrayExtensionモジュール登録 */
    mArrayExtension = rb_define_module_under( mDXRubyExtension, "ArrayExtension" );

    /* ArrayExtensionモジュールにメソッド登録 */
    rb_define_method( mArrayExtension, "hs_each"      , ArrayExtension_hseach, 1 );
    rb_define_method( mArrayExtension, "hs_delete_if" , ArrayExtension_hsdeleteif, 1 );

    /* 例外定義 */
    eDXRubyExError = rb_define_class_under( mDXRubyExtension, "DXRubyExtensionError", rb_eRuntimeError );

    /* 定数登録 */
    rb_define_const( mDXRubyExtension, "VERSION", rb_str_new2( DXRUBYEX_VERSION ) );

    {
        VALUE temp;
        temp = rb_eval_string( "$dxrubyex_no_include" );
        if( temp == Qfalse || temp == Qnil )
        {
            rb_include_module( rb_cObject, mDXRubyExtension );
        }
    }

    id_hit = rb_intern("hit");
    id_shot = rb_intern("shot");
}


/***********************
 * 外部インターフェース
 ***********************/

/*--------------------------------------------------------------------
   座標セット
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionBox_set( VALUE obj, int x, int y )
{
    struct CollisionBox *box;

    /* CollisionBoxオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionBox, box );

    box->x = x;
    box->y = y;
    box->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   判定範囲変更
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionBox_setrange( VALUE obj, int x1, int y1, int x2, int y2 )
{
    struct CollisionBox *box;

    /* CollisionBoxオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionBox, box );

    box->x1 = x1;
    box->y1 = y1;
    box->x2 = x2;
    box->y2 = y2;
    box->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   オブジェクトが消えた
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionBox_delete( VALUE obj )
{
    struct CollisionBox *box;

    /* CollisionBoxオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionBox, box );

    box->delflag = 1;

    return obj;
}


/*--------------------------------------------------------------------
   座標セット
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionCircle_set( VALUE obj, int x, int y )
{
    struct CollisionCircle *circle;

    /* CollisionCircleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionCircle, circle );

    circle->x = x;
    circle->y = y;
    circle->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   判定範囲変更
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionCircle_setrange( VALUE obj, int x1, int y1, int r )
{
    struct CollisionCircle *circle;

    /* CollisionCircleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionCircle, circle );

    circle->x1 = x1;
    circle->y1 = y1;
    circle->r = r;
    circle->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   オブジェクトが消えた
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionCircle_delete( VALUE obj )
{
    struct CollisionCircle *circle;

    /* CollisionCircleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionCircle, circle );

    circle->delflag = 1;

    return obj;
}

/*--------------------------------------------------------------------
   座標セット
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionPoint_set( VALUE obj, int x, int y )
{
    struct CollisionPoint *point;

    /* CollisionPointオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionPoint, point );

    point->x = x;
    point->y = y;
    point->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   オブジェクトが消えた
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionPoint_delete( VALUE obj )
{
    struct CollisionPoint *point;

    /* CollisionPointオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionPoint, point );

    point->delflag = 1;

    return obj;
}


/*--------------------------------------------------------------------
   座標セット
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionTriangle_set( VALUE obj, int x, int y )
{
    struct CollisionTriangle *tri;

    /* CollisionTriangleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionTriangle, tri );

    tri->x = x;
    tri->y = y;
    tri->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   判定範囲変更
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionTriangle_setrange( VALUE obj, int x1, int y1, int x2, int y2, int x3, int y3 )
{
    struct CollisionTriangle *tri;

    /* CollisionTriangleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionTriangle, tri );

    tri->x1 = x1;
    tri->y1 = y1;
    tri->x2 = x2;
    tri->y2 = y2;
    tri->x3 = x3;
    tri->y3 = y3;
    tri->delflag = 0;

    return obj;
}


/*--------------------------------------------------------------------
   オブジェクトが消えた
 ---------------------------------------------------------------------*/
VALUE DXRubyEx_CollisionTriangle_delete( VALUE obj )
{
    struct CollisionTriangle *tri;

    /* CollisionTriangleオブジェクト取得 */
    Data_Get_Struct( obj, struct CollisionTriangle, tri );

    tri->delflag = 1;

    return obj;
}


