• R/O
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

X operations(XOPS)に非常に近いFPSゲームを制作・リメイクし、成果物をオープンソースとして公開することを目的としたプロジェクトです。


Commit MetaInfo

Revision262 (tree)
Time2021-02-21 03:02:11
Authorxops-mikan

Log Message

人とマップの当たり判定を一新、一部ベクトル計算を関数化、標準ミッションで追加の当たり判定フラグが反映されないバグの修正。

Change Summary

Incremental Difference

--- trunk/collision.cpp (revision 261)
+++ trunk/collision.cpp (revision 262)
@@ -876,6 +876,37 @@
876876 return true;
877877 }
878878
879+//! @brief ブロックに沿って移動するベクトルと進入角度を求める
880+//! @return 成功:true 失敗:false
881+//! @attention 向き:0.0〜PI/2(0.0度〜90.0度)
882+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)
883+{
884+ if( blockdata == NULL ){ return false; }
885+ if( (id < 0)||(blockdata->GetTotaldatas() <= id) ){ return false; }
886+ if( (face < 0)||(6 < face) ){ return false; }
887+
888+ if( (in_vx == 0.0f)&&(in_vy == 0.0f)&&(in_vz == 0.0f) ){ return false; }
889+
890+ struct blockdata bdata;
891+ blockdata->Getdata(&bdata, id);
892+
893+ //内積
894+ float Dot = in_vx * bdata.material[face].vx + in_vy * bdata.material[face].vy + in_vz * bdata.material[face].vz;
895+
896+ //裏向きなら除外
897+ if( Dot >= 0.0f ){ return false; }
898+
899+ if( out_vx != NULL ){ *out_vx = in_vx - Dot * bdata.material[face].vx; }
900+ if( out_vy != NULL ){ *out_vy = in_vy - Dot * bdata.material[face].vy; }
901+ if( out_vz != NULL ){ *out_vz = in_vz - Dot * bdata.material[face].vz; }
902+
903+ //角度を求める
904+ if( out_angle != NULL ){ *out_angle = asin(Dot) * -1; }
905+ //if( out_angle != NULL ){ *out_angle = Dot * -1; }
906+
907+ return true;
908+}
909+
879910 //! @brief AABBによる当たり判定
880911 //! @param box1_min_x 物体Aの最少 X座標
881912 //! @param box1_min_y 物体Aの最少 Y座標
@@ -1119,12 +1150,7 @@
11191150 }
11201151
11211152 //ベクトルを正規化
1122- float r = sqrt(RayDir_x*RayDir_x + RayDir_y*RayDir_y + RayDir_z*RayDir_z);
1123- if( r > 1.0f ){
1124- RayDir_x /= r;
1125- RayDir_y /= r;
1126- RayDir_z /= r;
1127- }
1153+ VectorNormalization(&RayDir_x, &RayDir_y, &RayDir_z);
11281154
11291155 //各座標を配列に格納
11301156 float box_min[] = {box_min_x, box_min_y, box_min_z};
@@ -1596,4 +1622,20 @@
15961622 if( out_dist2 != NULL ){ *out_dist2 = dist2; }
15971623
15981624 return true;
1625+}
1626+
1627+//! @brief ベクトル正規化
1628+//! @param vx vxのポインタ
1629+//! @param vy vyのポインタ
1630+//! @param vz vzのポインタ
1631+//! @return 正規化前のベクトルの長さ
1632+float VectorNormalization(float *vx, float *vy, float *vz)
1633+{
1634+ float r = sqrt((*vx) * (*vx) + (*vy) * (*vy) + (*vz) * (*vz));
1635+ if( r > 0.0f ){
1636+ *vx /= r;
1637+ *vy /= r;
1638+ *vz /= r;
1639+ }
1640+ return r;
15991641 }
\ No newline at end of file
--- trunk/collision.h (revision 261)
+++ trunk/collision.h (revision 262)
@@ -84,6 +84,7 @@
8484 void ScratchVector(int id, int face, float in_vx, float in_vy, float in_vz, float *out_vx, float *out_vy, float *out_vz);
8585 void ReflectVector(int id, int face, float in_vx, float in_vy, float in_vz, float *out_vx, float *out_vy, float *out_vz);
8686 bool AngleVector(int id, int face, float in_vx, float in_vy, float in_vz, float *out_angle);
87+ 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);
8788 };
8889
8990 bool CollideBoxAABB(float box1_min_x, float box1_min_y, float box1_min_z, float box1_max_x, float box1_max_y, float box1_max_z, float box2_min_x, float box2_min_y, float box2_min_z, float box2_max_x, float box2_max_y, float box2_max_z);
@@ -99,4 +100,6 @@
99100
100101 bool CheckTargetAngle(float pos_x, float pos_y, float pos_z, float rx, float ry, float target_x, float target_y, float target_z, float checkdist, float *out_rx, float *out_ry, float *out_dist2);
101102
103+float VectorNormalization(float *vx, float *vy, float *vz);
104+
102105 #endif
\ No newline at end of file
--- trunk/object.cpp (revision 261)
+++ trunk/object.cpp (revision 262)
@@ -169,6 +169,7 @@
169169 move_y = 0.0f;
170170 move_z = 0.0f;
171171 move_y_flag = false;
172+ move_y_upper = 0;
172173 rotation_x = rx;
173174 id_parameter = id_param;
174175 upmodel_size = 9.4f;
@@ -250,6 +251,7 @@
250251 move_y = 0.0f;
251252 move_z = 0.0f;
252253 move_y_flag = false;
254+ move_y_upper = 0;
253255 rotation_y = 0.0f;
254256 armrotation_y = DegreeToRadian(-30);
255257
@@ -920,21 +922,10 @@
920922 }
921923
922924 //! @brief ジャンプ
923-//! @return 成功:0 失敗:1
924925 //! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。
925-int human::Jump()
926+void human::Jump()
926927 {
927- //地面に触れており、落下速度が0.0ならば
928- if( move_y_flag == false ){
929- if( move_y == 0.0f ){
930- move_y = HUMAN_JUMP_SPEED;
931-
932- //モーション実行
933- MotionCtrl->Jump();
934- return 0;
935- }
936- }
937- return 1;
928+ SetFlag(MoveFlag, MOVEFLAG_JUMP);
938929 }
939930
940931 //! @brief 押しだす・力を加える
@@ -1423,268 +1414,305 @@
14231414 //! @param CollD Collisionクラスのポインタ
14241415 //! @param inblockdata BlockDataInterfaceクラスのポインタ
14251416 //! @param AddCollisionFlag 追加の当たり判定フラグ
1426-//! @param FallDist Y軸の移動量を取得するポインタ
1427-//! @param nowmove_x X軸の移動量を取得するポインタ
1428-//! @param nowmove_z Z軸の移動量を取得するポインタ
1429-//! @return ブロックに埋まっている:true 埋まっていない:false
1430-bool human::MapCollisionDetection(class Collision *CollD, class BlockDataInterface *inblockdata, bool AddCollisionFlag, float *FallDist, float *nowmove_x, float *nowmove_z)
1417+//! @param player 対象の人物がプレイヤーかどうか
1418+void human::CollisionMap(class Collision *CollD, class BlockDataInterface *inblockdata, bool AddCollisionFlag, bool player)
14311419 {
1432- bool inside = false;
1433- int id;
1434- int face;
1435- float vx, vz;
1436- float vy = 0.1f;
1420+ float pos_x2, pos_y2, pos_z2;
1421+ float dist_x, dist_y, dist_z;
14371422 float speed;
14381423 float Dist;
1439- float FallDistance;
1440- float offset;
1441- float move_x2 = move_x;
1442- float move_z2 = move_z;
1424+ bool FallFlag;
14431425
1444- //足元ギリギリは当たり判定から除外する
1445- offset = 0.1f;
1426+ //現時点の座標をバックアップ
1427+ pos_x2 = pos_x;
1428+ pos_y2 = pos_y;
1429+ pos_z2 = pos_z;
14461430
1447- // 上下方向の当たり判定(ジャンプ・自然落下)
1448- //--------------------------------------------------
1431+ //移動反映
1432+ pos_x += move_x;
1433+ pos_z += move_z;
14491434
1450- //足元がブロックに埋まっていなければ
1451- if( CollD->CheckALLBlockInside(pos_x, pos_y + offset, pos_z) == false ){
1452- //落下速度を計算
1453- move_y -= HUMAN_DAMAGE_SPEED;
1454- if( move_y < HUMAN_DAMAGE_MAXSPEED ){ move_y = HUMAN_DAMAGE_MAXSPEED; }
1435+ //次フレームの移動量を減衰
1436+ move_x *= HUMAN_ATTENUATION;
1437+ move_z *= HUMAN_ATTENUATION;
14551438
1456- if( move_y > 0.0f ){
1457- //上方向へ当たり判定
1458- if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + HUMAN_HEIGHT, pos_z, 0, 1, 0, NULL, NULL, &Dist, move_y) == true ){
1459- CollD->CheckALLBlockIntersectRay(pos_x, pos_y + HUMAN_HEIGHT, pos_z, 0, 1, 0, NULL, NULL, &Dist, move_y);
1439+ //移動ベクトル算出
1440+ dist_x = pos_x - pos_x2;
1441+ dist_y = pos_y - pos_y2;
1442+ dist_z = pos_z - pos_z2;
14601443
1461- FallDistance = Dist;
1462- move_y = 0.0f;
1463- }
1464- else{
1465- FallDistance = move_y;
1466- }
1467- move_y_flag = true;
1444+ speed = sqrt(dist_x*dist_x + dist_z*dist_z);
1445+ if( (speed != 0.0f)||(move_y != 0.0f) ){
14681446
1469- //DummyRay() 関数の結果に関わらず FallDistance = move_y; でも良いのだろうか?
1447+ //頭部で当たり判定
1448+ if( CollisionBlockScratch(CollD, inblockdata, &pos_x, &pos_y, &pos_z, pos_x2, pos_y2, pos_z2, pos_x, pos_y + HUMAN_HEIGHT, pos_z, 0x01) == true ){
1449+ if( move_y > 0.0f ){ move_y = 0.0f; }
14701450 }
1471- else{
1472- int id, face;
1473- struct blockdata bdata;
14741451
1475- //下方向へ当たり判定
1476- if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + offset, pos_z, 0, -1, 0, NULL, NULL, &Dist, move_y*-1 + offset) == true ){
1477- if( CollD->CheckALLBlockIntersectRay(pos_x, pos_y + offset, pos_z, 0, -1, 0, &id, &face, &Dist, move_y*-1 + offset) == false ){
1478- //もし、-DummyRay()関数ではブロックが見つかるのに -Ray()関数で見つからないなら、おそらくブロックが歪んでいる。
1479- //とりあず適当な値で誤魔化し、微振動を防ぐ。
1480- Dist = offset;
1481- }
1452+ //足元で当たり判定
1453+ CollisionBlockScratch(CollD, inblockdata, &pos_x, &pos_y, &pos_z, pos_x2, pos_y2, pos_z2, pos_x, pos_y, pos_z, 0x00);
14821454
1483- if( Invincible == false ){
1484- //ダメージ計算
1485- if( move_y > HUMAN_DAMAGE_MINSPEED ){ hp -= 0; }
1486- else{ hp -= (int)((float)HUMAN_DAMAGE_MAXFALL / fabs(HUMAN_DAMAGE_MAXSPEED - (HUMAN_DAMAGE_MINSPEED)) * fabs(move_y - (HUMAN_DAMAGE_MINSPEED))); }
1487- }
1455+ //腰くらいで当たり判定
1456+ CollisionBlockScratch(CollD, inblockdata, &pos_x, &pos_y, &pos_z, pos_x2, pos_y2, pos_z2, pos_x + dist_x*HUMAN_MAPCOLLISION_R, pos_y + HUMAN_MAPCOLLISION_HEIGHT, pos_z + dist_z*HUMAN_MAPCOLLISION_R, 0x02);
1457+ CollisionBlockScratch(CollD, inblockdata, &pos_x, &pos_y, &pos_z, pos_x2, pos_y2, pos_z2, pos_x + dist_z*HUMAN_MAPCOLLISION_R, pos_y + HUMAN_MAPCOLLISION_HEIGHT, pos_z + dist_x*HUMAN_MAPCOLLISION_R, 0x02);
1458+ CollisionBlockScratch(CollD, inblockdata, &pos_x, &pos_y, &pos_z, pos_x2, pos_y2, pos_z2, pos_x + dist_z*HUMAN_MAPCOLLISION_R*-1, pos_y + HUMAN_MAPCOLLISION_HEIGHT, pos_z + dist_x*HUMAN_MAPCOLLISION_R*-1, 0x02);
14881459
1489- FallDistance = (Dist - offset) * -1;
1490- move_y = 0.0f;
1491-
1492- inblockdata->Getdata(&bdata, id);
1460+ if( AddCollisionFlag == true ){
1461+ //腰付近の追加当たり判定
1462+ CollisionBlockScratch(CollD, inblockdata, &pos_x, &pos_y, &pos_z, pos_x2, pos_y2, pos_z2, pos_x, pos_y + HUMAN_MAPCOLLISION_ADD_HEIGHT_A, pos_z, 0x02);
1463+ CollisionBlockScratch(CollD, inblockdata, &pos_x, &pos_y, &pos_z, pos_x2, pos_y2, pos_z2, pos_x, pos_y + HUMAN_MAPCOLLISION_ADD_HEIGHT_B, pos_z, 0x02);
1464+ }
14931465
1494- //斜面に立っているなら
1495- if( acos(bdata.material[face].vy) > HUMAN_MAPCOLLISION_SLOPEANGLE ){
1496- //地面と認めない (ジャンプ対策)
1497- move_y_flag = true;
1466+ //斜面を登る
1467+ if( (fabs(move_x) > 0.2f)||(fabs(move_z) > 0.2f) ){
1468+ if( move_y_upper == 0 ){
1469+ if(
1470+ (CollD->CheckALLBlockInside(pos_x + dist_x*2.0f, pos_y, pos_z + dist_z*2.0f) == true)&&
1471+ (CollD->CheckALLBlockInside(pos_x + dist_x*2.0f, pos_y + 3.2f, pos_z + dist_z*2.0f) == false)
1472+ ){
1473+ int id, face;
1474+ struct blockdata bdata;
1475+ bool flag = false;
14981476
1499- float angvx = atan2(bdata.material[face].vz, bdata.material[face].vx);
1500- float angvy = acos(bdata.material[face].vy);
1477+ //足元の面の角度を取得
1478+ if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y, pos_z, 0.0f, -1.0f, 0.0f, NULL, NULL, &Dist, 1.2f) == true ){
1479+ CollD->CheckALLBlockIntersectRay(pos_x, pos_y, pos_z, 0.0f, -1.0f, 0.0f, &id, &face, &Dist, 1.2f);
15011480
1502- //押し出す力の決定
1503- //y = -0.6*x*x + 1.9*x - 0.2
1504- float force = -0.6f*angvy*angvy + 1.9f*angvy - 0.2f;
1481+ inblockdata->Getdata(&bdata, id);
15051482
1506- //押し出す
1507- move_x = cos(angvx) * cos(HUMAN_MAPCOLLISION_SLOPEFORCEANGLE) * force;
1508- move_y = sin(HUMAN_MAPCOLLISION_SLOPEFORCEANGLE) * force;
1509- move_z = sin(angvx) * cos(HUMAN_MAPCOLLISION_SLOPEFORCEANGLE) * force;
1483+ //斜面に立っているならば、上昇無効
1484+ if( acos(bdata.material[face].vy) > HUMAN_MAPCOLLISION_SLOPEANGLE ){
1485+ flag = true;
1486+ }
1487+ }
15101488
1511- move_x2 = move_x;
1512- move_z2 = move_z;
1489+ if( flag == false ){
1490+ pos_y += 0.4f;
1491+ move_y *= 0.2f;
1492+ }
15131493 }
1514- else{
1515- move_y_flag = false;
1516- }
15171494 }
1518- else{
1519- FallDistance = move_y;
1520- move_y_flag = true;
1495+ }
1496+
1497+ //移動先がブロックへめり込んでいるなら移動を無効にする
1498+ if(
1499+ (CollD->CheckALLBlockInside(pos_x, pos_y + 2.0f, pos_z) == true)||
1500+ (CollD->CheckALLBlockIntersectRay(pos_x, pos_y + 2.0f, pos_z, 0.0f, 1.0f, 0.0f, NULL, NULL, &Dist, (18.0f-2.0f)) == true)
1501+ ){
1502+ pos_x = pos_x2;
1503+ pos_z = pos_z2;
1504+ }
1505+
1506+ //移動先がブロックにめり込む&移動先もめり込む ならば、移動を無効にする
1507+ if( CollD->CheckALLBlockInside(pos_x, pos_y + 19.4f, pos_z) == true ){
1508+ ////↓ここ怪しい
1509+ if( CollD->CheckALLBlockInside(pos_x + move_x*0.2f, pos_y + 19.4f, pos_z + move_x*0.2f) == true ){
1510+ pos_x = pos_x2;
1511+ pos_y = pos_y2;
1512+ pos_z = pos_z2;
1513+ if( move_y > 0.0f ){ move_y = 0.0f; }
15211514 }
15221515 }
15231516 }
1524- else{ //埋まっている
1525- FallDistance = move_y;
1526- move_y = 0.0f;
1527- move_y_flag = false;
1528- }
15291517
1518+ if( move_y_upper > 0 ) { move_y_upper -= 1; }
15301519
1531- // 水平方向の当たり判定(移動)
1532- //--------------------------------------------------
1520+ //落下処理
1521+ move_y_flag = false;
1522+ FallFlag = false;
1523+ for(int i=0; i<3; i++){
1524+ int cnt = 0;
1525+ float ang = atan2(move_z, move_x);
15331526
1534- if( (move_x2*move_x2 + move_z2*move_z2) ){
1535- int surface;
1536- float ang = atan2(move_z2, move_x2);
1537- float newpos_x, newpos_y, newpos_z;
1527+ pos_y += move_y*0.33f;
15381528
1539- //腰付近を当たり判定
1540- for(int i=0; i<MAX_BLOCKS; i++){
1541- float min_x, min_y, min_z, max_x, max_y, max_z;
1542- CollD->GetBlockPosMINMAX(i, &min_x, &min_y, &min_z, &max_x, &max_y, &max_z);
1529+ if( player == true ){
1530+ cnt = 0;
1531+ if( CollD->CheckALLBlockInside(pos_x + cos(ang)*0.15f, pos_y - 0.5f, pos_z + sin(ang)*0.15f) == true ){ cnt += 1; }
1532+ if( CollD->CheckALLBlockInside(pos_x - cos(ang)*0.15f, pos_y - 0.5f, pos_z - sin(ang)*0.15f) == true ){ cnt += 1; }
1533+ if( CollD->CheckALLBlockInside(pos_x + cos(ang + (float)M_PI/2)*0.15f, pos_y - 0.5f, pos_z + sin(ang + (float)M_PI/2)*0.15f) == true ){ cnt += 1; }
1534+ if( CollD->CheckALLBlockInside(pos_x + cos(ang - (float)M_PI/2)*0.15f, pos_y - 0.5f, pos_z + sin(ang - (float)M_PI/2)*0.15f) == true ){ cnt += 1; }
1535+ if( cnt == 4 ){ FallFlag = true; break; }
15431536
1544- //腰付近をAABBで荒削り
1545- if( CollideBoxAABB(min_x, min_y, min_z, max_x, max_y, max_z,
1546- pos_x - HUMAN_MAPCOLLISION_R - 1.0f, pos_y + HUMAN_MAPCOLLISION_HEIGHT - 1.0f, pos_z - HUMAN_MAPCOLLISION_R - 1.0f, pos_x + HUMAN_MAPCOLLISION_R + 1.0f, pos_y + HUMAN_MAPCOLLISION_HEIGHT + 1.0f, pos_z + HUMAN_MAPCOLLISION_R + 1.0f) == true
1547- ){
1548- surface = -1;
1549- CollD->CheckBlockInside(i, pos_x, pos_y + HUMAN_MAPCOLLISION_HEIGHT, pos_z, false, &surface);
1537+ if( CollD->CheckALLBlockInside(pos_x + cos(ang)*0.5f, pos_y - 0.5f, pos_z + sin(ang)*0.5f) == true ){ cnt += 1; }
1538+ if( CollD->CheckALLBlockInside(pos_x - cos(ang)*0.5f, pos_y - 0.5f, pos_z - sin(ang)*0.5f) == true ){ cnt += 1; }
1539+ if( CollD->CheckALLBlockInside(pos_x + cos(ang + (float)M_PI/2)*0.5f, pos_y - 0.5f, pos_z + sin(ang + (float)M_PI/2)*0.5f) == true ){ cnt += 1; }
1540+ if( CollD->CheckALLBlockInside(pos_x + cos(ang - (float)M_PI/2)*0.5f, pos_y - 0.5f, pos_z + sin(ang - (float)M_PI/2)*0.5f) == true ){ cnt += 1; }
1541+ if( cnt == 4 ){ FallFlag = true; break; }
1542+ }
1543+ else{
1544+ if( CollD->CheckALLBlockInside(pos_x, pos_y - 0.5f, pos_z) == true ){ FallFlag = true; break; }
1545+ if( CollD->CheckALLBlockInside(pos_x + cos(ang)*0.3f, pos_y - 0.5f, pos_z + sin(ang)*0.3f) == true ){ FallFlag = true; break; }
1546+ }
15501547
1551- if( surface != -1 ){
1552- //HUMAN_MAPCOLLISION_R 分の先を調べる
1553- if( CollD->CheckBlockInside(i, pos_x + cos(ang)*HUMAN_MAPCOLLISION_R, pos_y + HUMAN_MAPCOLLISION_HEIGHT, pos_z + sin(ang)*HUMAN_MAPCOLLISION_R, true, NULL) == true ){
1554- CollD->ScratchVector(i, surface, move_x2, vy, move_z2, &move_x2, &vy, &move_z2);
1555- }
1548+ //落下速度加算
1549+ move_y -= 0.066f;
1550+ if( move_y < HUMAN_DAMAGE_MAXSPEED ){ move_y = HUMAN_DAMAGE_MAXSPEED; }
15561551
1557- //左右90度づつを調べる
1558- if( CollD->CheckBlockInside(i, pos_x + cos(ang + (float)M_PI/2)*HUMAN_MAPCOLLISION_R, pos_y + HUMAN_MAPCOLLISION_HEIGHT, pos_z + sin(ang + (float)M_PI/2)*HUMAN_MAPCOLLISION_R, true, NULL) == true ){
1559- if( CollD->CheckPolygonFrontRx(i, surface, ang) == true ){ //進行方向に対して表向きなら〜
1560- CollD->ScratchVector(i, surface, move_x2, vy, move_z2, &move_x2, &vy, &move_z2);
1561- }
1562- }
1563- if( CollD->CheckBlockInside(i, pos_x + cos(ang - (float)M_PI/2)*HUMAN_MAPCOLLISION_R, pos_y + HUMAN_MAPCOLLISION_HEIGHT, pos_z + sin(ang - (float)M_PI/2)*HUMAN_MAPCOLLISION_R, true, NULL) == true ){
1564- if( CollD->CheckPolygonFrontRx(i, surface, ang) == true ){ //進行方向に対して表向きなら〜
1565- CollD->ScratchVector(i, surface, move_x2, vy, move_z2, &move_x2, &vy, &move_z2);
1566- }
1567- }
1568- }
1569- }
1570- }
1552+ move_y_flag = true;
1553+ }
15711554
1572- //進行方向を示すベクトルを算出
1573- vx = move_x2;
1574- vz = move_z2;
1575- speed = sqrt(vx*vx + vz*vz);
1576- if( speed > 0.0f ){
1577- vx = vx / speed;
1578- vz = vz / speed;
1579- }
1555+ if( FallFlag == true ){
1556+ int id, face;
1557+ struct blockdata bdata;
1558+ bool flag = true;
15801559
1581- //頭を当たり判定
1582- if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + HUMAN_HEIGHT, pos_z, vx, 0, vz, NULL, NULL, &Dist, speed) == true ){
1583- CollD->CheckALLBlockIntersectRay(pos_x, pos_y + FallDistance + HUMAN_HEIGHT, pos_z, vx, 0, vz, &id, &face, &Dist, speed);
1584- CollD->ScratchVector(id, face, move_x2, vy, move_z2, &move_x2, &vy, &move_z2);
1560+ //落下ダメージを与える
1561+ if( move_y < HUMAN_DAMAGE_MINSPEED ){
1562+ //hp -= GetRand(6) + (int)( fabs(move_y + HUMAN_DAMAGE_MINSPEED)*37.5f );
1563+ hp -= GetRand(6) + (int)((float)HUMAN_DAMAGE_MAXFALL / fabs(HUMAN_DAMAGE_MAXSPEED - (HUMAN_DAMAGE_MINSPEED)) * fabs(move_y - (HUMAN_DAMAGE_MINSPEED)));
15851564 }
15861565
1587- if( AddCollisionFlag == true ){
1588- //腰付近の追加当たり判定
1589- if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + HUMAN_MAPCOLLISION_ADD_HEIGHT_A, pos_z, vx, 0, vz, NULL, NULL, &Dist, speed) == true ){
1590- CollD->CheckALLBlockIntersectRay(pos_x, pos_y + FallDistance + HUMAN_MAPCOLLISION_ADD_HEIGHT_A, pos_z, vx, 0, vz, &id, &face, &Dist, speed);
1591- CollD->ScratchVector(id, face, move_x2, vy, move_z2, &move_x2, &vy, &move_z2);
1592- }
1566+ move_y = 0.0f;
15931567
1594- //腰付近の追加当たり判定
1595- if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + HUMAN_MAPCOLLISION_ADD_HEIGHT_B, pos_z, vx, 0, vz, NULL, NULL, &Dist, speed) == true ){
1596- CollD->CheckALLBlockIntersectRay(pos_x, pos_y + FallDistance + HUMAN_MAPCOLLISION_ADD_HEIGHT_B, pos_z, vx, 0, vz, &id, &face, &Dist, speed);
1597- CollD->ScratchVector(id, face, move_x2, vy, move_z2, &move_x2, &vy, &move_z2);
1598- }
1568+ if( (GetFlag(MoveFlag_lt, MOVEFLAG_JUMP))&&(move_y_upper == 0) ){
1569+ move_y = HUMAN_JUMP_SPEED;
1570+
1571+ //モーション実行
1572+ MotionCtrl->Jump();
15991573 }
16001574
1601- //足元がブロックに埋まっていなければ
1602- if( CollD->CheckALLBlockInside(pos_x, pos_y + offset, pos_z) == false ){
1575+ if( GetRand(4) == 0 ){
1576+ if( (GetFlag(MoveFlag_lt, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT | MOVEFLAG_WALK)) == 0x00)&&(move_y_upper == 0) ){ flag = false; }
1577+ }
16031578
1604- //進行方向を示すベクトルを算出
1605- vx = move_x2;
1606- vz = move_z2;
1607- speed = sqrt(vx*vx + vz*vz);
1608- if( speed > 0.0f ){
1609- vx = vx / speed;
1610- vz = vz / speed;
1611- }
1579+ if( flag == true ){
1580+ //足元の面の角度を取得
1581+ if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + 2.5f, pos_z, 0.0f, -1.0f, 0.0f, NULL, NULL, &Dist, (2.5f + 1.0f)) == true ){
1582+ CollD->CheckALLBlockIntersectRay(pos_x, pos_y + 2.5f, pos_z, 0.0f, -1.0f, 0.0f, &id, &face, &Dist, (2.5f + 1.0f));
16121583
1613- //足元を当たり判定
1614- if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + offset, pos_z, vx, 0, vz, NULL, NULL, &Dist, speed) == true ){
1615- CollD->CheckALLBlockIntersectRay(pos_x, pos_y + offset, pos_z, vx, 0, vz, &id, &face, &Dist, speed);
1616-
1617- struct blockdata bdata;
16181584 inblockdata->Getdata(&bdata, id);
1619- float surface_ang = acos(bdata.material[face].vy);
16201585
1621- if( surface_ang > DegreeToRadian((90.0f-1.0f)) ){ //壁なら
1622- //乗り越えられる高さか調べる
1623- if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + 3.5f + offset, pos_z, vx, 0, vz, NULL, NULL, &Dist, speed) == false ){
1624- //人を上に持ち上げる
1625- FallDistance = 0.4f;
1586+ //斜面に立っているならば、斜面を滑らせる処理
1587+ if( acos(bdata.material[face].vy) > HUMAN_MAPCOLLISION_SLOPEANGLE ){
1588+ move_x = bdata.material[face].vx * 1.2f;
1589+ move_y = bdata.material[face].vy * -0.5f;
1590+ move_z = bdata.material[face].vz * 1.2f;
1591+
1592+ if( CollD->CheckALLBlockInside(pos_x + move_x*3.0f, pos_y + move_y*3.0f, pos_z + move_z*3.0f) == true ){
16261593 move_y = 0.0f;
1594+ if( CollD->CheckALLBlockInside(pos_x + move_x*3.0f, pos_y, pos_z + move_z*3.0f) == true ){
1595+ move_x = 0.0f;
1596+ move_z = 0.0f;
1597+ }
16271598 }
16281599
1629- //足元を当たり判定
1630- CollD->ScratchVector(id, face, move_x2, vy, move_z2, &move_x2, &vy, &move_z2);
1600+ move_y_upper = 8;
16311601 }
1632- else if( surface_ang > HUMAN_MAPCOLLISION_SLOPEANGLE ){ //斜面〜壁なら
1633- //足元を当たり判定
1634- CollD->ScratchVector(id, face, move_x2, vy, move_z2, &move_x2, &vy, &move_z2);
1635- }
1636- else{ //水平〜斜面なら
1637- //地面と認めない (ジャンプ対策)
1638- move_y_flag = true;
1602+ }
1603+ }
1604+ }
16391605
1640- //移動先の位置を計算
1641- newpos_x = pos_x + move_x2;
1642- newpos_y = pos_y + FallDistance;
1643- newpos_z = pos_z + move_z2;
1606+ //移動ベクトル再算出
1607+ dist_x = pos_x - pos_x2;
1608+ dist_y = pos_y - pos_y2;
1609+ dist_z = pos_z - pos_z2;
16441610
1645- //移動先の高さを調べる
1646- if( CollD->CheckALLBlockInside(newpos_x, newpos_y + HUMAN_HEIGHT, newpos_z) == false ){
1647- if( CollD->CheckALLBlockIntersectRay(newpos_x, newpos_y + HUMAN_HEIGHT, newpos_z, 0, -1, 0, NULL, NULL, &Dist, HUMAN_HEIGHT) == true ){
1648- float height = HUMAN_HEIGHT - Dist;
1611+ Dist = sqrt(dist_x*dist_x + dist_z*dist_z);
1612+ speed = sqrt((move_x*2)*(move_x*2) + (move_z*2)*(move_z*2));
16491613
1650- //人を上に持ち上げる
1651- FallDistance = height;
1614+ //明らかに移動量がおかしいならば元に戻す
1615+ if( (sqrt(dist_x*dist_x + dist_y*dist_y + dist_z*dist_z) > 12.0f)||(Dist - speed > 1.0f) ){
1616+ pos_x = pos_x2;
1617+ pos_y = pos_y2;
1618+ pos_z = pos_z2;
1619+ }
16521620
1653- if( height > 0.4f ){
1654- move_x2 *= 0.75f;
1655- move_z2 *= 0.75f;
1656- move_x = move_x2;
1657- move_z = move_z2;
1658- }
1621+ if( player == true ){
1622+ speed = sqrt(dist_x*dist_x + dist_y*dist_y + dist_z*dist_z);
16591623
1660- move_y = 0.0f;
1661- }
1662- }
1663- }
1664- }
1665- }
1666-
1667- //移動先の位置を計算
1668- newpos_x = pos_x + move_x2;
1669- newpos_y = pos_y + FallDistance;
1670- newpos_z = pos_z + move_z2;
1671-
1672- //全身を改めて確認
1624+ //移動先との間にブロックがあるならば元に戻す(目線ぐらいの高さで判定)
16731625 if(
1674- (CollD->CheckALLBlockInside(newpos_x, newpos_y + offset, newpos_z) == true)||
1675- (CollD->CheckALLBlockIntersectRay(newpos_x, newpos_y + offset, newpos_z, 0, 1, 0, NULL, NULL, &Dist, HUMAN_HEIGHT - offset - 1.0f) == true)
1626+ (CollD->CheckALLBlockInside(pos_x2, pos_y2 + 17.0f, pos_z2) == true)||
1627+ (CollD->CheckALLBlockIntersectRay(pos_x2, pos_y2 + 17.0f, pos_z2, dist_x/speed, dist_y/speed, dist_z/speed, NULL, NULL, &Dist, speed) == true)
16761628 ){
1677- //めり込むなら移動しない
1678- move_x2 = 0.0f;
1679- move_z2 = 0.0f;
1680- inside = true;
1629+ pos_x = pos_x2;
1630+ pos_y = pos_y2;
1631+ pos_z = pos_z2;
16811632 }
16821633 }
1634+}
16831635
1684- *FallDist = FallDistance;
1685- *nowmove_x = move_x2;
1686- *nowmove_z = move_z2;
1687- return inside;
1636+//! @brief ブロックと衝突時のベクトル計算
1637+//! @param CollD Collisionクラスのポインタ
1638+//! @param inblockdata BlockDataInterfaceクラスのポインタ
1639+//! @param px X座標
1640+//! @param py Y座標
1641+//! @param pz Z座標
1642+//! @param px_old 前フレームのX座標
1643+//! @param py_old 前フレームのY座標
1644+//! @param pz_old 前フレームのZ座標
1645+//! @param in_vx 判定するX座標
1646+//! @param in_vy 判定するY座標
1647+//! @param in_vz 判定するZ座標
1648+//! @param mode 座標補正モード(0x00:通常、0x01:Y座標上昇禁止、0x02:Y座標固定)
1649+//! @return 成功:true 失敗:false
1650+bool human::CollisionBlockScratch(class Collision *CollD, class BlockDataInterface *inblockdata, float *px, float *py, float *pz, float px_old, float py_old, float pz_old, float in_vx, float in_vy, float in_vz, int mode)
1651+{
1652+ //if( (*px == px_old)&&(*py == py_old)&&(*pz == pz_old) ){ return false; }
1653+
1654+ float px2, py2, pz2;
1655+ float vx, vy, vz;
1656+ float speed;
1657+ float dist;
1658+ int id, face;
1659+ float face_vx, face_vy, face_vz, face_angle, face_angle_per;
1660+ float temp;
1661+
1662+ px2 = *px;
1663+ py2 = *py;
1664+ pz2 = *pz;
1665+
1666+ //追突したブロック面取得
1667+ vx = in_vx - px_old;
1668+ vy = in_vy - py_old;
1669+ vz = in_vz - pz_old;
1670+ speed = VectorNormalization(&vx, &vy, &vz);
1671+ if( CollD->CheckALLBlockIntersectDummyRay(px_old, py_old, pz_old, vx, vy, vz, NULL, NULL, &dist, speed) == false ){ return false; }
1672+ if( CollD->CheckALLBlockIntersectRay(px_old, py_old, pz_old, vx, vy, vz, &id, &face, &dist, speed) == false ){ return false; }
1673+
1674+ //現在の移動ベクトルと距離算出
1675+ vx = *px - px_old;
1676+ vy = *py - py_old;
1677+ vz = *pz - pz_old;
1678+ dist = VectorNormalization(&vx, &vy, &vz);
1679+
1680+ //ブロックに沿って移動するベクトルと進入角度を求める
1681+ if( CollD->ScratchAngleVector(id, face, vx, vy, vz, &vx, &vy, &vz, &face_angle) == false ){ return false; }
1682+
1683+ //角度の割合算出
1684+ if( face_angle != 0.0f ){ face_angle_per = 1.0f - face_angle / ((float)M_PI); }
1685+ else{ face_angle_per = 0.0f; }
1686+
1687+ //ブロック面の法線ベクトル取得
1688+ struct blockdata bdata;
1689+ inblockdata->Getdata(&bdata, id);
1690+ face_vx = bdata.material[face].vx;
1691+ face_vy = bdata.material[face].vy;
1692+ face_vz = bdata.material[face].vz;
1693+
1694+ //最終的な位置を計算
1695+ temp = face_angle_per * dist;
1696+ *px = vx*temp + px_old;
1697+ *py = vy*temp + py_old;
1698+ *pz = vz*temp + pz_old;
1699+
1700+ //最終的な位置がブロックの内側ならば、移動無効
1701+ if( CollD->CheckALLBlockInside(*px, *py, *pz) == true ){
1702+ *px = px2;
1703+ *py = py2;
1704+ *pz = pz2;
1705+ }
1706+
1707+ //座標補正
1708+ if( mode == 0x01 ){
1709+ if( *py > py2 ){ *py = py2; } //今より上には移動させない
1710+ }
1711+ if( mode == 0x02 ){
1712+ *py = py2; //Y座標は変えない
1713+ }
1714+
1715+ return true;
16881716 }
16891717
16901718 //! @brief 計算を実行(当たり判定)
@@ -1709,10 +1737,7 @@
17091737
17101738 int WeaponReloadMotionCnt;
17111739 int WeaponChangeWeaponIDCnt;
1712- float FallDistance;
1713- float nowmove_x, nowmove_z;
17141740 int CheckDead;
1715- int hp_old;
17161741
17171742 //武器切り替えカウント
17181743 if( selectweaponcnt > 0 ){
@@ -1758,27 +1783,8 @@
17581783 ControlProcess();
17591784
17601785 //マップとの当たり判定
1761- hp_old = hp;
1762- MapCollisionDetection(CollD, inblockdata, AddCollisionFlag, &FallDistance, &nowmove_x, &nowmove_z);
1786+ CollisionMap(CollD, inblockdata, AddCollisionFlag, player);
17631787
1764- //移動するなら
1765- if( (nowmove_x*nowmove_x + nowmove_z*nowmove_z) > 0.0f ){
1766- totalmove += sqrt(nowmove_x*nowmove_x + nowmove_z*nowmove_z);
1767- }
1768-
1769- //座標移動
1770- pos_x += nowmove_x;
1771- pos_z += nowmove_z;
1772-
1773- //移動量を減衰
1774- move_x *= HUMAN_ATTENUATION;
1775- move_z *= HUMAN_ATTENUATION;
1776-
1777- //F5を使用していなければ、計算結果を反映
1778- if( F5mode == false ){
1779- pos_y += FallDistance;
1780- }
1781-
17821788 //今回の当たり判定で-100.0より下に落ちたら、死亡
17831789 if( CheckDead == 0 ){
17841790 if( pos_y < HUMAN_DEADLINE ){
@@ -1787,11 +1793,6 @@
17871793 return 4;
17881794 }
17891795 }
1790-
1791- //今回のマップとの当たり判定でHPがゼロになったなら、地形による死亡
1792- if( (hp_old >0)&&(hp <= 0) ){
1793- return 4;
1794- }
17951796 }
17961797
17971798
--- trunk/object.h (revision 261)
+++ trunk/object.h (revision 262)
@@ -43,7 +43,7 @@
4343 #define HUMAN_PROGRESSWALK_ACCELERATION 0.35f //!< 人が歩く加速度
4444 #define HUMAN_ATTENUATION 0.5f //!< 人の1フレームあたりの減衰率 (0.0 < x < 1.0)
4545
46-#define HUMAN_JUMP_SPEED (2.2f + (HUMAN_DAMAGE_SPEED)) //!< ジャンプする速度
46+#define HUMAN_JUMP_SPEED 2.2f //!< ジャンプする速度
4747
4848 #define HUMAN_HEIGHT 20.0f //!< 人の高さ
4949 #define HUMAN_DAMAGE_HEAD 2.0f //!< 弾が 頭 に当たった場合のダメージ倍率
@@ -70,10 +70,10 @@
7070 #define ARMRAD_NOWEAPON DegreeToRadian((-90 + 20)) //!< 手ぶら時の腕の描画角度
7171 #define ARMRAD_RELOADWEAPON DegreeToRadian(-20) //!< リロード時の腕の描画角度
7272
73-#define HUMAN_MAPCOLLISION_R 5.0f //!< 人とマップの当たり判定 半径
74-#define HUMAN_MAPCOLLISION_HEIGHT 10.2f //!< 人とマップの当たり判定 高さ(注:腰程度)
75-#define HUMAN_MAPCOLLISION_ADD_HEIGHT_A 9.2f //!< 人とマップの当たり判定 追加分 高さ(注:標準マップ SCHOOL に合わせる)
76-#define HUMAN_MAPCOLLISION_ADD_HEIGHT_B 13.2f //!< 人とマップの当たり判定 追加分 高さ(注:標準マップ SCHOOL に合わせる)
73+#define HUMAN_MAPCOLLISION_R 2.8f //!< 人とマップの当たり判定 半径
74+#define HUMAN_MAPCOLLISION_HEIGHT 10.0f //!< 人とマップの当たり判定 高さ(注:腰程度)
75+#define HUMAN_MAPCOLLISION_ADD_HEIGHT_A 9.0f //!< 人とマップの当たり判定 追加分 高さ(注:標準マップ SCHOOL に合わせる)
76+#define HUMAN_MAPCOLLISION_ADD_HEIGHT_B 13.0f //!< 人とマップの当たり判定 追加分 高さ(注:標準マップ SCHOOL に合わせる)
7777 #define HUMAN_MAPCOLLISION_SLOPEANGLE DegreeToRadian(50) //!< 人とマップの当たり判定 登れない斜面の角度
7878 #define HUMAN_MAPCOLLISION_SLOPEFORCEANGLE DegreeToRadian(22.62f) //!< 人とマップの当たり判定 登れない斜面が人を押し出す角度
7979 #define HUMAN_DEADLINE -100.0f //!< 人が死亡するY座標(デッドライン)
@@ -135,6 +135,7 @@
135135 float move_y; //!< Y軸(落下)速度
136136 float move_z; //!< Z軸速度
137137 bool move_y_flag; //!< Y軸移動フラグ
138+ int move_y_upper; //!< Y軸上昇禁止カウンター
138139 float rotation_y; //!< 全体の回転角度
139140 float armrotation_y; //!< 腕の回転角度
140141 float upmodel_size; //!< 上半身描画サイズ
@@ -167,7 +168,8 @@
167168 void GunsightErrorRange();
168169 int CheckAndProcessDead(class Collision *CollD);
169170 void ControlProcess();
170- bool MapCollisionDetection(class Collision *CollD, class BlockDataInterface *inblockdata, bool AddCollisionFlag, float *FallDist, float *nowmove_x, float *nowmove_z);
171+ void CollisionMap(class Collision *CollD, class BlockDataInterface *inblockdata, bool AddCollisionFlag, bool player);
172+ bool CollisionBlockScratch(class Collision *CollD, class BlockDataInterface *inblockdata, float *px, float *py, float *pz, float px_old, float py_old, float pz_old, float in_vx, float in_vy, float in_vz, int mode);
171173
172174 public:
173175 human(class ParameterInfo *in_Param = NULL, float x = 0.0f, float y = 0.0f, float z = 0.0f, float rx = 0.0f, int id_param = -1, int dataid = 0, signed char p4 = 0, int team = 0, bool flag = false);
@@ -208,7 +210,7 @@
208210 virtual void GetRxRy(float *rx, float *ry);
209211 virtual void SetRxRy(float rx, float ry);
210212 virtual float GetDeadRy();
211- virtual int Jump();
213+ virtual void Jump();
212214 virtual void AddPosOrder(float rx, float ry, float speed);
213215 virtual void HitBulletHead(int attacks);
214216 virtual void HitBulletUp(int attacks);
@@ -404,6 +406,7 @@
404406 MOVEFLAG_LEFT = 0x04,
405407 MOVEFLAG_RIGHT = 0x08,
406408 MOVEFLAG_WALK = 0x10,
409+ MOVEFLAG_JUMP = 0x20,
407410 };
408411
409412 //! エフェクトの種類を表す定数
--- trunk/parameter.cpp (revision 261)
+++ trunk/parameter.cpp (revision 262)
@@ -1878,7 +1878,7 @@
18781878 if( fullname != NULL ){ strcpy(fullname, MissionData[id].fullname); }
18791879 if( directory != NULL ){ strcpy(directory, MissionData[id].directory); }
18801880 if( txt != NULL ){ strcpy(txt, MissionData[id].txt); }
1881- if( collisionflag != NULL ){ *collisionflag = MissionData[id].screen; }
1881+ if( collisionflag != NULL ){ *collisionflag = MissionData[id].collision; }
18821882 if( screenflag != NULL ){ *screenflag = MissionData[id].screen; }
18831883 return 0;
18841884 }