-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcomai.cpp
More file actions
236 lines (214 loc) · 6.28 KB
/
comai.cpp
File metadata and controls
236 lines (214 loc) · 6.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
//==========================================
//
//コンピューターのAIプログラム[comai.cpp]
//Author:石原颯馬
//
//==========================================
#include "main.h"
#include "comai.h"
#include "PvP_player.h"
#include "input.h"
#include "meshfield.h"
#include "conversioninput.h"
#include <time.h>
//マクロ
#define CHARGE_LENGTH_AVG (600.0f) //チャージの移動距離の基準値
#define CHARGE_DIGIT (100) //チャージの小数点の位置指定
#define HIPDROP_RADIUS (100.0f) //落下回避ヒップドロップまでの距離
#define HIPDROP_RAND_DIGIT (100) //ヒップドロップ回避確率桁数
#define CHARGE_WAIT (75) //チャージする前の待機時間
#define ONE_MORE_PUSH (0.31f) //プレイヤーを落とすためにするもう一押し
//プロト
void RotateAI(Player *pCom);
void ChargeAI(Player *pCom);
//グローバル
ComAIBrain g_aAIBrain[MAX_USE_GAMEPAD];
bool g_bUseAIPointer[MAX_USE_GAMEPAD];
const AIParam c_aAIParam[AIDIFF_MAX] =
{
{ 0.50f, 0.25f, 30, 20 }, //EASY
{ 0.25f, 0.17f, 60, 15 }, //NORMAL
{ 0.15f, 0.10f, 90, 10 }, //HARD
{ 0.00f, 0.50f, 0, 0 } //VIEW
};
//========================
//初期化処理
//========================
void InitComAI(void)
{
srand((unsigned int)time(NULL)); //乱数の初期化
for (int nCntAI = 0; nCntAI < MAX_USE_GAMEPAD; nCntAI++)
{//脳みそを空っぽにする
g_aAIBrain[nCntAI] = {};
g_aAIBrain[nCntAI].nCounterWaitTime = 0;
g_aAIBrain[nCntAI].difficulty = AIDIFF_NORMAL;
g_aAIBrain[nCntAI].bDoHipdrop = false;
g_aAIBrain[nCntAI].bHipdropped = false;
g_bUseAIPointer[nCntAI] = false;
}
}
//========================
//終了処理
//========================
void UninitComAI(void)
{
for (int nCntAI = 0; nCntAI < MAX_USE_GAMEPAD; nCntAI++)
{//AIを使っていないことにする
g_bUseAIPointer[nCntAI] = false;
}
}
//========================
//選択処理
//========================
void SelectAIMove(Player *pCom)
{
if (pCom->stat != PLAYERSTAT_FALL)
{//落ちていない
RotateAI(pCom);
//あらかじめAIの中心からの距離求める
float fAILength = fabsf(D3DXVec3Length(&pCom->pos));
//スティック操作をしていないならチャージ
if (pCom->pAI->nCounterWaitTime >= CHARGE_WAIT)
{
float fMoveLength = sqrtf(powf(fAILength, 2) + powf(GetMeshField()->fRadius, 2) - 2 * fAILength * GetMeshField()->fRadius * cosf(pCom->rot.y)) / CHARGE_LENGTH_AVG; //ジャストなチャージ量を求める
//↓でアバウトにしていく
int nChargeWidth = (int)((((fMoveLength + c_aAIParam[pCom->pAI->difficulty].fChargeAboutPlus) - (fMoveLength - c_aAIParam[pCom->pAI->difficulty].fChargeAboutMinus)) * CHARGE_DIGIT) + ONE_MORE_PUSH);
pCom->pAI->fChargePower = (float)(rand() % (nChargeWidth + 1)) / CHARGE_DIGIT + (fMoveLength - c_aAIParam[pCom->pAI->difficulty].fChargeAboutMinus);
//最低値以下なら最低値にする
if (pCom->pAI->fChargePower < 1.0f / CHARGE_DIGIT)
{
pCom->pAI->fChargePower = 1.0f / CHARGE_DIGIT;
}
else if (pCom->pAI->fChargePower > PLAYER_POWER_MAX)
{
pCom->pAI->fChargePower = PLAYER_POWER_MAX;
}
ChargeAI(pCom);
}
else if (GetButton(pCom->nPlayerNum, INPUTTYPE_PRESS, BUTTON_X) == true)
{
ChargeAI(pCom);
}
//落ちそうならヒップドロップ回避
if (GetMeshField()->fRadius - fAILength <= HIPDROP_RADIUS)
{
if (pCom->pAI->bHipdropped == false)
{
pCom->pAI->bDoHipdrop = rand() % (HIPDROP_RAND_DIGIT + 1) <= c_aAIParam[pCom->pAI->difficulty].nHipdropRandom ? true : false;
if (pCom->pAI->bDoHipdrop == true || pCom->stat == PLAYERSTAT_JUMP)
{
SetButton(pCom->nPlayerNum, INPUTTYPE_TRIGGER, BUTTON_A, true);
if (pCom->stat == PLAYERSTAT_JUMP)
{
if (pCom->jumpTime > c_aAIParam[pCom->pAI->difficulty].nHipdropTime)
{
pCom->pAI->bHipdropped = true;
}
else
{
SetButton(pCom->nPlayerNum, INPUTTYPE_TRIGGER, BUTTON_A, false);
}
}
}
else
{
pCom->pAI->bHipdropped = true;
}
}
else
{
SetButton(pCom->nPlayerNum, INPUTTYPE_PRESS, BUTTON_A, false);
}
}
else
{
pCom->pAI->bHipdropped = false;
SetButton(pCom->nPlayerNum, INPUTTYPE_PRESS, BUTTON_A, false);
}
}
else
{//落ちたのでAIがコントローラーから手を放してOMGしている
SetButton(pCom->nPlayerNum, INPUTTYPE_PRESS, BUTTON_A, false);
SetButton(pCom->nPlayerNum, INPUTTYPE_PRESS, BUTTON_X, false);
SetButton(pCom->nPlayerNum, INPUTTYPE_RELEASE, BUTTON_X, false);
SetStick(pCom->nPlayerNum, CONVSTICK_NEUTRAL);
}
}
//========================
//回転処理
//========================
void RotateAI(Player *pCom)
{
Player *pPlayer = GetPlayer();
Player *pNearPlayer = NULL;
float fMinLength = -1.0f;
//一番近いプレイヤーの方を向くようにする
//近いプレイヤーを探す
for (int nCntPlayer = 0; nCntPlayer < MAX_USE_GAMEPAD; nCntPlayer++)
{
if ((pPlayer + nCntPlayer) != pCom)
{//自分でなければ
//距離計算
float fLength = PYTHAGORAS(((pPlayer + nCntPlayer)->pos.x - pCom->pos.x), ((pPlayer + nCntPlayer)->pos.z - pCom->pos.z));
if (pNearPlayer == NULL || fMinLength >= fLength)
{//何も入っていない または もっと近いプレイヤー見つけた
//距離と近いプレイヤーのポインタ代入
fMinLength = fLength;
pNearPlayer = (pPlayer + nCntPlayer);
}
}
}
//角度を変える(2DSTGのホーミング技術使用)
float fRotMove = pCom->rot.y;
float fRotDest = atan2f(pNearPlayer->pos.x - pCom->pos.x, pNearPlayer->pos.z - pCom->pos.z);
float fRotDiff = FIX_ROT(fRotDest - fRotMove + D3DX_PI);
if ((int)(fabsf(fRotDiff) * 10) == 0)//10にしないと厳しすぎてプルプルする
{
SetStick(pCom->nPlayerNum, CONVSTICK_NEUTRAL);
pCom->pAI->nCounterWaitTime++;
}
else
{
//判断
if ((int)copysign(1, fRotDiff) < 0)
{
SetStick(pCom->nPlayerNum, CONVSTICK_LEFT);
}
else
{
SetStick(pCom->nPlayerNum, CONVSTICK_RIGHT);
}
}
}
//========================
//チャージボタンを押す処理
//========================
void ChargeAI(Player *pCom)
{
if (pCom->moveGauge >= pCom->pAI->fChargePower)
{
SetButton(pCom->nPlayerNum, INPUTTYPE_PRESS, BUTTON_X, false);
SetButton(pCom->nPlayerNum, INPUTTYPE_RELEASE, BUTTON_X, true);
pCom->pAI->nCounterWaitTime = 0;
}
else
{
SetButton(pCom->nPlayerNum, INPUTTYPE_PRESS, BUTTON_X, true);
}
}
//========================
//選択処理
//========================
ComAIBrain *GetAI(AIDIFF diff)
{
for (int nCntAI = 0; nCntAI < MAX_USE_GAMEPAD; nCntAI++)
{
if (g_bUseAIPointer[nCntAI] == false)
{
g_bUseAIPointer[nCntAI] = true;
g_aAIBrain[nCntAI].difficulty = diff;
return &g_aAIBrain[nCntAI];
}
}
return NULL;
}