X operations(XOPS)に非常に近いFPSゲームを制作・リメイクし、成果物をオープンソースとして公開することを目的としたプロジェクトです。
リビジョン | 348 (tree) |
---|---|
日時 | 2023-02-04 02:08:34 |
作者 | ![]() |
人とマップの当たり判定を修正、一部ベクトル計算関数の仕様を変更
@@ -867,15 +867,17 @@ | ||
867 | 867 | if( BlockDataIF == NULL ){ return false; } |
868 | 868 | if( (id < 0)||(BlockDataIF->GetTotaldatas() <= id) ){ return false; } |
869 | 869 | if( (face < 0)||(6 < face) ){ return false; } |
870 | + if( out_angle == NULL ){ return false; } | |
870 | 871 | |
872 | + if( (in_vx == 0.0f)&&(in_vy == 0.0f)&&(in_vz == 0.0f) ){ return false; } | |
873 | + | |
871 | 874 | blockdata bdata; |
872 | 875 | BlockDataIF->Getdata(&bdata, id); |
873 | 876 | |
874 | - float maxDist = sqrtf(in_vx*in_vx + in_vy*in_vy + in_vz*in_vz); | |
875 | - if( maxDist == 0.0f ){ return false; } | |
877 | + VectorNormalization(&in_vx, &in_vy, &in_vz); | |
876 | 878 | |
877 | 879 | //内積 |
878 | - float Dot = in_vx/maxDist * bdata.material[face].vx + in_vy/maxDist * bdata.material[face].vy + in_vz/maxDist * bdata.material[face].vz; | |
880 | + float Dot = in_vx * bdata.material[face].vx + in_vy * bdata.material[face].vy + in_vz * bdata.material[face].vz; | |
879 | 881 | |
880 | 882 | //角度を求める |
881 | 883 | *out_angle = asinf(Dot) * -1; |
@@ -883,14 +885,15 @@ | ||
883 | 885 | return true; |
884 | 886 | } |
885 | 887 | |
886 | -//! @brief ブロックに沿って移動するベクトルと進入角度を求める | |
888 | +//! @brief ブロックに対するベクトルのなす角を求める | |
887 | 889 | //! @return 成功:true 失敗:false |
888 | -//! @attention 向き:0.0〜PI/2(0.0度〜90.0度) | |
889 | -bool Collision::ScratchAngleVector(int id, int face, float in_vx, float in_vy, float in_vz, float *out_vx, float *out_vy, float *out_vz, float *out_angle) | |
890 | +//! @attention ベクトルのなす角:0.0〜PI(0度〜180度) | |
891 | +bool Collision::AngleVector2(int id, int face, float in_vx, float in_vy, float in_vz, float *out_angle) | |
890 | 892 | { |
891 | 893 | if( BlockDataIF == NULL ){ return false; } |
892 | 894 | if( (id < 0)||(BlockDataIF->GetTotaldatas() <= id) ){ return false; } |
893 | 895 | if( (face < 0)||(6 < face) ){ return false; } |
896 | + if( out_angle == NULL ){ return false; } | |
894 | 897 | |
895 | 898 | if( (in_vx == 0.0f)&&(in_vy == 0.0f)&&(in_vz == 0.0f) ){ return false; } |
896 | 899 |
@@ -903,14 +906,9 @@ | ||
903 | 906 | //裏向きなら除外 |
904 | 907 | if( Dot >= 0.0f ){ return false; } |
905 | 908 | |
906 | - if( out_vx != NULL ){ *out_vx = in_vx - Dot * bdata.material[face].vx; } | |
907 | - if( out_vy != NULL ){ *out_vy = in_vy - Dot * bdata.material[face].vy; } | |
908 | - if( out_vz != NULL ){ *out_vz = in_vz - Dot * bdata.material[face].vz; } | |
909 | + //なす角を求める | |
910 | + *out_angle = acosf(Dot); | |
909 | 911 | |
910 | - //角度を求める | |
911 | - if( out_angle != NULL ){ *out_angle = asinf(Dot) * -1; } | |
912 | - //if( out_angle != NULL ){ *out_angle = Dot * -1; } | |
913 | - | |
914 | 912 | return true; |
915 | 913 | } |
916 | 914 |
@@ -87,7 +87,7 @@ | ||
87 | 87 | void ScratchVector(int id, int face, float in_vx, float in_vy, float in_vz, float *out_vx, float *out_vy, float *out_vz); |
88 | 88 | void ReflectVector(int id, int face, float in_vx, float in_vy, float in_vz, float *out_vx, float *out_vy, float *out_vz); |
89 | 89 | bool AngleVector(int id, int face, float in_vx, float in_vy, float in_vz, float *out_angle); |
90 | - bool ScratchAngleVector(int id, int face, float in_vx, float in_vy, float in_vz, float *out_vx, float *out_vy, float *out_vz, float *out_angle); | |
90 | + bool AngleVector2(int id, int face, float in_vx, float in_vy, float in_vz, float *out_angle); | |
91 | 91 | }; |
92 | 92 | |
93 | 93 | void GetAABBRay(float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float maxDist, float *min_x, float *min_y, float *min_z, float *max_x, float *max_y, float *max_z); |
@@ -1538,6 +1538,8 @@ | ||
1538 | 1538 | dist_x = pos_x - pos_x2; |
1539 | 1539 | dist_y = pos_y - pos_y2; |
1540 | 1540 | dist_z = pos_z - pos_z2; |
1541 | + speed = sqrtf(dist_x*dist_x + dist_z*dist_z); | |
1542 | + VectorNormalization(&dist_x, &dist_y, &dist_z); | |
1541 | 1543 | |
1542 | 1544 | int bs = inblockdata->GetTotaldatas(); |
1543 | 1545 |
@@ -1554,7 +1556,6 @@ | ||
1554 | 1556 | CheckBlockID[i] = CollD->CheckBlockAABB(i, box_min_x, box_min_y, box_min_z, box_max_x, box_max_y, box_max_z); |
1555 | 1557 | } |
1556 | 1558 | |
1557 | - speed = sqrtf(dist_x*dist_x + dist_z*dist_z); | |
1558 | 1559 | if( (speed != 0.0f)||(move_y != 0.0f) ){ |
1559 | 1560 | |
1560 | 1561 | //頭部で当たり判定 |
@@ -1595,35 +1596,40 @@ | ||
1595 | 1596 | //斜面を登る |
1596 | 1597 | if( (fabsf(move_x) > 0.2f)||(fabsf(move_z) > 0.2f) ){ |
1597 | 1598 | if( move_y_upper == 0 ){ |
1599 | + bool flag = false; | |
1598 | 1600 | for(int i=0; i<bs; i++){ |
1599 | 1601 | if( CheckBlockID[i] == true ){ |
1602 | + //足のつま先のみブロックに埋まっていれば | |
1600 | 1603 | if( |
1601 | 1604 | (CollD->CheckBlockInside(i, pos_x + dist_x*2.0f, pos_y, pos_z + dist_z*2.0f, true, NULL) == true)&& |
1602 | 1605 | (CollD->CheckBlockInside(i, pos_x + dist_x*2.0f, pos_y + HUMAN_MAPCOLLISION_CLIMBHEIGHT, pos_z + dist_z*2.0f, true, NULL) == false) |
1603 | 1606 | ){ |
1607 | + flag = true; | |
1608 | + | |
1604 | 1609 | int face; |
1605 | 1610 | blockdata bdata; |
1606 | - bool flag = false; | |
1607 | 1611 | |
1608 | 1612 | //足元の面の角度を取得 |
1609 | 1613 | // ※足元にブロックがあることは確定なので、DummyRayは必要ない・・・はず。 |
1610 | - if( CollD->CheckBlockIntersectRay(i, pos_x, pos_y + HUMAN_MAPCOLLISION_CLIMBADDY, pos_z, 0.0f, -1.0f, 0.0f, &face, &Dist, 1.2f + HUMAN_MAPCOLLISION_CLIMBADDY) == true ){ | |
1614 | + if( CollD->CheckBlockIntersectRay(i, pos_x, pos_y, pos_z, 0.0f, -1.0f, 0.0f, &face, &Dist, 1.2f) == true ){ | |
1611 | 1615 | |
1612 | 1616 | inblockdata->Getdata(&bdata, i); |
1613 | 1617 | |
1614 | 1618 | //斜面に立っているならば、上昇無効 |
1615 | 1619 | if( acosf(bdata.material[face].vy) > HUMAN_MAPCOLLISION_SLOPEANGLE ){ |
1616 | - flag = true; | |
1620 | + flag = false; | |
1621 | + break; | |
1617 | 1622 | } |
1618 | 1623 | } |
1619 | - | |
1620 | - if( flag == false ){ | |
1621 | - pos_y += HUMAN_MAPCOLLISION_CLIMBADDY; | |
1622 | - move_y *= 0.2f; | |
1623 | - } | |
1624 | 1624 | } |
1625 | 1625 | } |
1626 | 1626 | } |
1627 | + | |
1628 | + //上昇する(登る) | |
1629 | + if( flag == true ){ | |
1630 | + pos_y += HUMAN_MAPCOLLISION_CLIMBADDY; | |
1631 | + move_y *= 0.2f; | |
1632 | + } | |
1627 | 1633 | } |
1628 | 1634 | } |
1629 | 1635 |
@@ -1657,7 +1663,7 @@ | ||
1657 | 1663 | move_y_flag = false; |
1658 | 1664 | FallFlag = false; |
1659 | 1665 | for(int ycnt=0; ycnt<3; ycnt++){ |
1660 | - int cnt = 0; | |
1666 | + int cnt; | |
1661 | 1667 | float ang = atan2f(move_z, move_x); |
1662 | 1668 | float x, y, z; |
1663 | 1669 |
@@ -1665,11 +1671,10 @@ | ||
1665 | 1671 | pos_y += move_y*0.33f; |
1666 | 1672 | |
1667 | 1673 | if( player == true ){ |
1668 | - cnt = 0; | |
1669 | - | |
1670 | 1674 | y = pos_y + HUMAN_MAPCOLLISION_GROUND_HEIGHT; |
1671 | 1675 | |
1672 | 1676 | //4方向判定 No.1 |
1677 | + cnt = 0; | |
1673 | 1678 | x = pos_x + cosf(ang)*HUMAN_MAPCOLLISION_GROUND_R1; |
1674 | 1679 | z = pos_z + sinf(ang)*HUMAN_MAPCOLLISION_GROUND_R1; |
1675 | 1680 | for(int i=0; i<bs; i++){ |
@@ -1701,6 +1706,7 @@ | ||
1701 | 1706 | if( cnt == 4 ){ FallFlag = true; break; } |
1702 | 1707 | |
1703 | 1708 | //4方向判定 No.2 |
1709 | + cnt = 0; | |
1704 | 1710 | x = pos_x + cosf(ang)*HUMAN_MAPCOLLISION_GROUND_R2; |
1705 | 1711 | z = pos_z + sinf(ang)*HUMAN_MAPCOLLISION_GROUND_R2; |
1706 | 1712 | for(int i=0; i<bs; i++){ |
@@ -1911,11 +1917,12 @@ | ||
1911 | 1917 | if( CollD->CheckBlockAABB(blockid, rmin_x, rmin_y, rmin_z, rmax_x, rmax_y, rmax_z) == false ){ return false; } |
1912 | 1918 | if( CollD->CheckBlockIntersectRay(blockid, in_vx - vx, in_vy - vy, in_vz - vz, vx, vy, vz, &face, &temp, dist) == false ){ return false; } |
1913 | 1919 | |
1914 | - //ブロックに沿って移動するベクトルと進入角度を求める | |
1915 | - if( CollD->ScratchAngleVector(blockid, face, vx, vy, vz, &vx, &vy, &vz, &face_angle) == false ){ return false; } | |
1920 | + //ブロックの面に対するベクトルのなす角を求める | |
1921 | + if( CollD->AngleVector2(blockid, face, vx, vy, vz, &face_angle) == false ){ return false; } | |
1916 | 1922 | |
1917 | 1923 | //角度の割合算出 |
1918 | - if( face_angle != 0.0f ){ face_angle_per = 1.0f - face_angle / ((float)M_PI); } | |
1924 | + //if( face_angle != 0.0f ){ face_angle_per = 1.0f - face_angle / ((float)M_PI); } | |
1925 | + if( face_angle != 0.0f ){ face_angle_per = ((float)M_PI) / face_angle - 1.0f; } | |
1919 | 1926 | else{ face_angle_per = 0.0f; } |
1920 | 1927 | |
1921 | 1928 | //ブロック面の法線ベクトル取得 |
@@ -1925,6 +1932,26 @@ | ||
1925 | 1932 | face_vy = bdata.material[face].vy; |
1926 | 1933 | face_vz = bdata.material[face].vz; |
1927 | 1934 | |
1935 | + //移動ベクトル+法線ベクトルを算出 | |
1936 | + float vx2, vy2, vz2; | |
1937 | + vx2 = vx + face_vx; | |
1938 | + vy2 = vy + face_vy; | |
1939 | + vz2 = vz + face_vz; | |
1940 | + VectorNormalization(&vx2, &vy2, &vz2); | |
1941 | + | |
1942 | + //なす角に応じて移動ベクトルを算出 | |
1943 | + vx = vx2 * (1.0f-face_angle_per) + vx * face_angle_per; | |
1944 | + vy = vy2 * (1.0f-face_angle_per) + vy * face_angle_per; | |
1945 | + vz = vz2 * (1.0f-face_angle_per) + vz * face_angle_per; | |
1946 | + VectorNormalization(&vx, &vy, &vz); | |
1947 | + | |
1948 | + //水平方向に移動しないならば、法線ベクトルを用いる | |
1949 | + if( (vx == 0.0f)&&(vz == 0.0f) ){ | |
1950 | + vx = bdata.material[face].vx; | |
1951 | + vy = bdata.material[face].vy; | |
1952 | + vz = bdata.material[face].vz; | |
1953 | + } | |
1954 | + | |
1928 | 1955 | //最終的な位置を計算 |
1929 | 1956 | temp = face_angle_per * dist; |
1930 | 1957 | *px = vx*temp + px_old; |
@@ -1934,9 +1961,9 @@ | ||
1934 | 1961 | //最終的な位置がブロックの内側ならば、移動無効 |
1935 | 1962 | //if( CollD->CheckALLBlockInside(*px, *py, *pz) == true ){ |
1936 | 1963 | if( CollD->CheckBlockInside(blockid, *px, *py, *pz, true, NULL) == true ){ |
1937 | - *px = px2; | |
1938 | - *py = py2; | |
1939 | - *pz = pz2; | |
1964 | + *px = px_old; | |
1965 | + *py = py_old; | |
1966 | + *pz = pz_old; | |
1940 | 1967 | } |
1941 | 1968 | |
1942 | 1969 | //座標補正 |