X operations(XOPS)に非常に近いFPSゲームを制作・リメイクし、成果物をオープンソースとして公開することを目的としたプロジェクトです。
Revision | 45 (tree) |
---|---|
Time | 2015-02-20 01:15:15 |
Author | ![]() |
Version:1.010
@@ -0,0 +1,115 @@ | ||
1 | +//! @file main.h | |
2 | +//! @brief 最上位のヘッダーファイル | |
3 | + | |
4 | +//-------------------------------------------------------------------------------- | |
5 | +// | |
6 | +// OpenXOPS | |
7 | +// Copyright (c) 2014-2015, OpenXOPS Project / [-_-;](mikan) All rights reserved. | |
8 | +// | |
9 | +// Redistribution and use in source and binary forms, with or without | |
10 | +// modification, are permitted provided that the following conditions are met: | |
11 | +// * Redistributions of source code must retain the above copyright notice, | |
12 | +// this list of conditions and the following disclaimer. | |
13 | +// * Redistributions in binary form must reproduce the above copyright notice, | |
14 | +// this list of conditions and the following disclaimer in the documentation | |
15 | +// and/or other materials provided with the distribution. | |
16 | +// * Neither the name of the OpenXOPS Project nor the names of its contributors | |
17 | +// may be used to endorse or promote products derived from this software | |
18 | +// without specific prior written permission. | |
19 | +// | |
20 | +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
21 | +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
22 | +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
23 | +// DISCLAIMED. IN NO EVENT SHALL OpenXOPS Project BE LIABLE FOR ANY | |
24 | +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
25 | +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
26 | +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
27 | +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 | +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
29 | +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | +//-------------------------------------------------------------------------------- | |
31 | + | |
32 | +#ifndef MAIN_H | |
33 | +#define MAIN_H | |
34 | + | |
35 | +#define MAINICON 101 //!< Icon | |
36 | + | |
37 | +//BorlandC++ Compilerか判定 | |
38 | +#ifndef _MSC_VER | |
39 | + #define COMPILER_BCC //!< Use BorlandC++ Compiler. | |
40 | +#endif | |
41 | + | |
42 | +#ifdef _DEBUG | |
43 | + #include <crtdbg.h> | |
44 | +#endif | |
45 | + | |
46 | +#ifndef H_LAYERLEVEL | |
47 | + #define H_LAYERLEVEL 3 //!< Select include file. | |
48 | +#endif | |
49 | + | |
50 | +#pragma warning(disable:4996) //VC++警告防止 | |
51 | + | |
52 | +//定数 | |
53 | +#define GAMENAME "OpenXOPS" //!< ゲーム名 | |
54 | +#define GAMEVERSION "1.010" //!< ゲームのバージョン | |
55 | +#define GAMEFRAMEMS 30 //!< フレームあたりの処理時間(ms) | |
56 | +#define GAMEFPS (1000.0f/GAMEFRAMEMS) //!< FPS(フレームレート) 1000 / 30 = 33.333[FPS] | |
57 | +#define SCREEN_WIDTH 640 //!< スクリーンの幅 | |
58 | +#define SCREEN_HEIGHT 480 //!< スクリーンの高さ | |
59 | + | |
60 | +#define MAX_ADDONLIST 128 //!< ADDONを読み込む最大数 | |
61 | + | |
62 | +#define TOTAL_HAVEWEAPON 2 //!< 持てる武器の数 | |
63 | + | |
64 | +//システムのインクルードファイル | |
65 | +#define _USE_MATH_DEFINES //!< math.h 'M_PI' enable | |
66 | +#include <stdio.h> | |
67 | +#include <stdlib.h> | |
68 | +#include <math.h> | |
69 | + | |
70 | +//BorlandC++ Compiler用の処理 | |
71 | +#ifdef COMPILER_BCC | |
72 | + #define sqrtf(df) sqrt(df) | |
73 | + int _matherr(struct _exception *__e) { return 1; } | |
74 | +#endif | |
75 | + | |
76 | +#define SetFlag(value, bit) value = value | bit //!< ビットによるフラグ 設定 | |
77 | +#define DelFlag(value, bit) value = value & (~bit) //!< ビットによるフラグ 解除 | |
78 | +#define GetFlag(value, bit) (value & bit) //!< ビットによるフラグ 取得 | |
79 | + | |
80 | +//低レイヤー | |
81 | +#if H_LAYERLEVEL >= 1 | |
82 | + #include "window.h" | |
83 | + #include "config.h" | |
84 | + #include "datafile.h" | |
85 | + #include "d3dgraphics.h" | |
86 | + #include "input.h" | |
87 | + #include "sound.h" | |
88 | + #include "parameter.h" | |
89 | +#endif | |
90 | + | |
91 | +//中間レイヤー | |
92 | +#if H_LAYERLEVEL >= 2 | |
93 | + #include "resource.h" | |
94 | + #include "collision.h" | |
95 | + #include "object.h" | |
96 | + #include "soundmanager.h" | |
97 | +#endif | |
98 | + | |
99 | +//高レイヤー | |
100 | +#if H_LAYERLEVEL >= 3 | |
101 | + #include "objectmanager.h" | |
102 | + #include "scene.h" | |
103 | + #include "gamemain.h" | |
104 | + #include "ai.h" | |
105 | + #include "statemachine.h" | |
106 | + #include "event.h" | |
107 | +#endif | |
108 | + | |
109 | +//追加ライブラリ | |
110 | +// not .lib | |
111 | + | |
112 | +extern class StateMachine GameState; | |
113 | +extern class Config GameConfig; | |
114 | + | |
115 | +#endif | |
\ No newline at end of file |
@@ -0,0 +1,1863 @@ | ||
1 | +//! @file ai.cpp | |
2 | +//! @brief AIcontrolクラスの定義 | |
3 | + | |
4 | +//-------------------------------------------------------------------------------- | |
5 | +// | |
6 | +// OpenXOPS | |
7 | +// Copyright (c) 2014-2015, OpenXOPS Project / [-_-;](mikan) All rights reserved. | |
8 | +// | |
9 | +// Redistribution and use in source and binary forms, with or without | |
10 | +// modification, are permitted provided that the following conditions are met: | |
11 | +// * Redistributions of source code must retain the above copyright notice, | |
12 | +// this list of conditions and the following disclaimer. | |
13 | +// * Redistributions in binary form must reproduce the above copyright notice, | |
14 | +// this list of conditions and the following disclaimer in the documentation | |
15 | +// and/or other materials provided with the distribution. | |
16 | +// * Neither the name of the OpenXOPS Project nor the names of its contributors | |
17 | +// may be used to endorse or promote products derived from this software | |
18 | +// without specific prior written permission. | |
19 | +// | |
20 | +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
21 | +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
22 | +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
23 | +// DISCLAIMED. IN NO EVENT SHALL OpenXOPS Project BE LIABLE FOR ANY | |
24 | +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
25 | +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
26 | +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
27 | +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 | +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
29 | +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | +//-------------------------------------------------------------------------------- | |
31 | + | |
32 | +#include "ai.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +AIcontrol::AIcontrol(class ObjectManager *in_ObjMgr, int in_ctrlid, class BlockDataInterface *in_blocks, class PointDataInterface *in_Points, class ParameterInfo *in_Param, class Collision *in_CollD, class SoundManager *in_GameSound) | |
36 | +{ | |
37 | + ObjMgr = in_ObjMgr; | |
38 | + ctrlid = in_ctrlid; | |
39 | + ctrlhuman = in_ObjMgr->GeHumanObject(in_ctrlid); | |
40 | + blocks = in_blocks; | |
41 | + Points = in_Points; | |
42 | + Param = in_Param; | |
43 | + CollD = in_CollD; | |
44 | + GameSound = in_GameSound; | |
45 | + | |
46 | + battlemode = AI_NORMAL; | |
47 | + movemode = AI_WAIT; | |
48 | + target_pointid = -1; | |
49 | + target_posx = 0.0f; | |
50 | + target_posz = 0.0f; | |
51 | + target_rx = 0.0f; | |
52 | + total_move = 0.0f; | |
53 | + waitcnt = 0; | |
54 | + movejumpcnt = 1*((int)GAMEFPS); | |
55 | + gotocnt = 0; | |
56 | + moveturn_mode = 0; | |
57 | + longattack = false; | |
58 | +} | |
59 | + | |
60 | +//! @brief ディストラクタ | |
61 | +AIcontrol::~AIcontrol() | |
62 | +{} | |
63 | + | |
64 | +//! @brief 対象クラスを設定 | |
65 | +//! @attention この関数で設定を行わないと、クラス自体が正しく機能しません。 | |
66 | +void AIcontrol::SetClass(class ObjectManager *in_ObjMgr, int in_ctrlid, class BlockDataInterface *in_blocks, class PointDataInterface *in_Points, class ParameterInfo *in_Param, class Collision *in_CollD, class SoundManager *in_GameSound) | |
67 | +{ | |
68 | + ObjMgr = in_ObjMgr; | |
69 | + ctrlid = in_ctrlid; | |
70 | + ctrlhuman = in_ObjMgr->GeHumanObject(in_ctrlid); | |
71 | + blocks = in_blocks; | |
72 | + Points = in_Points; | |
73 | + Param = in_Param; | |
74 | + CollD = in_CollD; | |
75 | + GameSound = in_GameSound; | |
76 | +} | |
77 | + | |
78 | +//! @brief ランダムな整数値を返す | |
79 | +//! @param num 範囲 | |
80 | +//! @return 0〜num-1 | |
81 | +int AIcontrol::random(int num) | |
82 | +{ | |
83 | + return GetRand(num); | |
84 | +} | |
85 | + | |
86 | +//! @brief 人を検索 | |
87 | +//! @param in_p4 検索する人の第4パラメータ(認識番号) | |
88 | +//! @param out_x X座標を受け取るポインタ | |
89 | +//! @param out_z Z座標を受け取るポインタ | |
90 | +//! @return 成功:1 失敗:0 | |
91 | +int AIcontrol::SearchHumanPos(signed char in_p4, float *out_x, float *out_z) | |
92 | +{ | |
93 | + float x, z; | |
94 | + human* thuman; | |
95 | + | |
96 | + //人を検索してクラスを取得 | |
97 | + thuman = ObjMgr->SearchHuman(in_p4); | |
98 | + if( thuman == NULL ){ return 0; } | |
99 | + | |
100 | + //X・Z座標を取得 | |
101 | + thuman->GetPosData(&x, NULL, &z, NULL); | |
102 | + *out_x = x; | |
103 | + *out_z = z; | |
104 | + return 1; | |
105 | +} | |
106 | + | |
107 | +//! @brief 目標地点に移動しているか確認 | |
108 | +//! @return 到達:true 非到達:false | |
109 | +bool AIcontrol::CheckTargetPos() | |
110 | +{ | |
111 | + //距離を算出 | |
112 | + float x = posx - target_posx; | |
113 | + float z = posz - target_posz; | |
114 | + float r = x * x + z * z; | |
115 | + | |
116 | + if( movemode == AI_TRACKING ){ //追尾中なら | |
117 | + if( r < AI_ARRIVALDIST_TRACKING * AI_ARRIVALDIST_TRACKING ){ | |
118 | + return true; | |
119 | + } | |
120 | + } | |
121 | + else{ //それ以外なら | |
122 | + if( r < (AI_ARRIVALDIST_PATH * AI_ARRIVALDIST_PATH) ){ | |
123 | + return true; | |
124 | + } | |
125 | + } | |
126 | + | |
127 | + return false; | |
128 | +} | |
129 | + | |
130 | +//! @brief 目標地点を検索 | |
131 | +//! @param next 次を検索する | |
132 | +//! @return 完了:true 失敗:false | |
133 | +bool AIcontrol::SearchTarget(bool next) | |
134 | +{ | |
135 | + //ポイントの情報を取得 | |
136 | + pointdata pdata; | |
137 | + if( Points->Getdata(&pdata, target_pointid) != 0 ){ | |
138 | + movemode = AI_NULL; | |
139 | + return false; | |
140 | + } | |
141 | + | |
142 | + signed char nextpointp4; | |
143 | + | |
144 | + //次のポイントを検索するなら | |
145 | + if( next == true ){ | |
146 | + nextpointp4 = pdata.p3; | |
147 | + | |
148 | + //ランダムパス処理 | |
149 | + if( pdata.p1 == 8 ){ | |
150 | + if( random(2) == 0 ){ | |
151 | + nextpointp4 = pdata.p2; | |
152 | + } | |
153 | + else{ | |
154 | + nextpointp4 = pdata.p3; | |
155 | + } | |
156 | + movemode = AI_RANDOM; | |
157 | + } | |
158 | + | |
159 | + //ポイントを検索 | |
160 | + if( Points->SearchPointdata(&pdata, 0x08, 0, 0, 0, nextpointp4, 0) == 0 ){ | |
161 | + return false; | |
162 | + } | |
163 | + } | |
164 | + | |
165 | + //ランダムパスなら次へ | |
166 | + if( pdata.p1 == 8 ){ | |
167 | + target_pointid = pdata.id; | |
168 | + movemode = AI_RANDOM; | |
169 | + return false; | |
170 | + } | |
171 | + | |
172 | + //人なら座標を取得 | |
173 | + if( (pdata.p1 == 1)||(pdata.p1 == 6) ){ | |
174 | + SearchHumanPos(pdata.p4, &target_posx, &target_posz); | |
175 | + return true; | |
176 | + } | |
177 | + | |
178 | + //移動パスなら〜 | |
179 | + if( pdata.p1 == 3 ){ | |
180 | + //情報適用 | |
181 | + target_pointid = pdata.id; | |
182 | + target_posx = pdata.x; | |
183 | + target_posz = pdata.z; | |
184 | + target_rx = pdata.r; | |
185 | + | |
186 | + //移動ステート設定 | |
187 | + switch(pdata.p2){ | |
188 | + case 0: movemode = AI_WALK; break; | |
189 | + case 1: movemode = AI_RUN; break; | |
190 | + case 2: movemode = AI_WAIT; break; | |
191 | + case 3: | |
192 | + movemode = AI_TRACKING; | |
193 | + if( next == true ){ | |
194 | + nextpointp4 = pdata.p3; | |
195 | + | |
196 | + //ポイント(人)の情報を取得 | |
197 | + if( Points->SearchPointdata(&pdata, 0x08, 0, 0, 0, nextpointp4, 0) == 0 ){ | |
198 | + return false; | |
199 | + } | |
200 | + | |
201 | + //情報保存 | |
202 | + target_pointid = pdata.id; | |
203 | + target_posx = pdata.x; | |
204 | + target_posz = pdata.z; | |
205 | + } | |
206 | + break; | |
207 | + case 4: movemode = AI_WAIT; break; | |
208 | + case 5: movemode = AI_STOP; break; | |
209 | + case 6: movemode = AI_GRENADE; break; | |
210 | + case 7: movemode = AI_RUN2; break; | |
211 | + default: break; | |
212 | + } | |
213 | + return true; | |
214 | + } | |
215 | + | |
216 | + movemode = AI_NULL; | |
217 | + return false; | |
218 | +} | |
219 | + | |
220 | +//! @brief 目標地点に移動 | |
221 | +void AIcontrol::MoveTarget() | |
222 | +{ | |
223 | + float r, atan; | |
224 | + int paramid; | |
225 | + HumanParameter Paraminfo; | |
226 | + bool zombie; | |
227 | + | |
228 | + //ゾンビかどうか判定 | |
229 | + ctrlhuman->GetParamData(¶mid, NULL, NULL, NULL); | |
230 | + Param->GetHuman(paramid, &Paraminfo); | |
231 | + if( Paraminfo.type == 2 ){ | |
232 | + zombie = true; | |
233 | + } | |
234 | + else{ | |
235 | + zombie = false; | |
236 | + } | |
237 | + | |
238 | + //目標地点への角度を求める | |
239 | + CheckTargetAngle(posx, 0.0f, posz, rx*-1 + (float)M_PI/2, 0.0f, target_posx, 0.0f, target_posz, 0.0f, &atan, NULL, &r); | |
240 | + | |
241 | + //大きな差があれば少しづつ旋回するだけ | |
242 | + if( atan > AI_TURNRAD ){ | |
243 | + SetFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
244 | + } | |
245 | + if( atan < AI_TURNRAD*-1 ){ | |
246 | + SetFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
247 | + } | |
248 | + | |
249 | + //微々たる差なら一気に向く | |
250 | + if( abs(atan) <= AI_TURNRAD ){ | |
251 | + DelFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
252 | + DelFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
253 | + rx -= atan; | |
254 | + } | |
255 | + | |
256 | + //前進する | |
257 | + if( zombie == true ){ | |
258 | + if( abs(atan) < (float)M_PI/18*2 ){ | |
259 | + SetFlag(moveturn_mode, AI_CTRL_MOVEWALK); | |
260 | + } | |
261 | + } | |
262 | + else if( battlemode == AI_CAUTION ){ | |
263 | + if( abs(atan) < (float)M_PI/18*5 ){ | |
264 | + SetFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
265 | + } | |
266 | + } | |
267 | + else if( movemode == AI_WALK ){ | |
268 | + if( abs(atan) < (float)M_PI/180*6 ){ | |
269 | + SetFlag(moveturn_mode, AI_CTRL_MOVEWALK); | |
270 | + } | |
271 | + } | |
272 | + else if( (movemode == AI_RUN)||(movemode == AI_RUN2) ){ | |
273 | + if( abs(atan) < (float)M_PI/18*5 ){ | |
274 | + SetFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
275 | + } | |
276 | + } | |
277 | + else if( (movemode == AI_WAIT)||(movemode == AI_STOP) ){ | |
278 | + if( abs(atan) < (float)M_PI/180*6 ){ | |
279 | + SetFlag(moveturn_mode, AI_CTRL_MOVEWALK); | |
280 | + } | |
281 | + } | |
282 | + else{ //movemode == AI_TRACKING | |
283 | + if( abs(atan) < (float)M_PI/18*2 ){ | |
284 | + if( r < (AI_ARRIVALDIST_WALKTRACKING * AI_ARRIVALDIST_WALKTRACKING) ){ | |
285 | + SetFlag(moveturn_mode, AI_CTRL_MOVEWALK); | |
286 | + } | |
287 | + else{ | |
288 | + SetFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
289 | + } | |
290 | + } | |
291 | + } | |
292 | + | |
293 | + //ジャンプ | |
294 | + if( random(16) == 0 ){ | |
295 | + MoveJump(); | |
296 | + } | |
297 | + | |
298 | + //引っ掛かっていたら、左右への回転をランダムに行う | |
299 | + if( random(28) == 0 ){ | |
300 | + if( ctrlhuman->GetMovemode(true) != 0 ){ | |
301 | + if( ctrlhuman->GetTotalMove() - total_move < 0.1f ){ | |
302 | + if( random(2) == 0 ){ SetFlag(moveturn_mode, AI_CTRL_TURNRIGHT); } | |
303 | + else{ SetFlag(moveturn_mode, AI_CTRL_TURNLEFT); } | |
304 | + } | |
305 | + } | |
306 | + } | |
307 | + total_move = ctrlhuman->GetTotalMove(); | |
308 | +} | |
309 | + | |
310 | +//! @brief 目標地点に移動(優先的な走り用) | |
311 | +void AIcontrol::MoveTarget2() | |
312 | +{ | |
313 | + float atan; | |
314 | + | |
315 | + //目標地点への角度を求める | |
316 | + CheckTargetAngle(posx, 0.0f, posz, rx*-1 + (float)M_PI/2, 0.0f, target_posx, 0.0f, target_posz, 0.0f, &atan, NULL, NULL); | |
317 | + | |
318 | + //前後移動の処理 | |
319 | + if( abs(atan) < (float)M_PI/180*56 ){ | |
320 | + SetFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
321 | + } | |
322 | + if( abs(atan) > (float)M_PI/180*123.5f ){ | |
323 | + SetFlag(moveturn_mode, AI_CTRL_MOVEBACKWARD); | |
324 | + } | |
325 | + | |
326 | + //左右移動の処理 | |
327 | + if( ((float)M_PI/180*-146 < atan)&&(atan < (float)M_PI/180*-33) ){ | |
328 | + SetFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
329 | + } | |
330 | + if( ((float)M_PI/180*33 < atan)&&(atan < (float)M_PI/180*146) ){ | |
331 | + SetFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
332 | + } | |
333 | + | |
334 | + //ジャンプ | |
335 | + if( random(16) == 0 ){ | |
336 | + MoveJump(); | |
337 | + } | |
338 | + | |
339 | + //引っ掛かっていたら、左右への回転をランダムに行う | |
340 | + if( random(28) == 0 ){ | |
341 | + if( ctrlhuman->GetMovemode(true) != 0 ){ | |
342 | + if( ctrlhuman->GetTotalMove() - total_move < 0.1f ){ | |
343 | + if( random(2) == 0 ){ SetFlag(moveturn_mode, AI_CTRL_TURNRIGHT); } | |
344 | + else{ SetFlag(moveturn_mode, AI_CTRL_TURNLEFT); } | |
345 | + } | |
346 | + } | |
347 | + } | |
348 | + total_move = ctrlhuman->GetTotalMove(); | |
349 | +} | |
350 | + | |
351 | +//! @brief 前後左右ランダムに移動(攻撃中用) | |
352 | +void AIcontrol::MoveRandom() | |
353 | +{ | |
354 | + int forwardstart, backstart, sidestart; | |
355 | + | |
356 | + if( longattack == false ){ | |
357 | + forwardstart = 80; | |
358 | + backstart = 90; | |
359 | + sidestart = 70; | |
360 | + } | |
361 | + else{ | |
362 | + forwardstart = 120; | |
363 | + backstart = 150; | |
364 | + sidestart = 130; | |
365 | + } | |
366 | + | |
367 | + //ランダムに移動を始める | |
368 | + if( random(forwardstart) == 0 ){ | |
369 | + SetFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
370 | + } | |
371 | + if( random(backstart) == 0 ){ | |
372 | + SetFlag(moveturn_mode, AI_CTRL_MOVEBACKWARD); | |
373 | + } | |
374 | + if( random(sidestart) == 0 ){ | |
375 | + SetFlag(moveturn_mode, AI_CTRL_MOVELEFT); | |
376 | + } | |
377 | + if( random(sidestart) == 0 ){ | |
378 | + SetFlag(moveturn_mode, AI_CTRL_MOVERIGHT); | |
379 | + } | |
380 | + | |
381 | + // 1/3の確率か、移動フラグが設定されていたら | |
382 | + if( (random(3) == 0)||(GetFlag(moveturn_mode, (AI_CTRL_MOVEFORWARD | AI_CTRL_MOVEBACKWARD | AI_CTRL_MOVELEFT | AI_CTRL_MOVERIGHT))) ){ | |
383 | + float vx, vz; | |
384 | + float Dist; | |
385 | + | |
386 | + if( random(2) == 0 ){ | |
387 | + //前方向のベクトルを計算 | |
388 | + vx = cos(rx*-1 + (float)M_PI/2); | |
389 | + vz = sin(rx*-1 + (float)M_PI/2); | |
390 | + if( | |
391 | + (CollD->CheckALLBlockIntersectDummyRay(posx, posy + HUMAN_MAPCOLLISION_HEIGTH, posz, vx, 0, vz, NULL, NULL, &Dist, HUMAN_MAPCOLLISION_R) == true)|| //腰の高さにブロックがある(ぶつかる) | |
392 | + (CollD->CheckALLBlockIntersectDummyRay(posx, posy - 5.0f, posz, vx, 0, vz, NULL, NULL, &Dist, HUMAN_MAPCOLLISION_R) == false) //足元にブロックがない(落ちる) | |
393 | + ){ | |
394 | + //前進フラグを削除し、後退フラグを設定 | |
395 | + DelFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
396 | + SetFlag(moveturn_mode, AI_CTRL_MOVEBACKWARD); | |
397 | + } | |
398 | + | |
399 | + //後方向のベクトルを計算 | |
400 | + vx = cos(rx*-1 + (float)M_PI/2 + (float)M_PI); | |
401 | + vz = sin(rx*-1 + (float)M_PI/2 + (float)M_PI); | |
402 | + if( | |
403 | + (CollD->CheckALLBlockIntersectDummyRay(posx, posy + HUMAN_MAPCOLLISION_HEIGTH, posz, vx, 0, vz, NULL, NULL, &Dist, HUMAN_MAPCOLLISION_R) == true)|| //腰の高さにブロックがある(ぶつかる) | |
404 | + (CollD->CheckALLBlockIntersectDummyRay(posx, posy - 5.0f, posz, vx, 0, vz, NULL, NULL, &Dist, HUMAN_MAPCOLLISION_R) == false) //足元にブロックがない(落ちる) | |
405 | + ){ | |
406 | + //後退フラグを削除し、前進フラグを設定 | |
407 | + DelFlag(moveturn_mode, AI_CTRL_MOVEBACKWARD); | |
408 | + SetFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
409 | + } | |
410 | + } | |
411 | + else{ | |
412 | + // | |
413 | + vx = cos(rx*-1); | |
414 | + vz = sin(rx*-1); | |
415 | + if( | |
416 | + (CollD->CheckALLBlockIntersectDummyRay(posx, posy + HUMAN_MAPCOLLISION_HEIGTH, posz, vx, 0, vz, NULL, NULL, &Dist, HUMAN_MAPCOLLISION_R) == true)|| //腰の高さにブロックがある(ぶつかる) | |
417 | + (CollD->CheckALLBlockIntersectDummyRay(posx, posy - 5.0f, posz, vx, 0, vz, NULL, NULL, &Dist, HUMAN_MAPCOLLISION_R) == false) //足元にブロックがない(落ちる) | |
418 | + ){ | |
419 | + //右移動フラグを削除し、左移動フラグを設定 | |
420 | + DelFlag(moveturn_mode, AI_CTRL_MOVERIGHT); | |
421 | + SetFlag(moveturn_mode, AI_CTRL_MOVELEFT); | |
422 | + } | |
423 | + | |
424 | + vx = cos(rx*-1 + (float)M_PI); | |
425 | + vz = sin(rx*-1 + (float)M_PI); | |
426 | + if( | |
427 | + (CollD->CheckALLBlockIntersectDummyRay(posx, posy + HUMAN_MAPCOLLISION_HEIGTH, posz, vx, 0, vz, NULL, NULL, &Dist, HUMAN_MAPCOLLISION_R) == true)|| //腰の高さにブロックがある(ぶつかる) | |
428 | + (CollD->CheckALLBlockIntersectDummyRay(posx, posy - 5.0f, posz, vx, 0, vz, NULL, NULL, &Dist, HUMAN_MAPCOLLISION_R) == false) //足元にブロックがない(落ちる) | |
429 | + ){ | |
430 | + //左移動フラグを削除し、右移動フラグを設定 | |
431 | + DelFlag(moveturn_mode, AI_CTRL_MOVELEFT); | |
432 | + SetFlag(moveturn_mode, AI_CTRL_MOVERIGHT); | |
433 | + } | |
434 | + } | |
435 | + } | |
436 | + | |
437 | + //攻撃対象がいるなら | |
438 | + if( enemyhuman != NULL ){ | |
439 | + float tx, ty, tz; | |
440 | + | |
441 | + enemyhuman->GetPosData(&tx, &ty, &tz, NULL); | |
442 | + | |
443 | + float x = posx - tx; | |
444 | + float y = posy - ty; | |
445 | + float z = posz - tz; | |
446 | + float r = x * x + y * y + z * z; | |
447 | + | |
448 | + //敵に近づきすぎたなら後退する | |
449 | + if( r < 20.0f * 20.0f ){ | |
450 | + DelFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
451 | + if( random(70) == 0 ){ | |
452 | + SetFlag(moveturn_mode, AI_CTRL_MOVEBACKWARD); | |
453 | + } | |
454 | + } | |
455 | + } | |
456 | +} | |
457 | + | |
458 | +//! @brief その場を見まわす | |
459 | +void AIcontrol::TurnSeen() | |
460 | +{ | |
461 | + int turnstart, turnstop; | |
462 | + | |
463 | + //回転の開始・終了確率を設定 | |
464 | + if( battlemode == AI_ACTION ){ | |
465 | + return; | |
466 | + } | |
467 | + else if( battlemode == AI_CAUTION ){ | |
468 | + turnstart = 20; | |
469 | + turnstop = 20; | |
470 | + } | |
471 | + else{ | |
472 | + if( movemode == AI_TRACKING ){ turnstart = 65; } | |
473 | + else{ turnstart = 85; } | |
474 | + turnstop = 18; | |
475 | + } | |
476 | + | |
477 | + //ランダムに回転を始める | |
478 | + if( random(turnstart) == 0 ){ | |
479 | + SetFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
480 | + } | |
481 | + if( random(turnstart) == 0 ){ | |
482 | + SetFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
483 | + } | |
484 | + | |
485 | + if( (battlemode == AI_NORMAL)&&(movemode == AI_WAIT) ){ | |
486 | + //ランダムにポイントの方を向こうとする | |
487 | + //「ポイントの方向を少し重視する」の再現 | |
488 | + if( random(80) == 0 ){ | |
489 | + float tr; | |
490 | + tr = target_rx - rx; | |
491 | + for(; tr > (float)M_PI; tr -= (float)M_PI*2){} | |
492 | + for(; tr < (float)M_PI*-1; tr += (float)M_PI*2){} | |
493 | + | |
494 | + if( tr > 0.0f ){ | |
495 | + SetFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
496 | + } | |
497 | + if( tr < 0.0f ){ | |
498 | + SetFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
499 | + } | |
500 | + } | |
501 | + } | |
502 | + | |
503 | + //回転をランダムに止める | |
504 | + if( random(turnstop) == 0 ){ | |
505 | + DelFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
506 | + } | |
507 | + if( random(turnstop) == 0 ){ | |
508 | + DelFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
509 | + } | |
510 | +} | |
511 | + | |
512 | +//! @brief 特定の方向を見続ける | |
513 | +bool AIcontrol::StopSeen() | |
514 | +{ | |
515 | + float tr; | |
516 | + bool returnflag = false; | |
517 | + | |
518 | + tr = target_rx - rx; | |
519 | + for(; tr > (float)M_PI; tr -= (float)M_PI*2){} | |
520 | + for(; tr < (float)M_PI*-1; tr += (float)M_PI*2){} | |
521 | + | |
522 | + //大きな差があれば少しづつ旋回するだけ | |
523 | + if( tr > AI_TURNRAD ){ | |
524 | + SetFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
525 | + returnflag = false; | |
526 | + } | |
527 | + if( tr < AI_TURNRAD*-1 ){ | |
528 | + SetFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
529 | + returnflag = false; | |
530 | + } | |
531 | + | |
532 | + //微々たる差なら一気に向ける。 | |
533 | + if( abs(tr) <= AI_TURNRAD ){ | |
534 | + DelFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
535 | + DelFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
536 | + rx += tr; | |
537 | + returnflag = true; | |
538 | + } | |
539 | + | |
540 | + return returnflag; | |
541 | +} | |
542 | + | |
543 | +//! @brief 進行方向に障害物があればジャンプする | |
544 | +bool AIcontrol::MoveJump() | |
545 | +{ | |
546 | + //立ち止まっていれば処理しない | |
547 | + if( ctrlhuman->GetMovemode(false) == 0 ){ return false; } | |
548 | + | |
549 | + float dist_dummy; | |
550 | + | |
551 | + float new_posx, new_posy, new_posz; | |
552 | + | |
553 | + //腰付近のあたり判定 | |
554 | + new_posx = posx + cos(rx*-1 + (float)M_PI/2) * (AI_CHECKJUMP_DIST + HUMAN_MAPCOLLISION_R); | |
555 | + new_posy = posy + HUMAN_MAPCOLLISION_HEIGTH; | |
556 | + new_posz = posz + sin(rx*-1 + (float)M_PI/2) * (AI_CHECKJUMP_DIST + HUMAN_MAPCOLLISION_R); | |
557 | + if( CollD->CheckALLBlockInside(new_posx, new_posy, new_posz) == true ){ | |
558 | + ObjMgr->MoveJump(ctrlid); | |
559 | + return true; | |
560 | + } | |
561 | + | |
562 | + //体全体のあたり判定 | |
563 | + new_posx = posx + cos(rx*-1 + (float)M_PI/2) * AI_CHECKJUMP_DIST; | |
564 | + new_posy = posy + AI_CHECKJUMP_HEIGHT; | |
565 | + new_posz = posz + sin(rx*-1 + (float)M_PI/2) * AI_CHECKJUMP_DIST; | |
566 | + if( CollD->CheckALLBlockInside(new_posx, new_posy, new_posz) == true ){ | |
567 | + ObjMgr->MoveJump(ctrlid); | |
568 | + return true; | |
569 | + } | |
570 | + else if( CollD->CheckALLBlockIntersectRay(new_posx, new_posy, new_posz, 0.0f, 1.0f, 0.0f, NULL, NULL, &dist_dummy, HUMAN_HEIGTH - AI_CHECKJUMP_HEIGHT) == true ){ | |
571 | + ObjMgr->MoveJump(ctrlid); | |
572 | + return true; | |
573 | + } | |
574 | + | |
575 | + return false; | |
576 | +} | |
577 | + | |
578 | +//! @brief 攻撃 | |
579 | +//! @todo ゾンビの相手を捕まえる処理 | |
580 | +void AIcontrol::Action() | |
581 | +{ | |
582 | + human* EnemyHuman = NULL; | |
583 | + int paramid; | |
584 | + HumanParameter Paraminfo; | |
585 | + bool zombie; | |
586 | + float posy2; | |
587 | + float tx, ty, tz; | |
588 | + | |
589 | + EnemyHuman = enemyhuman; | |
590 | + | |
591 | + //座標を取得 | |
592 | + EnemyHuman->GetPosData(&tx, &ty, &tz, NULL); | |
593 | + posy2 = posy + VIEW_HEIGHT; | |
594 | + ty += VIEW_HEIGHT; | |
595 | + | |
596 | + //ゾンビかどうか判定 | |
597 | + ctrlhuman->GetParamData(¶mid, NULL, NULL, NULL); | |
598 | + Param->GetHuman(paramid, &Paraminfo); | |
599 | + if( Paraminfo.type == 2 ){ | |
600 | + zombie = true; | |
601 | + } | |
602 | + else{ | |
603 | + zombie = false; | |
604 | + } | |
605 | + | |
606 | + //所持している武器の種類を取得 | |
607 | + int weaponid = ctrlhuman->GetMainWeaponTypeNO(); | |
608 | + | |
609 | + float atanx, atany, r; | |
610 | + | |
611 | + //自分が手榴弾を持っていれば〜 | |
612 | + if( weaponid == ID_WEAPON_GRENADE ){ | |
613 | + if( zombie == false ){ | |
614 | + float x = posx - tx; | |
615 | + float z = posz - tz; | |
616 | + float r = x * x + z * z; | |
617 | + float scale; | |
618 | + if( longattack == false ){ scale = 0.12f; } | |
619 | + else{ scale = 0.4f; } | |
620 | + | |
621 | + //距離に応じて高さを変える | |
622 | + ty += (sqrt(r) - 200.0f) * scale; | |
623 | + } | |
624 | + } | |
625 | + else{ | |
626 | + float mx, mz; | |
627 | + float scale; | |
628 | + EnemyHuman->GetMovePos(&mx, NULL, &mz); | |
629 | + if( longattack == false ){ scale = 1.5f; } | |
630 | + else{ scale = 0.12f; } | |
631 | + | |
632 | + //敵の移動を見超す | |
633 | + tx += mx * scale; | |
634 | + tz += mz * scale; | |
635 | + } | |
636 | + | |
637 | + //目標地点への角度を求める | |
638 | + CheckTargetAngle(posx, posy2, posz, rx*-1 + (float)M_PI/2, ry, tx, ty, tz, 0.0f, &atanx, &atany, &r); | |
639 | + | |
640 | + //大きな差があれば少しづつ旋回するだけ | |
641 | + if( atanx > AI_TURNRAD ){ | |
642 | + SetFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
643 | + } | |
644 | + if( atanx < AI_TURNRAD*-1 ){ | |
645 | + SetFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
646 | + } | |
647 | + | |
648 | + //微々たる差なら一気に向ける | |
649 | + if( abs(atanx) <= AI_TURNRAD ){ | |
650 | + DelFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
651 | + DelFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
652 | + rx -= atanx; | |
653 | + rx += (float)M_PI/180 * (random(5) - 2); | |
654 | + } | |
655 | + | |
656 | + //腕の角度 | |
657 | + if( zombie == true ){ | |
658 | + //ry = 0.0f; | |
659 | + | |
660 | + //大きな差があれば少しづつ旋回するだけ | |
661 | + if( ry < AI_TURNRAD*-1 ){ | |
662 | + SetFlag(moveturn_mode, AI_CTRL_TURNUP); | |
663 | + } | |
664 | + if( ry > AI_TURNRAD ){ | |
665 | + SetFlag(moveturn_mode, AI_CTRL_TURNDOWN); | |
666 | + } | |
667 | + | |
668 | + //微々たる差なら一気に向ける | |
669 | + if( abs(ry) <= AI_TURNRAD ){ | |
670 | + DelFlag(moveturn_mode, AI_CTRL_TURNUP); | |
671 | + DelFlag(moveturn_mode, AI_CTRL_TURNDOWN); | |
672 | + ry = 0.0f; | |
673 | + } | |
674 | + } | |
675 | + else{ | |
676 | + float addry; | |
677 | + | |
678 | + //自分が手ぶらならば〜 | |
679 | + if( weaponid == ID_WEAPON_NONE ){ | |
680 | + if( EnemyHuman->GetMainWeaponTypeNO() == ID_WEAPON_NONE ){ //敵も手ぶらならば〜 | |
681 | + addry = ARMRAD_NOWEAPON - ry; | |
682 | + } | |
683 | + else{ //敵が武器を持っていれば〜 | |
684 | + addry = (float)M_PI/18*8 - ry; | |
685 | + } | |
686 | + } | |
687 | + else{ | |
688 | + addry = atany; | |
689 | + } | |
690 | + | |
691 | + //大きな差があれば少しづつ旋回するだけ | |
692 | + if( addry > AI_TURNRAD ){ | |
693 | + SetFlag(moveturn_mode, AI_CTRL_TURNUP); | |
694 | + } | |
695 | + if( addry < AI_TURNRAD*-1 ){ | |
696 | + SetFlag(moveturn_mode, AI_CTRL_TURNDOWN); | |
697 | + } | |
698 | + | |
699 | + //微々たる差なら一気に向ける | |
700 | + if( abs(addry) <= AI_TURNRAD ){ | |
701 | + DelFlag(moveturn_mode, AI_CTRL_TURNUP); | |
702 | + DelFlag(moveturn_mode, AI_CTRL_TURNDOWN); | |
703 | + ry += addry; | |
704 | + ry += (float)M_PI/180 * (random(5) - 2); | |
705 | + } | |
706 | + } | |
707 | + | |
708 | + //ゾンビ以外で手ぶらならば | |
709 | + if( zombie == false ){ | |
710 | + if( weaponid == ID_WEAPON_NONE ){ | |
711 | + //一定の確率で後退する | |
712 | + if( random(80) == 0 ){ | |
713 | + SetFlag(moveturn_mode, AI_CTRL_MOVEBACKWARD); | |
714 | + } | |
715 | + } | |
716 | + } | |
717 | + | |
718 | + | |
719 | + if( zombie == true ){ //ゾンビの攻撃 | |
720 | + float y = posy2 - ty; | |
721 | + | |
722 | + //もし走っていれば、一度歩きに切り替える | |
723 | + if( GetFlag(moveturn_mode, AI_CTRL_MOVEFORWARD) ){ | |
724 | + DelFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
725 | + SetFlag(moveturn_mode, AI_CTRL_MOVEWALK); | |
726 | + } | |
727 | + | |
728 | + //敵に向かって前進する | |
729 | + if( abs(atanx) <= (float)M_PI/180*25 ){ | |
730 | + if( (abs(atanx) <= (float)M_PI/180*15) && (r < 24.0f*24.0f) && (actioncnt%50 > 20) ){ | |
731 | + //歩きを取り消し、走る | |
732 | + SetFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
733 | + DelFlag(moveturn_mode, AI_CTRL_MOVEWALK); | |
734 | + } | |
735 | + else{ | |
736 | + SetFlag(moveturn_mode, AI_CTRL_MOVEWALK); | |
737 | + } | |
738 | + } | |
739 | + | |
740 | + /* | |
741 | + //ジャンプ | |
742 | + if( random(16) == 0 ){ | |
743 | + MoveJump(); | |
744 | + } | |
745 | + */ | |
746 | + | |
747 | + if( (r < 9.0f*9.0f)&&( abs(y) < 10.0f) ){ | |
748 | + float x = posx - tx; | |
749 | + float z = posz - tz; | |
750 | + | |
751 | + //捕まえる (敵を引き付ける) | |
752 | + EnemyHuman->AddPosOrder(atan2(z, x), 0.0f, 0.5f); | |
753 | + | |
754 | + //敵の視点をランダムに動かす | |
755 | + float erx, ery; | |
756 | + EnemyHuman->GetRxRy(&erx, &ery); | |
757 | + switch(random(3)){ | |
758 | + case 0: erx -= (float)M_PI/180*2; break; | |
759 | + case 1: erx += (float)M_PI/180*2; break; | |
760 | + default: break; | |
761 | + } | |
762 | + switch(random(3)){ | |
763 | + case 0: ery -= (float)M_PI/180*2; break; | |
764 | + case 1: ery += (float)M_PI/180*2; break; | |
765 | + default: break; | |
766 | + } | |
767 | + EnemyHuman->SetRxRy(erx, ery); | |
768 | + } | |
769 | + | |
770 | + if( actioncnt%50 == 0){ | |
771 | + if( ObjMgr->CheckZombieAttack(ctrlhuman, EnemyHuman) == true ){ | |
772 | + ObjMgr->HitZombieAttack(EnemyHuman); | |
773 | + } | |
774 | + } | |
775 | + } | |
776 | + else{ //発砲する | |
777 | + float ShotAngle; | |
778 | + if( longattack == false ){ | |
779 | + //敵を捉えたと判定する、許容誤差を計算する | |
780 | + ShotAngle = (float)M_PI/180*8; | |
781 | + if( weaponid != ID_WEAPON_NONE ){ | |
782 | + WeaponParameter wparam; | |
783 | + Param->GetWeapon(weaponid, &wparam); | |
784 | + if( wparam.scopemode == 1 ){ | |
785 | + ShotAngle = (float)M_PI/180*6; | |
786 | + } | |
787 | + if( wparam.scopemode == 2 ){ | |
788 | + ShotAngle = (float)M_PI/180*4; | |
789 | + } | |
790 | + } | |
791 | + | |
792 | + //AIレベルごとに調整 | |
793 | + ShotAngle += (float)M_PI/180*0.5f * LevelParam->limitserror; | |
794 | + | |
795 | + if( movemode == AI_RUN2 ){ | |
796 | + ShotAngle *= 1.5f; | |
797 | + } | |
798 | + } | |
799 | + else{ | |
800 | + //敵を捉えたと判定する、許容誤差を計算する | |
801 | + ShotAngle = (float)M_PI/180*4; | |
802 | + if( weaponid != ID_WEAPON_NONE ){ | |
803 | + WeaponParameter wparam; | |
804 | + Param->GetWeapon(weaponid, &wparam); | |
805 | + if( wparam.scopemode == 1 ){ | |
806 | + ShotAngle = (float)M_PI/180*3; | |
807 | + } | |
808 | + if( wparam.scopemode == 2 ){ | |
809 | + ShotAngle = (float)M_PI/180*2; | |
810 | + } | |
811 | + } | |
812 | + | |
813 | + //AIレベルごとに調整 | |
814 | + ShotAngle += (float)M_PI/180*0.2f * LevelParam->limitserror; | |
815 | + } | |
816 | + | |
817 | + //敵を捉えていれば | |
818 | + float atanxy = atanx + atany; | |
819 | + if( atanxy < ShotAngle ){ | |
820 | + int rand = LevelParam->attack; | |
821 | + if( longattack == true ){ rand += 1; } | |
822 | + | |
823 | + //発砲 | |
824 | + if( random(rand) == 0 ){ | |
825 | + ObjMgr->ShotWeapon(ctrlid); | |
826 | + } | |
827 | + } | |
828 | + } | |
829 | + | |
830 | + //距離に応じて近距離・遠距離を切り替える | |
831 | + // 200.0fピッタリで設定値維持 | |
832 | + if( r < 200.0f * 200.0f ){ | |
833 | + longattack = false; | |
834 | + } | |
835 | + if( (r > 200.0f * 200.0f)&&(movemode != AI_RUN2) ){ | |
836 | + longattack = true; | |
837 | + } | |
838 | + | |
839 | + if( zombie == false ){ | |
840 | + //ランダムに移動 | |
841 | + MoveRandom(); | |
842 | + } | |
843 | + | |
844 | + actioncnt += 1; | |
845 | +} | |
846 | + | |
847 | +//! @brief 攻撃をキャンセル | |
848 | +bool AIcontrol::ActionCancel() | |
849 | +{ | |
850 | + //非戦闘化フラグが有効なら終了 | |
851 | + if( NoFight == true ){ | |
852 | + return true; | |
853 | + } | |
854 | + | |
855 | + //敵が死亡したら終了 | |
856 | + if( enemyhuman->GetDeadFlag() == true ){ | |
857 | + return true; | |
858 | + } | |
859 | + | |
860 | + //距離を取得 | |
861 | + float tx, ty, tz; | |
862 | + enemyhuman->GetPosData(&tx, &ty, &tz, NULL); | |
863 | + float x = posx - tx; | |
864 | + float y = posy - ty; | |
865 | + float z = posz - tz; | |
866 | + float r = x*x + y*y + z*z; | |
867 | + | |
868 | + //距離が離れ過ぎていたら終了 | |
869 | + if( r > 620.0f*620.0f ){ | |
870 | + return true; | |
871 | + } | |
872 | + | |
873 | + if( longattack == false ){ | |
874 | + //適当なタイミングで敵が見えるか確認 | |
875 | + if( random(40) == 0 ){ | |
876 | + //ブロックが遮っていた(=見えない)ならば終了 | |
877 | + if( CheckLookEnemy(enemyhuman, AI_SEARCH_RX, AI_SEARCH_RY, 620.0f, NULL) == false ){ | |
878 | + return true; | |
879 | + } | |
880 | + } | |
881 | + | |
882 | + //強制的に終了 | |
883 | + if( random(550) == 0 ){ | |
884 | + return true; | |
885 | + } | |
886 | + } | |
887 | + else{ | |
888 | + //適当なタイミングで敵が見えるか確認 | |
889 | + if( random(30) == 0 ){ | |
890 | + //ブロックが遮っていた(=見えない)ならば終了 | |
891 | + if( CheckLookEnemy(enemyhuman, AI_SEARCH_RX, AI_SEARCH_RY, 620.0f, NULL) == false ){ | |
892 | + return true; | |
893 | + } | |
894 | + } | |
895 | + | |
896 | + //強制的に終了 | |
897 | + if( random(450) == 0 ){ | |
898 | + return true; | |
899 | + } | |
900 | + } | |
901 | + | |
902 | + return false; | |
903 | +} | |
904 | + | |
905 | +//! @brief 武器を持つ | |
906 | +int AIcontrol::HaveWeapon() | |
907 | +{ | |
908 | + int selectweapon; | |
909 | + class weapon *weapon[TOTAL_HAVEWEAPON]; | |
910 | + int weaponid; | |
911 | + | |
912 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
913 | + weapon[i] = NULL; | |
914 | + } | |
915 | + | |
916 | + //武器の情報を取得 | |
917 | + ctrlhuman->GetWeapon(&selectweapon, weapon); | |
918 | + | |
919 | + //武器を持っていれば、武器番号を取得 | |
920 | + if( weapon[selectweapon] != NULL ){ | |
921 | + weapon[selectweapon]->GetParamData(&weaponid, NULL, NULL); | |
922 | + } | |
923 | + | |
924 | + //武器を持っていないか、「ケース」ならば | |
925 | + if( (weapon[selectweapon] == NULL)||(weaponid == ID_WEAPON_CASE) ){ | |
926 | + //次の武器を指定 | |
927 | + int notselectweapon = selectweapon + 1; | |
928 | + if( notselectweapon == TOTAL_HAVEWEAPON ){ notselectweapon = 0; } | |
929 | + | |
930 | + //持ち替える | |
931 | + if( weapon[notselectweapon] != NULL ){ | |
932 | + ObjMgr->ChangeWeapon(ctrlid); | |
933 | + return 1; | |
934 | + } | |
935 | + } | |
936 | + | |
937 | + return 0; | |
938 | +} | |
939 | + | |
940 | +//! @brief 移動や方向転換をランダムに終了 | |
941 | +void AIcontrol::CancelMoveTurn() | |
942 | +{ | |
943 | + int forward, back, side, updown, rightleft; | |
944 | + | |
945 | + if( battlemode == AI_ACTION ){ //攻撃中 | |
946 | + if( movemode == AI_RUN2 ){ //優先的な走り | |
947 | + DelFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
948 | + DelFlag(moveturn_mode, AI_CTRL_MOVEBACKWARD); | |
949 | + DelFlag(moveturn_mode, AI_CTRL_MOVELEFT); | |
950 | + DelFlag(moveturn_mode, AI_CTRL_MOVERIGHT); | |
951 | + DelFlag(moveturn_mode, AI_CTRL_TURNUP); | |
952 | + DelFlag(moveturn_mode, AI_CTRL_TURNDOWN); | |
953 | + DelFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
954 | + DelFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
955 | + if( random(3) == 0 ){ | |
956 | + DelFlag(moveturn_mode, AI_CTRL_MOVEWALK); | |
957 | + } | |
958 | + return; | |
959 | + } | |
960 | + else{ //優先的な走り 以外 | |
961 | + if( longattack == false ){ | |
962 | + forward = 6; | |
963 | + back = 6; | |
964 | + side = 7; | |
965 | + updown = 5; | |
966 | + rightleft = 6; | |
967 | + } | |
968 | + else{ | |
969 | + forward = 5; | |
970 | + back = 4; | |
971 | + side = 5; | |
972 | + updown = 3; | |
973 | + rightleft = 3; | |
974 | + } | |
975 | + } | |
976 | + } | |
977 | + else if( battlemode == AI_CAUTION ){ //警戒中 | |
978 | + forward = 10; | |
979 | + back = 10; | |
980 | + side = 10; | |
981 | + updown = 14; | |
982 | + rightleft = 20; | |
983 | + } | |
984 | + else{ | |
985 | + forward = 12; | |
986 | + back = 12; | |
987 | + side = 12; | |
988 | + updown = 15; | |
989 | + rightleft = 18; | |
990 | + } | |
991 | + | |
992 | + //移動をランダムに止める | |
993 | + if( random(forward) == 0 ){ | |
994 | + DelFlag(moveturn_mode, AI_CTRL_MOVEFORWARD); | |
995 | + } | |
996 | + if( random(back) == 0 ){ | |
997 | + DelFlag(moveturn_mode, AI_CTRL_MOVEBACKWARD); | |
998 | + } | |
999 | + if( random(side) == 0 ){ | |
1000 | + DelFlag(moveturn_mode, AI_CTRL_MOVELEFT); | |
1001 | + } | |
1002 | + if( random(side) == 0 ){ | |
1003 | + DelFlag(moveturn_mode, AI_CTRL_MOVERIGHT); | |
1004 | + } | |
1005 | + if( random(3) == 0 ){ | |
1006 | + DelFlag(moveturn_mode, AI_CTRL_MOVEWALK); | |
1007 | + } | |
1008 | + | |
1009 | + //回転をランダムに止める | |
1010 | + if( random(updown) == 0 ){ | |
1011 | + DelFlag(moveturn_mode, AI_CTRL_TURNUP); | |
1012 | + } | |
1013 | + if( random(updown) == 0 ){ | |
1014 | + DelFlag(moveturn_mode, AI_CTRL_TURNDOWN); | |
1015 | + } | |
1016 | + if( random(rightleft) == 0 ){ | |
1017 | + DelFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
1018 | + } | |
1019 | + if( random(rightleft) == 0 ){ | |
1020 | + DelFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
1021 | + } | |
1022 | +} | |
1023 | + | |
1024 | +//! @brief 移動や方向転換を実行 | |
1025 | +void AIcontrol::ControlMoveTurn() | |
1026 | +{ | |
1027 | + //移動の実行 | |
1028 | + if( GetFlag(moveturn_mode, AI_CTRL_MOVEFORWARD) ){ | |
1029 | + ObjMgr->MoveForward(ctrlid); | |
1030 | + } | |
1031 | + if( GetFlag(moveturn_mode, AI_CTRL_MOVEBACKWARD) ){ | |
1032 | + ObjMgr->MoveBack(ctrlid); | |
1033 | + } | |
1034 | + if( GetFlag(moveturn_mode, AI_CTRL_MOVELEFT) ){ | |
1035 | + ObjMgr->MoveLeft(ctrlid); | |
1036 | + } | |
1037 | + if( GetFlag(moveturn_mode, AI_CTRL_MOVERIGHT) ){ | |
1038 | + ObjMgr->MoveRight(ctrlid); | |
1039 | + } | |
1040 | + if( GetFlag(moveturn_mode, AI_CTRL_MOVEWALK) ){ | |
1041 | + ObjMgr->MoveWalk(ctrlid); | |
1042 | + } | |
1043 | + | |
1044 | + //方向転換の実行 | |
1045 | + if( GetFlag(moveturn_mode, AI_CTRL_TURNUP) ){ | |
1046 | + ry += AI_TURNRAD; | |
1047 | + } | |
1048 | + if( GetFlag(moveturn_mode, AI_CTRL_TURNDOWN) ){ | |
1049 | + ry -= AI_TURNRAD; | |
1050 | + } | |
1051 | + if( GetFlag(moveturn_mode, AI_CTRL_TURNLEFT) ){ | |
1052 | + rx -= AI_TURNRAD; | |
1053 | + } | |
1054 | + if( GetFlag(moveturn_mode, AI_CTRL_TURNRIGHT) ){ | |
1055 | + rx += AI_TURNRAD; | |
1056 | + } | |
1057 | +} | |
1058 | + | |
1059 | +//! @brief 武器をリロード・捨てる | |
1060 | +//! @return 捨てる:1 リロード:2 持ち替える:3 FULL/SEMI切り替え:4 何もしない:0 | |
1061 | +int AIcontrol::ControlWeapon() | |
1062 | +{ | |
1063 | + int selectweapon; | |
1064 | + class weapon *weapon[TOTAL_HAVEWEAPON]; | |
1065 | + int weaponid, lnbs, nbs; | |
1066 | + WeaponParameter paramdata; | |
1067 | + bool blazingmodeS, blazingmodeN; | |
1068 | + | |
1069 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
1070 | + weapon[i] = NULL; | |
1071 | + } | |
1072 | + | |
1073 | + //武器の情報を取得 | |
1074 | + ctrlhuman->GetWeapon(&selectweapon, weapon); | |
1075 | + if( weapon[selectweapon] == NULL ){ return 0; } | |
1076 | + weapon[selectweapon]->GetParamData(&weaponid, &lnbs, &nbs); | |
1077 | + | |
1078 | + //武器の性能を取得 | |
1079 | + if( Param->GetWeapon(weaponid, ¶mdata) == 1 ){ return 0; } | |
1080 | + | |
1081 | + //スコープ解除 | |
1082 | + ctrlhuman->SetDisableScope(); | |
1083 | + | |
1084 | + //「ケース」なら何もしない | |
1085 | + if( weaponid == ID_WEAPON_CASE ){ return 0; } | |
1086 | + | |
1087 | + //戦闘中にグレネードを持っていれば | |
1088 | + if( battlemode == AI_ACTION ){ | |
1089 | + if( weaponid == ID_WEAPON_GRENADE ){ | |
1090 | + int nextselectweapon, nextnds; | |
1091 | + | |
1092 | + //次の武器の弾数を取得 | |
1093 | + nextselectweapon = selectweapon + 1; | |
1094 | + nextnds = 0; | |
1095 | + if( nextselectweapon == TOTAL_HAVEWEAPON ){ | |
1096 | + nextselectweapon = 0; | |
1097 | + } | |
1098 | + if( weapon[nextselectweapon] != NULL ){ | |
1099 | + weapon[nextselectweapon]->GetParamData(NULL, NULL, &nextnds); | |
1100 | + } | |
1101 | + | |
1102 | + if( longattack == false ){ | |
1103 | + // 1/100の確率で持ち替える | |
1104 | + if( (random(100) == 0)&&(nextnds > 0) ){ | |
1105 | + ObjMgr->ChangeWeapon(ctrlid); | |
1106 | + return 3; | |
1107 | + } | |
1108 | + } | |
1109 | + else{ | |
1110 | + // 1/66の確率で持ち替える | |
1111 | + if( (random(66) == 0)&&(nextnds > 0) ){ | |
1112 | + ObjMgr->ChangeWeapon(ctrlid); | |
1113 | + return 3; | |
1114 | + } | |
1115 | + } | |
1116 | + } | |
1117 | + } | |
1118 | + | |
1119 | + //残弾数が無ければ | |
1120 | + if( lnbs == 0 ){ | |
1121 | + int ways; | |
1122 | + | |
1123 | + //処理確率決定 | |
1124 | + if( battlemode == AI_NORMAL ){ ways = 1; } | |
1125 | + else if( battlemode == AI_CAUTION ){ ways = 10; } | |
1126 | + else{ ways = 8; } | |
1127 | + | |
1128 | + // 1/waysの確率で処理 | |
1129 | + if( random(ways) == 0 ){ | |
1130 | + int under; | |
1131 | + | |
1132 | + //リロード確率 | |
1133 | + if( battlemode == AI_NORMAL ){ | |
1134 | + ways = 1; | |
1135 | + under = 0; | |
1136 | + } | |
1137 | + else if( battlemode == AI_CAUTION ){ | |
1138 | + ways = 5; | |
1139 | + under = 3; | |
1140 | + } | |
1141 | + else{ | |
1142 | + if( longattack == false ){ | |
1143 | + // 確率は 3/4 | |
1144 | + ways = 4; | |
1145 | + under = 2; | |
1146 | + } | |
1147 | + else{ | |
1148 | + // 確率は 2/3 | |
1149 | + ways = 3; | |
1150 | + under = 1; | |
1151 | + } | |
1152 | + } | |
1153 | + | |
1154 | + //弾が無ければ捨てる | |
1155 | + if( nbs == 0 ){ | |
1156 | + ObjMgr->DumpWeapon(ctrlid); | |
1157 | + return 1; | |
1158 | + } | |
1159 | + | |
1160 | + //ランダムに リロード実行 or 武器を持ちかえ | |
1161 | + if( random(ways) <= under ){ | |
1162 | + ObjMgr->ReloadWeapon(ctrlid); | |
1163 | + return 2; | |
1164 | + } | |
1165 | + //else{ | |
1166 | + ObjMgr->ChangeWeapon(ctrlid); | |
1167 | + return 3; | |
1168 | + //} | |
1169 | + } | |
1170 | + } | |
1171 | + | |
1172 | + //連射切り替えが可能な武器なら | |
1173 | + if( paramdata.ChangeWeapon != -1 ){ | |
1174 | + //現在の武器の連射設定を取得 | |
1175 | + blazingmodeS = paramdata.blazingmode; | |
1176 | + | |
1177 | + //新たな武器の連射設定を取得 | |
1178 | + if( Param->GetWeapon(paramdata.ChangeWeapon, ¶mdata) == 1 ){ return 0; } | |
1179 | + blazingmodeN = paramdata.blazingmode; | |
1180 | + | |
1181 | + if( longattack == false ){ | |
1182 | + //近距離攻撃中で、現在SEMI・切り替えるとFULLになるなら | |
1183 | + if( (blazingmodeS == false)||(blazingmodeN == true) ){ | |
1184 | + ObjMgr->ChangeShotMode(ctrlid); //切り替える | |
1185 | + return 4; | |
1186 | + } | |
1187 | + } | |
1188 | + else{ | |
1189 | + //遠距離攻撃中で、現在FULL・切り替えるとSEMIになるなら | |
1190 | + if( (blazingmodeS == true)||(blazingmodeN == false) ){ | |
1191 | + ObjMgr->ChangeShotMode(ctrlid); //切り替える | |
1192 | + return 4; | |
1193 | + } | |
1194 | + } | |
1195 | + } | |
1196 | + | |
1197 | + return 0; | |
1198 | +} | |
1199 | + | |
1200 | +//! @brief 手榴弾を投げる | |
1201 | +//! @return 処理中:0 投げ終わった:1 手榴弾を持っていない:2 | |
1202 | +int AIcontrol::ThrowGrenade() | |
1203 | +{ | |
1204 | + int selectweapon; | |
1205 | + class weapon *weapon[TOTAL_HAVEWEAPON]; | |
1206 | + int weaponid, nbs, i; | |
1207 | + | |
1208 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
1209 | + weapon[i] = NULL; | |
1210 | + } | |
1211 | + | |
1212 | + //手榴弾を持っているか確認 | |
1213 | + ctrlhuman->GetWeapon(&selectweapon, weapon); | |
1214 | + for(i=0; i<TOTAL_HAVEWEAPON; i++){ | |
1215 | + if( weapon[i] != NULL ){ | |
1216 | + weapon[i]->GetParamData(&weaponid, NULL, &nbs); | |
1217 | + if( weaponid == ID_WEAPON_GRENADE ){ | |
1218 | + break; | |
1219 | + } | |
1220 | + } | |
1221 | + } | |
1222 | + if( i == TOTAL_HAVEWEAPON ){ | |
1223 | + return 2; | |
1224 | + } | |
1225 | + | |
1226 | + //手榴弾を持っていなければ、切り替える | |
1227 | + if( i != selectweapon ){ | |
1228 | + ObjMgr->ChangeWeapon(ctrlid, i); | |
1229 | + } | |
1230 | + | |
1231 | + pointdata pdata; | |
1232 | + float posy2; | |
1233 | + float atan_rx, atan_ry; | |
1234 | + | |
1235 | + //パスと人の高さを取得 | |
1236 | + Points->Getdata(&pdata, target_pointid); | |
1237 | + posy2 = posy + VIEW_HEIGHT; | |
1238 | + | |
1239 | + //目標地点への角度を求める | |
1240 | + CheckTargetAngle(posx, pdata.y, posz, rx*-1 + (float)M_PI/2, ry, target_posx, posy2, target_posz, 0.0f, &atan_rx, &atan_ry, NULL); | |
1241 | + | |
1242 | + //大きな差があれば少しづつ旋回するだけ | |
1243 | + if( atan_rx > AI_TURNRAD ){ | |
1244 | + SetFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
1245 | + } | |
1246 | + if( atan_rx < AI_TURNRAD*-1 ){ | |
1247 | + SetFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
1248 | + } | |
1249 | + if( atan_ry > AI_TURNRAD ){ | |
1250 | + SetFlag(moveturn_mode, AI_CTRL_TURNUP); | |
1251 | + } | |
1252 | + if( atan_ry < AI_TURNRAD*-1 ){ | |
1253 | + SetFlag(moveturn_mode, AI_CTRL_TURNDOWN); | |
1254 | + } | |
1255 | + | |
1256 | + //微々たる差なら一気に向ける | |
1257 | + if( abs(atan_rx) <= AI_TURNRAD ){ | |
1258 | + DelFlag(moveturn_mode, AI_CTRL_TURNRIGHT); | |
1259 | + DelFlag(moveturn_mode, AI_CTRL_TURNLEFT); | |
1260 | + rx += atan_rx; | |
1261 | + } | |
1262 | + if( abs(atan_ry) <= AI_TURNRAD ){ | |
1263 | + DelFlag(moveturn_mode, AI_CTRL_TURNUP); | |
1264 | + DelFlag(moveturn_mode, AI_CTRL_TURNDOWN); | |
1265 | + ry += atan_ry; | |
1266 | + } | |
1267 | + | |
1268 | + //投げる | |
1269 | + if( (abs(atan_rx) < (float)M_PI/1800*15)&&(abs(atan_ry) < (float)M_PI/1800*15) ){ | |
1270 | + //角度を設定 | |
1271 | + ctrlhuman->SetRxRy(rx, ry); | |
1272 | + | |
1273 | + if( ObjMgr->ShotWeapon(ctrlid) != 0 ){ | |
1274 | + return 1; | |
1275 | + } | |
1276 | + } | |
1277 | + | |
1278 | + return 0; | |
1279 | +} | |
1280 | + | |
1281 | +//! @brief 腕の角度を設定 | |
1282 | +void AIcontrol::ArmAngle() | |
1283 | +{ | |
1284 | + float addry; | |
1285 | + | |
1286 | + if( ctrlhuman->GetMainWeaponTypeNO() == ID_WEAPON_NONE ){ //手ぶら | |
1287 | + addry = ARMRAD_NOWEAPON - ry; | |
1288 | + } | |
1289 | + else if( (battlemode == AI_CAUTION)&&(cautioncnt > 0) ){ //警戒中 | |
1290 | + addry = 0.0f - ry; | |
1291 | + } | |
1292 | + else{ //平常時で武器所有中 | |
1293 | + addry = AI_WEAPON_ARMRAD - ry; | |
1294 | + } | |
1295 | + | |
1296 | + //大きな差があれば少しづつ旋回するだけ | |
1297 | + if( addry > AI_TURNRAD ){ | |
1298 | + SetFlag(moveturn_mode, AI_CTRL_TURNUP); | |
1299 | + } | |
1300 | + if( addry < AI_TURNRAD*-1 ){ | |
1301 | + SetFlag(moveturn_mode, AI_CTRL_TURNDOWN); | |
1302 | + } | |
1303 | + | |
1304 | + //微々たる差なら一気に向ける | |
1305 | + if( abs(addry) <= AI_TURNRAD ){ | |
1306 | + DelFlag(moveturn_mode, AI_CTRL_TURNUP); | |
1307 | + DelFlag(moveturn_mode, AI_CTRL_TURNDOWN); | |
1308 | + ry += addry; | |
1309 | + } | |
1310 | +} | |
1311 | + | |
1312 | +//! @brief 敵を探す | |
1313 | +int AIcontrol::SearchEnemy() | |
1314 | +{ | |
1315 | + //非戦闘化フラグが有効なら敵を見つけない | |
1316 | + if( NoFight == true ){ | |
1317 | + return 0; | |
1318 | + } | |
1319 | + | |
1320 | + if( battlemode == AI_ACTION ){ return 0; } | |
1321 | + | |
1322 | + int weaponid = ctrlhuman->GetMainWeaponTypeNO(); | |
1323 | + int weaponscope = 0; | |
1324 | + int searchloops; | |
1325 | + float maxDist; | |
1326 | + float A_rx, A_ry, B_rx, B_ry; | |
1327 | + | |
1328 | + //武器を持っていれば、スコープモードを取得 | |
1329 | + if( weaponid != ID_WEAPON_NONE ){ | |
1330 | + WeaponParameter Wparam; | |
1331 | + | |
1332 | + Param->GetWeapon(weaponid, &Wparam); | |
1333 | + weaponscope = Wparam.scopemode; | |
1334 | + } | |
1335 | + | |
1336 | + //敵の探索回数と探索範囲(距離と角度)を設定 | |
1337 | + if( battlemode == AI_NORMAL ){ | |
1338 | + searchloops = (LevelParam->search) * 4; | |
1339 | + | |
1340 | + if( weaponscope == 2 ){ maxDist = 50.0f; } | |
1341 | + if( weaponscope == 1 ){ maxDist = 25.0f; } | |
1342 | + else{ maxDist = 0.0f; } | |
1343 | + maxDist += 12.0f*((LevelParam->search)-2) + 350.0f; | |
1344 | + A_rx = (float)M_PI/180*60; | |
1345 | + A_ry = (float)M_PI/180*110; | |
1346 | + B_rx = (float)M_PI/180*40; | |
1347 | + B_ry = (float)M_PI/180*60; | |
1348 | + } | |
1349 | + else { //battlemode == AI_CAUTION | |
1350 | + searchloops = (LevelParam->search) * 5; | |
1351 | + | |
1352 | + if( weaponscope == 2 ){ maxDist = 80.0f; } | |
1353 | + if( weaponscope == 1 ){ maxDist = 40.0f; } | |
1354 | + else{ maxDist = 0.0f; } | |
1355 | + maxDist += 15.0f*((LevelParam->search)-2) + 420.0f; | |
1356 | + A_rx = (float)M_PI/180*80; | |
1357 | + A_ry = (float)M_PI/180*130; | |
1358 | + B_rx = (float)M_PI/180*50; | |
1359 | + B_ry = (float)M_PI/180*80; | |
1360 | + } | |
1361 | + | |
1362 | + //指定回数、敵を探索 | |
1363 | + for(int i=0; i<searchloops; i++){ | |
1364 | + int targetid = random(MAX_HUMAN); | |
1365 | + | |
1366 | + if( CheckLookEnemy(targetid, A_rx, A_ry, 200.0f, NULL) == true ){ | |
1367 | + longattack = false; | |
1368 | + return 1; | |
1369 | + } | |
1370 | + | |
1371 | + if( CheckLookEnemy(targetid, B_rx, B_ry, maxDist, NULL) == true ){ | |
1372 | + if( random(4) == 0 ){ | |
1373 | + if( movemode == AI_RUN2 ){ longattack = false; } | |
1374 | + else{ longattack = true; } | |
1375 | + return 2; | |
1376 | + } | |
1377 | + } | |
1378 | + } | |
1379 | + return 0; | |
1380 | +} | |
1381 | + | |
1382 | +//! @brief 敵を探す(遠距離攻撃中に近距離を探す) | |
1383 | +int AIcontrol::SearchShortEnemy() | |
1384 | +{ | |
1385 | + float A_rx, A_ry; | |
1386 | + A_rx = (float)M_PI/180*100; | |
1387 | + A_ry = (float)M_PI/180*52; | |
1388 | + | |
1389 | + for(int i=0; i<3; i++){ | |
1390 | + int targetid = random(MAX_HUMAN); | |
1391 | + | |
1392 | + if( CheckLookEnemy(targetid, A_rx, A_ry, 200.0f, NULL) == true ){ | |
1393 | + longattack = false; | |
1394 | + return 1; | |
1395 | + } | |
1396 | + } | |
1397 | + return 0; | |
1398 | +} | |
1399 | + | |
1400 | +//! @brief 敵が見えるか判定 | |
1401 | +bool AIcontrol::CheckLookEnemy(int id, float search_rx, float search_ry, float maxDist, float *out_minDist) | |
1402 | +{ | |
1403 | + if( ObjMgr == NULL ){ return false; } | |
1404 | + | |
1405 | + //人のオブジェクトを取得 | |
1406 | + class human* thuman; | |
1407 | + thuman = ObjMgr->GeHumanObject(id); | |
1408 | + if( thuman == NULL ){ return false; } | |
1409 | + | |
1410 | + //同名関数をオーバーロード | |
1411 | + return CheckLookEnemy(thuman, search_rx, search_ry, maxDist, out_minDist); | |
1412 | +} | |
1413 | + | |
1414 | +//! @brief 敵が見えるか判定 | |
1415 | +bool AIcontrol::CheckLookEnemy(class human* thuman, float search_rx, float search_ry, float maxDist, float *out_minDist) | |
1416 | +{ | |
1417 | + //return false; | |
1418 | + | |
1419 | + //無効なデータなら終了 | |
1420 | + if( ctrlhuman == NULL ){ return false; } | |
1421 | + if( thuman == NULL ){ return false; } | |
1422 | + if( thuman->GetDrawFlag() == false ){ return false; } | |
1423 | + if( thuman->GetDeadFlag() == true ){ return false; } | |
1424 | + | |
1425 | + //自分と敵の座標を取得 | |
1426 | + int ctrlteam, targetteam; | |
1427 | + float tx, ty, tz; | |
1428 | + ctrlhuman->GetParamData(NULL, NULL, NULL, &ctrlteam); | |
1429 | + thuman->GetParamData(NULL, NULL, NULL, &targetteam); | |
1430 | + thuman->GetPosData(&tx, &ty, &tz, NULL); | |
1431 | + | |
1432 | + //自分と敵が同一人物でなければ | |
1433 | + if( ctrlteam != targetteam ){ | |
1434 | + float mrx, mry; | |
1435 | + float Dist2 , Dist; | |
1436 | + float Dist_dummy; | |
1437 | + | |
1438 | + //距離を判定し、角度も取得 | |
1439 | + if( CheckTargetAngle(posx, posy, posz, rx*-1 + (float)M_PI/2, 0.0f, tx, ty, tz, maxDist, &mrx, &mry, &Dist2) == true ){ | |
1440 | + //角度上、視界に入っていれば | |
1441 | + if( (abs(mrx) < search_rx/2)&&(abs(mry) < search_ry/2) ){ | |
1442 | + float vx, vy, vz; | |
1443 | + | |
1444 | + Dist = sqrt(Dist2); | |
1445 | + | |
1446 | + //ベクトルを取得 | |
1447 | + vx = (tx - posx)/Dist; | |
1448 | + vy = (ty - posy)/Dist; | |
1449 | + vz = (tz - posz)/Dist; | |
1450 | + | |
1451 | + //ブロックが遮っていなければ (レイで当たり判定を行い、当たっていなければ) | |
1452 | + if( CollD->CheckALLBlockIntersectRay(posx, posy + VIEW_HEIGHT, posz, vx, vy, vz, NULL, NULL, &Dist_dummy, Dist) == false ){ | |
1453 | + if( out_minDist != NULL ){ *out_minDist = Dist; } | |
1454 | + enemyhuman = thuman; | |
1455 | + return true; | |
1456 | + } | |
1457 | + } | |
1458 | + } | |
1459 | + } | |
1460 | + return false; | |
1461 | +} | |
1462 | + | |
1463 | +//! @brief 死体があるか確認 | |
1464 | +bool AIcontrol::CheckCorpse(int id) | |
1465 | +{ | |
1466 | + //クラス設定がおかしければ処理しない | |
1467 | + if( ObjMgr == NULL ){ return false; } | |
1468 | + if( ctrlhuman == NULL ){ return false; } | |
1469 | + | |
1470 | + //ターゲットのクラスを取得 | |
1471 | + class human* thuman; | |
1472 | + thuman = ObjMgr->GeHumanObject(id); | |
1473 | + if( thuman == NULL ){ return false; } | |
1474 | + if( thuman->GetDrawFlag() == false ){ return false; } | |
1475 | + | |
1476 | + //死亡していれば | |
1477 | + if( thuman->GetDeadFlag() == true ){ | |
1478 | + | |
1479 | + //チーム番号を取得 | |
1480 | + int ctrlteam, targetteam; | |
1481 | + ctrlhuman->GetParamData(NULL, NULL, NULL, &ctrlteam); | |
1482 | + thuman->GetParamData(NULL, NULL, NULL, &targetteam); | |
1483 | + | |
1484 | + //味方ならば | |
1485 | + if( ctrlteam == targetteam ){ | |
1486 | + float tposx, tposy, tposz; | |
1487 | + float atan; | |
1488 | + | |
1489 | + //座標から距離を取得 | |
1490 | + thuman->GetPosData(&tposx, &tposy, &tposz, NULL); | |
1491 | + | |
1492 | + //距離と角度を計算 | |
1493 | + if( CheckTargetAngle(posx, posy, posz, rx*-1 + (float)M_PI/2, 0.0f, tposx, tposy, tposz, 22.0f, &atan, NULL, NULL) == true ){ | |
1494 | + if( abs(atan) < (float)M_PI/18*4 ){ | |
1495 | + return true; | |
1496 | + } | |
1497 | + } | |
1498 | + } | |
1499 | + } | |
1500 | + return false; | |
1501 | +} | |
1502 | + | |
1503 | +//! @brief パスによる移動 | |
1504 | +void AIcontrol::MovePath() | |
1505 | +{ | |
1506 | + if( movemode == AI_NULL ){ //異常なパス | |
1507 | + // | |
1508 | + } | |
1509 | + else if( movemode == AI_GRENADE ){ //手榴弾パス | |
1510 | + if( ThrowGrenade() != 0 ){ | |
1511 | + SearchTarget(true); | |
1512 | + } | |
1513 | + } | |
1514 | + else{ //その他パス | |
1515 | + if( CheckTargetPos() == false ){ | |
1516 | + MoveTarget(); | |
1517 | + } | |
1518 | + else if( (movemode == AI_WAIT)||(movemode == AI_TRACKING) ){ | |
1519 | + TurnSeen(); | |
1520 | + } | |
1521 | + else if( (movemode == AI_STOP)&&(waitcnt < ((int)GAMEFPS)*5) ){ | |
1522 | + if( StopSeen() == true ){ | |
1523 | + waitcnt += 1; | |
1524 | + } | |
1525 | + } | |
1526 | + else{ | |
1527 | + waitcnt = 0; | |
1528 | + SearchTarget(true); | |
1529 | + } | |
1530 | + } | |
1531 | +} | |
1532 | + | |
1533 | +//! @brief 攻撃メイン処理 | |
1534 | +//! @return 不変:false 変更:true | |
1535 | +bool AIcontrol::ActionMain() | |
1536 | +{ | |
1537 | + int newbattlemode = AI_ACTION; | |
1538 | + | |
1539 | + //攻撃処理 | |
1540 | + Action(); | |
1541 | + | |
1542 | + if( movemode == AI_RUN2 ){ //優先的な走り | |
1543 | + //目標地点へ移動 | |
1544 | + if( CheckTargetPos() == true ){ | |
1545 | + newbattlemode = AI_NORMAL; | |
1546 | + SearchTarget(true); | |
1547 | + } | |
1548 | + else{ | |
1549 | + MoveTarget2(); | |
1550 | + } | |
1551 | + } | |
1552 | + else{ //優先的な走り 以外 | |
1553 | + //遠距離攻撃中なら、近くの敵を探す | |
1554 | + if( longattack == true ){ | |
1555 | + SearchShortEnemy(); | |
1556 | + } | |
1557 | + } | |
1558 | + | |
1559 | + //攻撃終了判定 | |
1560 | + if( ActionCancel() == true ){ | |
1561 | + enemyhuman = NULL; | |
1562 | + | |
1563 | + if( movemode == AI_RUN2 ){ | |
1564 | + newbattlemode = AI_NORMAL; | |
1565 | + } | |
1566 | + else{ | |
1567 | + newbattlemode = AI_CAUTION; | |
1568 | + cautioncnt = 160; | |
1569 | + } | |
1570 | + } | |
1571 | + | |
1572 | + //設定を判定 | |
1573 | + if( battlemode != newbattlemode ){ | |
1574 | + battlemode = newbattlemode; | |
1575 | + return true; | |
1576 | + } | |
1577 | + return false; | |
1578 | +} | |
1579 | + | |
1580 | +//! @brief 警戒メイン処理 | |
1581 | +//! @return 不変:false 変更:true | |
1582 | +bool AIcontrol::CautionMain() | |
1583 | +{ | |
1584 | + int newbattlemode = AI_CAUTION; | |
1585 | + | |
1586 | + //座標とチーム番号を取得 | |
1587 | + int teamid; | |
1588 | + ctrlhuman->GetParamData(NULL, NULL, NULL, &teamid); | |
1589 | + | |
1590 | + //被弾と音の状況を取得 | |
1591 | + bool HitFlag = ctrlhuman->CheckHit(); | |
1592 | + soundlist soundlist[MAX_SOUNDMGR_LIST]; | |
1593 | + int soundlists = GameSound->GetWorldSound(posx, posy + VIEW_HEIGHT, posz, teamid, soundlist); | |
1594 | + | |
1595 | + //非戦闘化フラグが有効なら、音は聞こえないことにする | |
1596 | + if( NoFight == true ){ | |
1597 | + soundlists = 0; | |
1598 | + } | |
1599 | + | |
1600 | + //回転と腕の角度 | |
1601 | + TurnSeen(); | |
1602 | + ArmAngle(); | |
1603 | + | |
1604 | + //メイン処理 | |
1605 | + if( enemyhuman != NULL ){ //既に敵を見つけていれば | |
1606 | + newbattlemode = AI_ACTION; | |
1607 | + actioncnt = 0; | |
1608 | + } | |
1609 | + else if( SearchEnemy() != 0 ){ //敵が見つかれば | |
1610 | + newbattlemode = AI_ACTION; | |
1611 | + actioncnt = 0; | |
1612 | + } | |
1613 | + else if( (HitFlag == true)||(soundlists > 0) ){ //被弾したか音が聞こえた | |
1614 | + cautioncnt = 160; //警戒を再開 | |
1615 | + } | |
1616 | + else if( cautioncnt == 0 ){ //警戒を終了するなら | |
1617 | + if( CheckTargetPos() == false ){ //警戒開始地点より離れているか | |
1618 | + MoveTarget(); //警戒開始地点に近づく | |
1619 | + } | |
1620 | + else{ | |
1621 | + newbattlemode = AI_NORMAL; | |
1622 | + | |
1623 | + //警戒待ちパスなら次へ進める | |
1624 | + pointdata pdata; | |
1625 | + Points->Getdata(&pdata, target_pointid); | |
1626 | + if( (pdata.p1 == 3)&&(pdata.p2 == 4) ){ | |
1627 | + SearchTarget(true); | |
1628 | + } | |
1629 | + } | |
1630 | + } | |
1631 | + else if( cautioncnt < 100 ){ //100フレームを切ったら、ランダムに警戒終了(カウント:0に) | |
1632 | + if( random(50) == 0 ){ cautioncnt = 0; } | |
1633 | + } | |
1634 | + else{ cautioncnt -= 1; } | |
1635 | + | |
1636 | + //追尾中で対象から離れすぎたら、ランダムに警戒終了 | |
1637 | + if( (movemode == AI_TRACKING)&&(random(3) == 0) ){ | |
1638 | + pointdata pdata; | |
1639 | + float x, z; | |
1640 | + float tx, tz; | |
1641 | + Points->Getdata(&pdata, target_pointid); | |
1642 | + SearchHumanPos(pdata.p4, &tx, &tz); | |
1643 | + x = posx - tx; | |
1644 | + z = posz - tz; | |
1645 | + if( (x*x + z*z) > 25.0f*25.0f ){ | |
1646 | + cautioncnt = 0; | |
1647 | + } | |
1648 | + } | |
1649 | + | |
1650 | + //設定を判定 | |
1651 | + if( battlemode != newbattlemode ){ | |
1652 | + battlemode = newbattlemode; | |
1653 | + return true; | |
1654 | + } | |
1655 | + return false; | |
1656 | +} | |
1657 | + | |
1658 | +//! @brief 通常メイン処理 | |
1659 | +//! @return 不変:false 変更:true | |
1660 | +bool AIcontrol::NormalMain() | |
1661 | +{ | |
1662 | + int newbattlemode = AI_NORMAL; | |
1663 | + | |
1664 | + if( hold == false ){ | |
1665 | + SearchTarget(false); | |
1666 | + } | |
1667 | + enemyhuman = NULL; | |
1668 | + | |
1669 | + //座標とチーム番号を取得 | |
1670 | + int teamid; | |
1671 | + ctrlhuman->GetParamData(NULL, NULL, NULL, &teamid); | |
1672 | + | |
1673 | + //被弾と音の状況を取得 | |
1674 | + bool HitFlag = ctrlhuman->CheckHit(); | |
1675 | + soundlist soundlist[MAX_SOUNDMGR_LIST]; | |
1676 | + int soundlists = GameSound->GetWorldSound(posx, posy + VIEW_HEIGHT, posz, teamid, soundlist); | |
1677 | + | |
1678 | + //非戦闘化フラグが有効なら、音は聞こえないことにする | |
1679 | + if( NoFight == true ){ | |
1680 | + soundlists = 0; | |
1681 | + } | |
1682 | + | |
1683 | + //ランダムパスなら処理実行 | |
1684 | + if( movemode == AI_RANDOM ){ | |
1685 | + SearchTarget(true); | |
1686 | + } | |
1687 | + | |
1688 | + //腕の角度を設定 | |
1689 | + if( movemode != AI_GRENADE ){ | |
1690 | + ArmAngle(); | |
1691 | + } | |
1692 | + | |
1693 | + if( movemode == AI_RUN2 ){ //優先的な走りの処理 | |
1694 | + //敵を見つけたら攻撃に入る | |
1695 | + if( SearchEnemy() != 0 ){ | |
1696 | + newbattlemode = AI_ACTION; | |
1697 | + } | |
1698 | + else{ | |
1699 | + MovePath(); //移動実行 | |
1700 | + } | |
1701 | + } | |
1702 | + else{ //優先的な走り以外の処理 | |
1703 | + //警戒判定に入る処理 | |
1704 | + if( | |
1705 | + (SearchEnemy() != 0)|| //敵を見つけた | |
1706 | + (HitFlag == true)||(soundlists > 0)|| //被弾したか音が聞こえた | |
1707 | + (CheckCorpse( random(MAX_HUMAN) ) == true) //死体を見つけた | |
1708 | + ){ | |
1709 | + newbattlemode = AI_CAUTION; | |
1710 | + cautioncnt = 160; | |
1711 | + target_posx = posx; | |
1712 | + target_posz = posz; | |
1713 | + } | |
1714 | + else{ | |
1715 | + MovePath(); //移動実行 | |
1716 | + } | |
1717 | + } | |
1718 | + | |
1719 | + //設定を判定 | |
1720 | + if( battlemode != newbattlemode ){ | |
1721 | + battlemode = newbattlemode; | |
1722 | + return true; | |
1723 | + } | |
1724 | + return false; | |
1725 | +} | |
1726 | + | |
1727 | +//! @brief 初期化系関数 | |
1728 | +void AIcontrol::Init() | |
1729 | +{ | |
1730 | + //クラス設定がおかしければ処理しない | |
1731 | + if( ctrlhuman == NULL ){ return; } | |
1732 | + if( blocks == NULL ){ return; } | |
1733 | + if( Points == NULL ){ return; } | |
1734 | + if( CollD == NULL ){ return; } | |
1735 | + | |
1736 | + //使用されていない人なら処理しない | |
1737 | + if( ctrlhuman->GetDrawFlag() == false ){ return; } | |
1738 | + | |
1739 | + //ステートを初期化 | |
1740 | + hold = false; | |
1741 | + NoFight = false; | |
1742 | + battlemode = AI_NORMAL; | |
1743 | + movemode = AI_NULL; | |
1744 | + enemyhuman = NULL; | |
1745 | + waitcnt = 0; | |
1746 | + gotocnt = 0; | |
1747 | + moveturn_mode = 0x00; | |
1748 | + cautioncnt = 0; | |
1749 | + actioncnt = 0; | |
1750 | + longattack = false; | |
1751 | + | |
1752 | + //AIレベルと設定値を取得 | |
1753 | + int paramid; | |
1754 | + HumanParameter paramdata; | |
1755 | + //target_pointid = in_target_pointid; | |
1756 | + ctrlhuman->GetParamData(¶mid, &target_pointid, NULL, NULL); | |
1757 | + Param->GetHuman(paramid, ¶mdata); | |
1758 | + AIlevel = paramdata.AIlevel; | |
1759 | + Param->GetAIlevel(AIlevel, &LevelParam); | |
1760 | + | |
1761 | + //次のポイントを検索 | |
1762 | + SearchTarget(true); | |
1763 | +} | |
1764 | + | |
1765 | +//! @brief 指定した場所へ待機させる | |
1766 | +//! @param px X座標 | |
1767 | +//! @param pz Z座標 | |
1768 | +//! @param rx 重視する向き | |
1769 | +//! @attention 移動パスに関わらず、指定した座標への待機を強制します。Init()関数を再度実行するまで元に戻せません。 | |
1770 | +void AIcontrol::SetHoldWait(float px, float pz, float rx) | |
1771 | +{ | |
1772 | + movemode = AI_WAIT; | |
1773 | + hold = true; | |
1774 | + target_posx = px; | |
1775 | + target_posz = pz; | |
1776 | + target_rx = rx; | |
1777 | +} | |
1778 | + | |
1779 | +//! @brief 指定した人を追尾させる | |
1780 | +//! @param id 人のデータ番号 | |
1781 | +//! @attention 移動パスに関わらず、指定した人への追尾を強制します。Init()関数を再度実行するまで元に戻せません。 | |
1782 | +void AIcontrol::SetHoldTracking(int id) | |
1783 | +{ | |
1784 | + movemode = AI_TRACKING; | |
1785 | + hold = false; | |
1786 | + target_pointid = id; | |
1787 | +} | |
1788 | + | |
1789 | +//! @brief 強制的に警戒させる | |
1790 | +//! @warning 優先的な走り を実行中の場合、この関数は何もしません。 | |
1791 | +void AIcontrol::SetCautionMode() | |
1792 | +{ | |
1793 | + //優先的な走りならば何もしない | |
1794 | + if( movemode == AI_RUN2 ){ return; } | |
1795 | + | |
1796 | + if( battlemode == AI_NORMAL ){ | |
1797 | + target_posx = posx; | |
1798 | + target_posz = posz; | |
1799 | + } | |
1800 | + battlemode = AI_CAUTION; | |
1801 | + cautioncnt = 160; | |
1802 | +} | |
1803 | + | |
1804 | +//! @brief 非戦闘化フラグを設定 | |
1805 | +//! @param flag true:戦闘を行わない(非戦闘化) false:戦闘を行う(通常) | |
1806 | +//! @attention フラグを有効にすると敵を認識しなくなります。 | |
1807 | +void AIcontrol::SetNoFightFlag(bool flag) | |
1808 | +{ | |
1809 | + NoFight = flag; | |
1810 | +} | |
1811 | + | |
1812 | +//! @brief 処理系関数 | |
1813 | +void AIcontrol::Process() | |
1814 | +{ | |
1815 | + //クラス設定がおかしければ処理しない | |
1816 | + if( ctrlhuman == NULL ){ return; } | |
1817 | + if( blocks == NULL ){ return; } | |
1818 | + if( Points == NULL ){ return; } | |
1819 | + if( CollD == NULL ){ return; } | |
1820 | + | |
1821 | + //無効な人クラスなら処理しない | |
1822 | + if( ctrlhuman->GetDrawFlag() == false ){ return; } | |
1823 | + | |
1824 | + //死亡したら | |
1825 | + if( ctrlhuman->GetHP() <= 0 ){ | |
1826 | + battlemode = AI_DEAD; | |
1827 | + movemode = AI_DEAD; | |
1828 | + return; | |
1829 | + } | |
1830 | + | |
1831 | + //座標と角度を取得 | |
1832 | + ctrlhuman->GetPosData(&posx, &posy, &posz, NULL); | |
1833 | + ctrlhuman->GetRxRy(&rx, &ry); | |
1834 | + | |
1835 | + //ランダムに動作を止める | |
1836 | + CancelMoveTurn(); | |
1837 | + | |
1838 | + //攻撃中か警戒中ならば | |
1839 | + if( (battlemode == AI_ACTION)||(battlemode == AI_CAUTION) ){ | |
1840 | + //武器を持つ | |
1841 | + HaveWeapon(); | |
1842 | + } | |
1843 | + | |
1844 | + //主計算実行 | |
1845 | + if( battlemode == AI_ACTION ){ //攻撃中 | |
1846 | + ActionMain(); | |
1847 | + } | |
1848 | + else if( battlemode == AI_CAUTION ){ //警戒中 | |
1849 | + CautionMain(); | |
1850 | + } | |
1851 | + else{ //平常時 | |
1852 | + NormalMain(); | |
1853 | + } | |
1854 | + | |
1855 | + //移動・方向転換処理 | |
1856 | + ControlMoveTurn(); | |
1857 | + | |
1858 | + //武器を取り扱い | |
1859 | + ControlWeapon(); | |
1860 | + | |
1861 | + //角度を適用 | |
1862 | + ctrlhuman->SetRxRy(rx, ry); | |
1863 | +} | |
\ No newline at end of file |
@@ -0,0 +1,2260 @@ | ||
1 | +//! @file objectmanager.cpp | |
2 | +//! @brief ObjectManagerクラスの定義 | |
3 | + | |
4 | +//-------------------------------------------------------------------------------- | |
5 | +// | |
6 | +// OpenXOPS | |
7 | +// Copyright (c) 2014-2015, OpenXOPS Project / [-_-;](mikan) All rights reserved. | |
8 | +// | |
9 | +// Redistribution and use in source and binary forms, with or without | |
10 | +// modification, are permitted provided that the following conditions are met: | |
11 | +// * Redistributions of source code must retain the above copyright notice, | |
12 | +// this list of conditions and the following disclaimer. | |
13 | +// * Redistributions in binary form must reproduce the above copyright notice, | |
14 | +// this list of conditions and the following disclaimer in the documentation | |
15 | +// and/or other materials provided with the distribution. | |
16 | +// * Neither the name of the OpenXOPS Project nor the names of its contributors | |
17 | +// may be used to endorse or promote products derived from this software | |
18 | +// without specific prior written permission. | |
19 | +// | |
20 | +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
21 | +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
22 | +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
23 | +// DISCLAIMED. IN NO EVENT SHALL OpenXOPS Project BE LIABLE FOR ANY | |
24 | +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
25 | +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
26 | +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
27 | +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 | +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
29 | +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | +//-------------------------------------------------------------------------------- | |
31 | + | |
32 | +#include "objectmanager.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +ObjectManager::ObjectManager() | |
36 | +{ | |
37 | + HumanIndex = new human[MAX_HUMAN]; | |
38 | + WeaponIndex = new weapon[MAX_WEAPON]; | |
39 | + SmallObjectIndex = new smallobject[MAX_SMALLOBJECT]; | |
40 | + BulletIndex = new bullet[MAX_BULLET]; | |
41 | + GrenadeIndex = new grenade[MAX_GRENADE]; | |
42 | + EffectIndex = new effect[MAX_EFFECT]; | |
43 | + | |
44 | + framecnt = 0; | |
45 | + Human_ontarget = new int[MAX_HUMAN]; | |
46 | + Human_kill = new int[MAX_HUMAN]; | |
47 | + Human_headshot = new int[MAX_HUMAN]; | |
48 | + Human_ShotFlag = new bool[MAX_HUMAN]; | |
49 | + Player_HumanID = 0; | |
50 | + AddHumanIndex_TextureID = -1; | |
51 | + | |
52 | + GameParamInfo = NULL; | |
53 | + d3dg = NULL; | |
54 | + Resource = NULL; | |
55 | + BlockData = NULL; | |
56 | + PointData = NULL; | |
57 | + CollD = NULL; | |
58 | +} | |
59 | + | |
60 | +//! @brief ディストラクタ | |
61 | +ObjectManager::~ObjectManager() | |
62 | +{ | |
63 | + Cleanup(); | |
64 | + | |
65 | + if( HumanIndex != NULL ){ delete [] HumanIndex; } | |
66 | + if( WeaponIndex != NULL ){ delete [] WeaponIndex; } | |
67 | + if( SmallObjectIndex != NULL ){ delete [] SmallObjectIndex; } | |
68 | + if( BulletIndex != NULL ){ delete [] BulletIndex; } | |
69 | + if( GrenadeIndex != NULL ){ delete [] GrenadeIndex; } | |
70 | + if( EffectIndex != NULL ){ delete [] EffectIndex; } | |
71 | + | |
72 | + if( Human_ontarget != NULL ){ delete [] Human_ontarget; } | |
73 | + if( Human_kill != NULL ){ delete [] Human_kill; } | |
74 | + if( Human_headshot != NULL ){ delete [] Human_headshot; } | |
75 | + if( Human_ShotFlag != NULL ){ delete [] Human_ShotFlag; } | |
76 | +} | |
77 | + | |
78 | +//! @brief 参照するクラスを設定 | |
79 | +//! @param in_GameParamInfo ゲーム設定データ管理クラス | |
80 | +//! @param in_d3dg 描画処理クラス | |
81 | +//! @param in_Resource リソース管理クラス | |
82 | +//! @param in_BlockData ブロックデータ管理クラス | |
83 | +//! @param in_PointData ポイントデータ管理クラス | |
84 | +//! @param in_CollD 当たり判定処理クラス | |
85 | +//! @param in_GameSound 効果音再生クラス | |
86 | +//! @param in_MIFdata MIFコントロールクラス | |
87 | +//! @attention この関数で設定を行わないと、クラス自体が正しく機能しません。 | |
88 | +void ObjectManager::SetClass(ParameterInfo *in_GameParamInfo, D3DGraphics *in_d3dg, ResourceManager *in_Resource, BlockDataInterface *in_BlockData, PointDataInterface *in_PointData, Collision *in_CollD, SoundManager *in_GameSound, MIFInterface *in_MIFdata) | |
89 | +{ | |
90 | + GameParamInfo = in_GameParamInfo; | |
91 | + d3dg = in_d3dg; | |
92 | + Resource = in_Resource; | |
93 | + BlockData = in_BlockData; | |
94 | + PointData = in_PointData; | |
95 | + CollD = in_CollD; | |
96 | + GameSound = in_GameSound; | |
97 | + MIFdata = in_MIFdata; | |
98 | + | |
99 | + for(int i=0; i<MAX_HUMAN; i++){ | |
100 | + HumanIndex[i].SetParameterInfoClass(GameParamInfo); | |
101 | + } | |
102 | + for(int i=0; i<MAX_WEAPON; i++){ | |
103 | + WeaponIndex[i].SetParameterInfoClass(GameParamInfo); | |
104 | + } | |
105 | + for(int i=0; i<MAX_SMALLOBJECT; i++){ | |
106 | + SmallObjectIndex[i].SetParameterInfoClass(GameParamInfo); | |
107 | + SmallObjectIndex[i].SetMIFInterfaceClass(MIFdata); | |
108 | + } | |
109 | + for(int i=0; i<MAX_GRENADE; i++){ | |
110 | + GrenadeIndex[i].SetParameterInfoClass(GameParamInfo); | |
111 | + } | |
112 | + | |
113 | + int bulletmodel, bullettexture; | |
114 | + Resource->GetBulletModelTexture(&bulletmodel, &bullettexture); | |
115 | + for(int i=0; i<MAX_BULLET; i++){ | |
116 | + BulletIndex[i].SetModel(bulletmodel, 1.0f); | |
117 | + BulletIndex[i].SetTexture(bullettexture); | |
118 | + } | |
119 | + | |
120 | + int grenademodel, grenadetexture; | |
121 | + float model_size = 1.0f; | |
122 | + WeaponParameter ParamData; | |
123 | + | |
124 | + //リソースとモデルサイズを取得 | |
125 | + Resource->GetWeaponModelTexture(ID_WEAPON_GRENADE, &grenademodel, &grenadetexture); | |
126 | + if( GameParamInfo->GetWeapon(ID_WEAPON_GRENADE, &ParamData) == 0 ){ | |
127 | + model_size = ParamData.size; | |
128 | + } | |
129 | + | |
130 | + //適用 | |
131 | + for(int i=0; i<MAX_GRENADE; i++){ | |
132 | + GrenadeIndex[i].SetModel(grenademodel, model_size); | |
133 | + GrenadeIndex[i].SetTexture(grenadetexture); | |
134 | + } | |
135 | +} | |
136 | + | |
137 | +//! @brief 人追加 | |
138 | +//! @param data 人のポイントデータ (pointdata構造体) | |
139 | +//! @param infodata 参照する人情報のポイントデータ (〃) | |
140 | +//! @return 成功:データ番号(0以上) 失敗:-1 | |
141 | +//! @attention 無効な人の種類番号が指定された場合は 通称:謎人間 が登場します。テクスチャはマップテクスチャ0番が使用され、HPは 0 が指定(=即死)されます。 | |
142 | +int ObjectManager::AddHumanIndex(pointdata data, pointdata infodata) | |
143 | +{ | |
144 | + int GetHumanFlag; | |
145 | + HumanParameter HumanParam; | |
146 | + GetHumanFlag = GameParamInfo->GetHuman(infodata.p2, &HumanParam); | |
147 | + int Humanindexid = -1; | |
148 | + int Weaponindexid = -1; | |
149 | + class weapon *Weapon[TOTAL_HAVEWEAPON]; | |
150 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
151 | + Weapon[i] = NULL; | |
152 | + } | |
153 | + | |
154 | + //人のモデル番号を取得 | |
155 | + int upmodel[TOTAL_UPMODE]; | |
156 | + int armmodel[TOTAL_ARMMODE]; | |
157 | + int legmodel; | |
158 | + int walkmodel[TOTAL_WALKMODE]; | |
159 | + int runmodel[TOTAL_RUNMODE]; | |
160 | + Resource->GetHumanModel(upmodel, armmodel, &legmodel, walkmodel, runmodel); | |
161 | + | |
162 | + for(int j=0; j<MAX_HUMAN; j++){ | |
163 | + if( HumanIndex[j].GetDrawFlag() == false ){ | |
164 | + //初期化する | |
165 | + HumanIndex[j].SetPosData(data.x, data.y, data.z, data.r); | |
166 | + HumanIndex[j].SetParamData(infodata.p2, data.id, data.p4, infodata.p3, true); | |
167 | + if( GetHumanFlag == 0 ){ | |
168 | + int id = Resource->GetHumanTexture(infodata.p2); | |
169 | + if( id == -1 ){ | |
170 | + id = AddHumanIndex_TextureID; | |
171 | + } | |
172 | + else{ | |
173 | + AddHumanIndex_TextureID = id; | |
174 | + } | |
175 | + | |
176 | + HumanIndex[j].SetTexture(id); | |
177 | + HumanIndex[j].SetModel(upmodel[ HumanParam.model ], armmodel, legmodel, walkmodel, runmodel); | |
178 | + } | |
179 | + else{ | |
180 | + AddHumanIndex_TextureID = d3dg->GetMapTextureID(0); | |
181 | + | |
182 | + HumanIndex[j].SetTexture(AddHumanIndex_TextureID); | |
183 | + HumanIndex[j].SetModel(upmodel[0], armmodel, legmodel, walkmodel, runmodel); | |
184 | + } | |
185 | + HumanIndex[j].SetDrawFlag(true); | |
186 | + Humanindexid = j; | |
187 | + break; | |
188 | + } | |
189 | + } | |
190 | + | |
191 | + //初期化できなかったらエラーとして返す | |
192 | + if( Humanindexid == -1 ){ | |
193 | + return -1; | |
194 | + } | |
195 | + | |
196 | + //人の設定データが正しく読めていれば〜 | |
197 | + if( GetHumanFlag == 0 ){ | |
198 | + //武器Bを仮想武器として追加 | |
199 | + Weaponindexid = AddVisualWeaponIndex(HumanParam.Weapon[0], true); | |
200 | + if( Weaponindexid != -1 ){ | |
201 | + //成功すれば配列に記録 | |
202 | + Weapon[0] = &WeaponIndex[Weaponindexid]; | |
203 | + } | |
204 | + if( data.p1 == 1 ){ | |
205 | + //武器Aの仮想武器として追加 | |
206 | + Weaponindexid = AddVisualWeaponIndex(HumanParam.Weapon[1], true); | |
207 | + if( Weaponindexid != -1 ){ | |
208 | + //成功すれば配列に記録 | |
209 | + Weapon[1] = &WeaponIndex[Weaponindexid]; | |
210 | + } | |
211 | + } | |
212 | + | |
213 | + //人に持たせる | |
214 | + HumanIndex[Humanindexid].SetWeapon(Weapon); | |
215 | + } | |
216 | + | |
217 | + //発砲フラグを初期化 | |
218 | + Human_ShotFlag[Humanindexid] = false; | |
219 | + | |
220 | + //プレイヤーならば、番号を記録 | |
221 | + if( ( (data.p1 == 1)||(data.p1 == 6) )&&(data.p4 == 0) ){ | |
222 | + Player_HumanID = Humanindexid; | |
223 | + } | |
224 | + | |
225 | + return Humanindexid; | |
226 | +} | |
227 | + | |
228 | +//! @brief 人追加(ゲーム中用) | |
229 | +//! @param px X座標 | |
230 | +//! @param py Y座標 | |
231 | +//! @param pz Z座標 | |
232 | +//! @param rx X軸向き | |
233 | +//! @param paramID 種類番号 | |
234 | +//! @param TeamID チーム番号 | |
235 | +//! @param WeaponID 武器種類番号の配列(要素数:TOTAL_HAVEWEAPON) | |
236 | +//! @return 成功:データ番号(0以上) 失敗:-1 | |
237 | +//! @attention 無効な人の種類番号が指定された場合は 通称:謎人間 が登場します。テクスチャはマップテクスチャ0番が使用され、HPは 0 が指定(=即死)されます。 | |
238 | +int ObjectManager::AddHumanIndex(float px, float py, float pz, float rx, int paramID, int TeamID, int WeaponID[]) | |
239 | +{ | |
240 | + int GetHumanFlag; | |
241 | + HumanParameter HumanParam; | |
242 | + GetHumanFlag = GameParamInfo->GetHuman(paramID, &HumanParam); | |
243 | + int Humanindexid = -1; | |
244 | + int Weaponindexid = -1; | |
245 | + class weapon *Weapon[TOTAL_HAVEWEAPON]; | |
246 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
247 | + Weapon[i] = NULL; | |
248 | + } | |
249 | + | |
250 | + //人のモデル番号を取得 | |
251 | + int upmodel[TOTAL_UPMODE]; | |
252 | + int armmodel[TOTAL_ARMMODE]; | |
253 | + int legmodel; | |
254 | + int walkmodel[TOTAL_WALKMODE]; | |
255 | + int runmodel[TOTAL_RUNMODE]; | |
256 | + Resource->GetHumanModel(upmodel, armmodel, &legmodel, walkmodel, runmodel); | |
257 | + | |
258 | + for(int i=0; i<MAX_HUMAN; i++){ | |
259 | + if( HumanIndex[i].GetDrawFlag() == false ){ | |
260 | + //初期化する | |
261 | + HumanIndex[i].SetPosData(px, py, pz, rx); | |
262 | + HumanIndex[i].SetParamData(paramID, -1, 0, TeamID, true); | |
263 | + if( GetHumanFlag == 0 ){ | |
264 | + //読み込めなければ、前回読み込んだテクスチャ番号を利用 | |
265 | + //読み込めれば、今回読み込むテクスチャ番号を上書き | |
266 | + int id = Resource->GetHumanTexture(paramID); | |
267 | + if( id == -1 ){ | |
268 | + id = AddHumanIndex_TextureID; | |
269 | + } | |
270 | + else{ | |
271 | + AddHumanIndex_TextureID = id; | |
272 | + } | |
273 | + | |
274 | + HumanIndex[i].SetTexture(id); | |
275 | + HumanIndex[i].SetModel(upmodel[ HumanParam.model ], armmodel, legmodel, walkmodel, runmodel); | |
276 | + } | |
277 | + else{ | |
278 | + //今回読み込むテクスチャ番号を上書き | |
279 | + AddHumanIndex_TextureID = d3dg->GetMapTextureID(0); | |
280 | + | |
281 | + HumanIndex[i].SetTexture(AddHumanIndex_TextureID); | |
282 | + HumanIndex[i].SetModel(upmodel[0], armmodel, legmodel, walkmodel, runmodel); | |
283 | + } | |
284 | + HumanIndex[i].SetDrawFlag(true); | |
285 | + Humanindexid = i; | |
286 | + break; | |
287 | + } | |
288 | + } | |
289 | + | |
290 | + //初期化できなかったらエラーとして返す | |
291 | + if( Humanindexid == -1 ){ | |
292 | + return -1; | |
293 | + } | |
294 | + | |
295 | + if( GetHumanFlag == 0 ){ | |
296 | + //仮想武器を追加 | |
297 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
298 | + Weaponindexid = AddVisualWeaponIndex(WeaponID[i], true); | |
299 | + if( Weaponindexid != -1 ){ | |
300 | + //成功すれば配列に記録 | |
301 | + Weapon[i] = &WeaponIndex[Weaponindexid]; | |
302 | + } | |
303 | + } | |
304 | + | |
305 | + //人に持たせる | |
306 | + HumanIndex[Humanindexid].SetWeapon(Weapon); | |
307 | + } | |
308 | + | |
309 | + return Humanindexid; | |
310 | +} | |
311 | + | |
312 | +//! @brief 武器追加 | |
313 | +//! @param data 武器のポイントデータ (pointdata構造体) | |
314 | +//! @return 成功:データ番号(0以上) 失敗:-1 | |
315 | +int ObjectManager::AddWeaponIndex(pointdata data) | |
316 | +{ | |
317 | + //武器番号と弾数を仮登録 | |
318 | + int WeaponID = data.p2; | |
319 | + int nbs = (unsigned char)data.p3; | |
320 | + | |
321 | + //ランダムな武器ならば | |
322 | + if( data.p1 == 7 ){ | |
323 | + WeaponParameter WeaponParam; | |
324 | + | |
325 | + if( GetRand(2) == 0 ){ | |
326 | + if( GameParamInfo->GetWeapon(data.p2, &WeaponParam) == 1 ){ return -1; } | |
327 | + nbs = (int)WeaponParam.nbsmax * TOTAL_WEAPON_AUTOBULLET; //弾数上書き | |
328 | + } | |
329 | + else{ | |
330 | + if( GameParamInfo->GetWeapon(data.p3, &WeaponParam) == 1 ){ return -1; } | |
331 | + WeaponID = data.p3; //武器番号上書き | |
332 | + nbs = (int)WeaponParam.nbsmax * TOTAL_WEAPON_AUTOBULLET; //弾数上書き | |
333 | + } | |
334 | + } | |
335 | + | |
336 | + //NONEならば失敗 | |
337 | + if( WeaponID == ID_WEAPON_NONE ){ return -1; } | |
338 | + | |
339 | + //モデルとテクスチャを取得 | |
340 | + int model, texture; | |
341 | + if( Resource->GetWeaponModelTexture(WeaponID, &model, &texture) == 1 ){ | |
342 | + return -1; | |
343 | + } | |
344 | + | |
345 | + //設定値を取得 | |
346 | + WeaponParameter WeaponParam; | |
347 | + if( GameParamInfo->GetWeapon(data.p2, &WeaponParam) == 1 ){ return -1; } | |
348 | + | |
349 | + for(int i=0; i<MAX_WEAPON; i++){ | |
350 | + if( WeaponIndex[i].GetDrawFlag() == false ){ | |
351 | + //初期化する | |
352 | + WeaponIndex[i].SetPosData(data.x, data.y, data.z, data.r); | |
353 | + WeaponIndex[i].SetParamData(WeaponID, 0, nbs, true); | |
354 | + WeaponIndex[i].SetModel(model, WeaponParam.size); | |
355 | + WeaponIndex[i].SetTexture(texture); | |
356 | + WeaponIndex[i].SetDrawFlag(true); | |
357 | + WeaponIndex[i].RunReload(); | |
358 | + return i; | |
359 | + } | |
360 | + } | |
361 | + return -1; | |
362 | +} | |
363 | + | |
364 | +//! @brief 仮想武器追加 | |
365 | +//! @param WeaponID 武器の種類番号 | |
366 | +//! @param loadbullet 弾をロードする | |
367 | +//! @return 成功:データ番号(0以上) 失敗:-1 | |
368 | +//! @attention 人が最初から所持している武器を、武器データ(オブジェクト)として追加処理するための関数です。 | |
369 | +//! @attention 武器単体として配置する場合は、AddWeaponIndex()関数を使用してください。 | |
370 | +int ObjectManager::AddVisualWeaponIndex(int WeaponID, bool loadbullet) | |
371 | +{ | |
372 | + //NONEならば失敗 | |
373 | + if( WeaponID == ID_WEAPON_NONE ){ return -1; } | |
374 | + | |
375 | + //情報を取得 | |
376 | + WeaponParameter WeaponParam; | |
377 | + if( GameParamInfo->GetWeapon(WeaponID, &WeaponParam) == 1 ){ return -1; } | |
378 | + | |
379 | + //モデルとテクスチャを取得 | |
380 | + int model, texture; | |
381 | + if( Resource->GetWeaponModelTexture(WeaponID, &model, &texture) == 1 ){ | |
382 | + return -1; | |
383 | + } | |
384 | + | |
385 | + for(int i=0; i<MAX_WEAPON; i++){ | |
386 | + if( WeaponIndex[i].GetDrawFlag() == false ){ | |
387 | + //初期化 | |
388 | + WeaponIndex[i].SetPosData(0.0f, 0.0f, 0.0f, 0.0f); | |
389 | + if( loadbullet == false ){ | |
390 | + WeaponIndex[i].SetParamData(WeaponID, 0, 0, true); | |
391 | + } | |
392 | + else{ | |
393 | + WeaponIndex[i].SetParamData(WeaponID, WeaponParam.nbsmax, WeaponParam.nbsmax * TOTAL_WEAPON_AUTOBULLET, true); | |
394 | + } | |
395 | + WeaponIndex[i].SetModel(model, WeaponParam.size); | |
396 | + WeaponIndex[i].SetTexture(texture); | |
397 | + WeaponIndex[i].SetDrawFlag(true); | |
398 | + return i; | |
399 | + } | |
400 | + } | |
401 | + return -1; | |
402 | +} | |
403 | + | |
404 | +//! @brief 小物追加 | |
405 | +//! @param data 小物のポイントデータ (pointdata構造体) | |
406 | +//! @return 成功:データ番号(0以上) 失敗:-1 | |
407 | +int ObjectManager::AddSmallObjectIndex(pointdata data) | |
408 | +{ | |
409 | + //モデルとテクスチャを取得 | |
410 | + int model, texture; | |
411 | + if( Resource->GetSmallObjectModelTexture(data.p2, &model, &texture) == 1 ){ | |
412 | + return -1; | |
413 | + } | |
414 | + | |
415 | + for(int j=0; j<MAX_SMALLOBJECT; j++){ | |
416 | + if( SmallObjectIndex[j].GetDrawFlag() == false ){ | |
417 | + //初期化 | |
418 | + SmallObjectIndex[j].SetPosData(data.x, data.y, data.z, data.r); | |
419 | + SmallObjectIndex[j].SetParamData(data.p2, data.p4, true); | |
420 | + SmallObjectIndex[j].SetModel(model, 5.0f); | |
421 | + SmallObjectIndex[j].SetTexture(texture); | |
422 | + SmallObjectIndex[j].SetDrawFlag(true); | |
423 | + | |
424 | + //位置修正フラグが有効ならば、マップと判定 | |
425 | + if( data.p3 !=0 ){ | |
426 | + SmallObjectIndex[j].CollisionMap(CollD); | |
427 | + } | |
428 | + return j; | |
429 | + } | |
430 | + } | |
431 | + return -1; | |
432 | +} | |
433 | + | |
434 | +//! @brief 小物追加(ゲーム中用) | |
435 | +//! @param px X座標 | |
436 | +//! @param py Y座標 | |
437 | +//! @param pz Z座標 | |
438 | +//! @param rx X軸向き | |
439 | +//! @param paramID 種類番号 | |
440 | +//! @param MapColl 位置修正フラグ | |
441 | +//! @return 成功:データ番号(0以上) 失敗:-1 | |
442 | +int ObjectManager::AddSmallObjectIndex(float px, float py, float pz, float rx, int paramID, bool MapColl) | |
443 | +{ | |
444 | + //モデルとテクスチャを取得 | |
445 | + int model, texture; | |
446 | + if( Resource->GetSmallObjectModelTexture(paramID, &model, &texture) == 1 ){ | |
447 | + return -1; | |
448 | + } | |
449 | + | |
450 | + for(int j=0; j<MAX_SMALLOBJECT; j++){ | |
451 | + if( SmallObjectIndex[j].GetDrawFlag() == false ){ | |
452 | + //初期化 | |
453 | + SmallObjectIndex[j].SetPosData(px, py, pz, rx); | |
454 | + SmallObjectIndex[j].SetParamData(paramID, 0, true); | |
455 | + SmallObjectIndex[j].SetModel(model, 5.0f); | |
456 | + SmallObjectIndex[j].SetTexture(texture); | |
457 | + SmallObjectIndex[j].SetDrawFlag(true); | |
458 | + | |
459 | + //位置修正フラグが有効ならば、マップと判定 | |
460 | + if( MapColl == true ){ | |
461 | + SmallObjectIndex[j].CollisionMap(CollD); | |
462 | + } | |
463 | + return j; | |
464 | + } | |
465 | + } | |
466 | + return -1; | |
467 | +} | |
468 | + | |
469 | +//! @brief エフェクト追加 | |
470 | +//! @param pos_x X座標 | |
471 | +//! @param pos_y Y座標 | |
472 | +//! @param pos_z Z座標 | |
473 | +//! @param move_x X軸移動量 | |
474 | +//! @param move_y Y軸移動量 | |
475 | +//! @param move_z Z軸移動量 | |
476 | +//! @param size 表示倍率 | |
477 | +//! @param rotation 回転角度 | |
478 | +//! @param count 表示フレーム数 | |
479 | +//! @param texture テクスチャの認識番号 | |
480 | +//! @param settype エフェクトの種類 (Effect_Type を組み合せる) | |
481 | +//! @return 成功:データ番号(0以上) 失敗:-1 | |
482 | +int ObjectManager::AddEffect(float pos_x, float pos_y, float pos_z, float move_x, float move_y, float move_z, float size, float rotation, int count, int texture, int settype) | |
483 | +{ | |
484 | + for(int i=0; i<MAX_EFFECT; i++){ | |
485 | + if( EffectIndex[i].GetDrawFlag() == false ){ | |
486 | + EffectIndex[i].SetPosData(pos_x, pos_y, pos_z, 0.0f); | |
487 | + EffectIndex[i].SetParamData(move_x, move_y, move_z, size, rotation, count, texture, settype, true); | |
488 | + EffectIndex[i].SetDrawFlag(true); | |
489 | + return i; | |
490 | + } | |
491 | + } | |
492 | + | |
493 | + return -1; | |
494 | +} | |
495 | + | |
496 | +//! @brief 出血させる | |
497 | +//! @param x X座標 | |
498 | +//! @param y Y座標 | |
499 | +//! @param z Z座標 | |
500 | +void ObjectManager::SetHumanBlood(float x, float y, float z) | |
501 | +{ | |
502 | + if( GameConfig.GetBloodFlag() == true ){ | |
503 | + for(int i=0; i<2; i++){ | |
504 | + float rx = (float)M_PI/18*GetRand(36); | |
505 | + AddEffect(x + cos(rx)*1.0f, y + (float)(GetRand(20)-10)/10, z + sin(rx)*1.0f, cos(rx)*0.5f, 0.5f, sin(rx)*0.5f, 10.0f, (float)M_PI/18*GetRand(18), (int)GAMEFPS * 1, Resource->GetEffectBloodTexture(), EFFECT_FALL); | |
506 | + } | |
507 | + } | |
508 | +} | |
509 | + | |
510 | +//! @brief 人同士の当たり判定 | |
511 | +//! @param in_humanA 対象の人オブジェクトA | |
512 | +//! @param in_humanB 対象の人オブジェクトB | |
513 | +//! @return 当たっている:true 当たっていない:false | |
514 | +//! @warning in_humanAとin_humanBで区別はありません。 | |
515 | +//! @warning in_humanAとin_humanBでの組み合せは、1フレーム間に1度だけ実行してください。 | |
516 | +//! @attention 両クラスは自動的にAddPosOrder()を用いて、お互いを押し合います。 | |
517 | +bool ObjectManager::CollideHuman(human *in_humanA, human *in_humanB) | |
518 | +{ | |
519 | + float h1_x, h1_y, h1_z; | |
520 | + float h2_x, h2_y, h2_z; | |
521 | + float angle, length; | |
522 | + | |
523 | + //初期化されていないか、死亡して入れば判定しない | |
524 | + if( in_humanA->GetDrawFlag() == false ){ return false; } | |
525 | + if( in_humanB->GetDrawFlag() == false ){ return false; } | |
526 | + if( in_humanA->GetHP() <= 0 ){ return false; } | |
527 | + if( in_humanB->GetHP() <= 0 ){ return false; } | |
528 | + | |
529 | + //お互いの座標を取得 | |
530 | + in_humanA->GetPosData(&h1_x, &h1_y, &h1_z, NULL); | |
531 | + in_humanB->GetPosData(&h2_x, &h2_y, &h2_z, NULL); | |
532 | + | |
533 | + //円柱の当たり判定 | |
534 | + if( CollideCylinder(h1_x, h1_y, h1_z, 3.0f, HUMAN_HEIGTH-0.5f, h2_x, h2_y, h2_z, 3.0f, HUMAN_HEIGTH-0.5f, &angle, &length) == true ){ | |
535 | + //めり込んだ分だけ押し出す | |
536 | + in_humanA->AddPosOrder(angle, 0.0f, length/2); | |
537 | + in_humanB->AddPosOrder(angle + (float)M_PI, 0.0f, length/2); | |
538 | + return true; | |
539 | + } | |
540 | + | |
541 | + return false; | |
542 | +} | |
543 | + | |
544 | +//! @brief 弾の当たり判定と処理 | |
545 | +//! @param in_bullet 対象の弾オブジェクト | |
546 | +//! @return 当たった:true 当たっていない:false | |
547 | +//! @attention 判定を行う対象は「マップ」「人(頭・上半身・下半身)」「小物」です。 | |
548 | +//! @attention 判定に限らず、ダメージ計算や効果音再生まで一貫して行います。 | |
549 | +bool ObjectManager::CollideBullet(bullet *in_bullet) | |
550 | +{ | |
551 | + //使用されていない弾丸ならば、処理せずに返す。 | |
552 | + if( in_bullet->GetDrawFlag() == false ){ return false; } | |
553 | + | |
554 | + float bx, by, bz; | |
555 | + float brx, bry; | |
556 | + int attacks; | |
557 | + int penetration; | |
558 | + int speed; | |
559 | + int teamid; | |
560 | + int humanid; | |
561 | + float vx, vy, vz; | |
562 | + int HumanHead_id; | |
563 | + int HumanUp_id; | |
564 | + int HumanLeg_id; | |
565 | + int SmallObject_id; | |
566 | + float map_Dist; | |
567 | + float HumanHead_Dist; | |
568 | + float HumanUp_Dist; | |
569 | + float HumanLeg_Dist; | |
570 | + float SmallObject_Dist; | |
571 | + float CheckDist; | |
572 | + bool CollideFlag; | |
573 | + | |
574 | + int id, face; | |
575 | + float Dist; | |
576 | + | |
577 | + //弾丸の座標を取得し、ベクトルを算出。 | |
578 | + in_bullet->GetPosData(&bx, &by, &bz, &brx, &bry); | |
579 | + in_bullet->GetParamData(&attacks, &penetration, &speed, &teamid, &humanid); | |
580 | + vx = cos(brx)*cos(bry); | |
581 | + vy = sin(bry); | |
582 | + vz = sin(brx)*cos(bry); | |
583 | + | |
584 | + CheckDist = 0; | |
585 | + CollideFlag = false; | |
586 | + | |
587 | + for(float TotalDist=0.0f; TotalDist<speed; TotalDist+=CheckDist){ | |
588 | + CheckDist = speed - TotalDist; | |
589 | + | |
590 | + //貫通力が残っていなければ | |
591 | + if( penetration < 0 ){ | |
592 | + //弾は無効にする | |
593 | + in_bullet->SetDrawFlag(false); | |
594 | + break; | |
595 | + } | |
596 | + | |
597 | + float bvx, bvy, bvz; | |
598 | + bvx = bx + vx*TotalDist; | |
599 | + bvy = by + vy*TotalDist; | |
600 | + bvz = bz + vz*TotalDist; | |
601 | + | |
602 | + HumanHead_id = -1; | |
603 | + HumanUp_id = -1; | |
604 | + HumanLeg_id = -1; | |
605 | + SmallObject_id = -1; | |
606 | + map_Dist = (float)speed - TotalDist + 1; | |
607 | + HumanHead_Dist = (float)speed - TotalDist + 1; | |
608 | + HumanUp_Dist = (float)speed - TotalDist + 1; | |
609 | + HumanLeg_Dist = (float)speed - TotalDist + 1; | |
610 | + SmallObject_Dist = (float)speed - TotalDist + 1; | |
611 | + | |
612 | + //マップとの当たり判定 | |
613 | + if( CollD->CheckALLBlockIntersectRay(bvx, bvy, bvz, vx, vy, vz, &id, &face, &Dist, (float)speed - TotalDist) == true ){ | |
614 | + map_Dist = Dist; | |
615 | + } | |
616 | + | |
617 | + //人との当たり判定 | |
618 | + for(int i=0; i<MAX_HUMAN; i++){ | |
619 | + //使用されていないか、死亡していれば処理しない。 | |
620 | + if( HumanIndex[i].GetDrawFlag() == false ){ continue; } | |
621 | + if( HumanIndex[i].GetHP() <= 0 ){ continue; } | |
622 | + | |
623 | + //座標を取得 | |
624 | + float ox, oy, oz; | |
625 | + int h_teamid; | |
626 | + HumanIndex[i].GetPosData(&ox, &oy, &oz, NULL); | |
627 | + HumanIndex[i].GetParamData(NULL, NULL, NULL, &h_teamid); | |
628 | + | |
629 | + //同じチーム番号(味方)なら処理しない | |
630 | + if( h_teamid == teamid ){ continue; } | |
631 | + | |
632 | + //人全体の当たり判定 | |
633 | + if( CollideAABBRay(ox-3.0f, oy, oz-3.0f, ox+3.0f, oy+HUMAN_HEIGTH, oz+3.0f, bvx, bvy, bvz, vx, vy, vz, &Dist, (float)speed - TotalDist) == true ){ | |
634 | + | |
635 | + //頭の当たり判定 | |
636 | + if( CollideAABBRay(ox-1.0f, oy+17.5f, oz-1.0f, ox+1.0f, oy+20.0f, oz+1.0f, bvx, bvy, bvz, vx, vy, vz, &Dist, (float)speed - TotalDist) == true ){ | |
637 | + if( Dist < HumanHead_Dist ){ | |
638 | + HumanHead_id = i; | |
639 | + HumanHead_Dist = Dist; | |
640 | + } | |
641 | + } | |
642 | + | |
643 | + //上半身と当たり判定 | |
644 | + if( CollideAABBRay(ox-3.0f, oy+10.0f, oz-3.0f, ox+3.0f, oy+17.5f, oz+3.0f, bvx, bvy, bvz, vx, vy, vz, &Dist, (float)speed - TotalDist) == true ){ | |
645 | + if( Dist < HumanUp_Dist ){ | |
646 | + HumanUp_id = i; | |
647 | + HumanUp_Dist = Dist; | |
648 | + } | |
649 | + } | |
650 | + | |
651 | + //足と当たり判定 | |
652 | + if( CollideAABBRay(ox-3.0f, oy, oz-3.0f, ox+3.0f, oy+10.0f, oz+3.0f, bvx, bvy, bvz, vx, vy, vz, &Dist, (float)speed - TotalDist) == true ){ | |
653 | + if( Dist < HumanLeg_Dist ){ | |
654 | + HumanLeg_id = i; | |
655 | + HumanLeg_Dist = Dist; | |
656 | + } | |
657 | + } | |
658 | + | |
659 | + } | |
660 | + } | |
661 | + | |
662 | + //小物との当たり判定 | |
663 | + for(int i=0; i<MAX_SMALLOBJECT; i++){ | |
664 | + //使用されていなければ処理しない | |
665 | + if( SmallObjectIndex[i].GetDrawFlag() == false ){ continue; } | |
666 | + | |
667 | + //座標を取得 | |
668 | + float ox, oy, oz; | |
669 | + int id; | |
670 | + float decide; | |
671 | + SmallObjectIndex[i].GetPosData(&ox, &oy, &oz, NULL); | |
672 | + SmallObjectIndex[i].GetParamData(&id, NULL); | |
673 | + | |
674 | + //当たり判定の大きさを取得 | |
675 | + if( id == TOTAL_PARAMETERINFO_SMALLOBJECT+1 -1 ){ | |
676 | + decide = (float)MIFdata->GetAddSmallobjectDecide()*SMALLOBJECT_SCALE; | |
677 | + } | |
678 | + else{ | |
679 | + SmallObjectParameter Param; | |
680 | + GameParamInfo->GetSmallObject(id, &Param); | |
681 | + decide = (float)Param.decide*SMALLOBJECT_SCALE; | |
682 | + } | |
683 | + | |
684 | + //当たり判定 | |
685 | + if( CollideSphereRay(ox, oy, oz, decide, bvx, bvy, bvz, vx, vy, vz, &Dist, (float)speed - TotalDist) == true ){ | |
686 | + if( Dist < SmallObject_Dist ){ | |
687 | + SmallObject_id = i; | |
688 | + SmallObject_Dist = Dist; | |
689 | + } | |
690 | + } | |
691 | + } | |
692 | + | |
693 | + //マップとの衝突距離が最短ならば〜 | |
694 | + if( (map_Dist <= speed)&&(map_Dist < HumanHead_Dist)&&(map_Dist < HumanUp_Dist)&&(map_Dist < HumanLeg_Dist)&&(map_Dist < SmallObject_Dist) ){ | |
695 | + //弾がマップに当たった処理 | |
696 | + HitBulletMap(bx + vx*(map_Dist+TotalDist), by + vy*(map_Dist+TotalDist), bz + vz*(map_Dist+TotalDist)); | |
697 | + | |
698 | + int Penetration_Dist; | |
699 | + | |
700 | + //マップにめり込んでいる量を調べる | |
701 | + // 最終地点がマップにめり込んでいるならば | |
702 | + if( CollD->CheckALLBlockIntersectRay(bx + vx*speed, by + vy*speed, bz + vz*speed, vx*-1, vy*-1, vz*-1, &id, &face, &Dist, (float)speed - map_Dist+TotalDist) == true ){ | |
703 | + //発射地点と最終地点、それぞれからの激突点から貫通距離を求める | |
704 | + Penetration_Dist = (int)( ((float)speed - map_Dist+TotalDist - Dist) / 2 ); | |
705 | + } | |
706 | + else{ | |
707 | + //衝突点から最終地点まで移動距離 | |
708 | + Penetration_Dist = (int)( ((float)speed - map_Dist+TotalDist) / 2 ); | |
709 | + } | |
710 | + | |
711 | + //攻撃力と貫通力を計算 | |
712 | + for(int i=0; i<Penetration_Dist; i++){ | |
713 | + attacks = (int)((float)attacks * 0.6f); | |
714 | + } | |
715 | + penetration -= Penetration_Dist; | |
716 | + | |
717 | + CheckDist = map_Dist + 1.0f; | |
718 | + } | |
719 | + | |
720 | + //人の頭との衝突距離が最短ならば〜 | |
721 | + if( (HumanHead_Dist <= speed)&&(HumanHead_Dist < map_Dist)&&(HumanHead_Dist < HumanUp_Dist)&&(HumanHead_Dist < HumanLeg_Dist)&&(HumanHead_Dist < SmallObject_Dist) ){ | |
722 | + //人に当たった処理 | |
723 | + HitBulletHuman(HumanHead_id, 0, bx + vx*(HumanHead_Dist+TotalDist), by + vy*(HumanHead_Dist+TotalDist), bz + vz*(HumanHead_Dist+TotalDist), brx, attacks, humanid); | |
724 | + | |
725 | + //攻撃力と貫通力を計算 | |
726 | + attacks = (int)((float)attacks * 0.6f); | |
727 | + penetration -= 1; | |
728 | + | |
729 | + CheckDist = HumanHead_Dist + 1.0f; | |
730 | + } | |
731 | + | |
732 | + //人の上半身との衝突距離が最短ならば〜 | |
733 | + if( (HumanUp_Dist <= speed)&&(HumanUp_Dist < map_Dist)&&(HumanUp_Dist < HumanHead_Dist)&&(HumanUp_Dist < HumanLeg_Dist)&&(HumanUp_Dist < SmallObject_Dist) ){ | |
734 | + //人に当たった処理 | |
735 | + HitBulletHuman(HumanUp_id, 1, bx + vx*(HumanUp_Dist+TotalDist), by + vy*(HumanUp_Dist+TotalDist), bz + vz*(HumanUp_Dist+TotalDist), brx, attacks, humanid); | |
736 | + | |
737 | + //攻撃力と貫通力を計算 | |
738 | + attacks = (int)((float)attacks * 0.6f); | |
739 | + penetration -= 1; | |
740 | + | |
741 | + CheckDist = HumanUp_Dist + 1.0f; | |
742 | + } | |
743 | + | |
744 | + //人の足との衝突距離が最短ならば〜 | |
745 | + if( (HumanLeg_Dist <= speed)&&(HumanLeg_Dist < map_Dist)&&(HumanLeg_Dist < HumanHead_Dist)&&(HumanLeg_Dist < HumanUp_Dist)&&(HumanLeg_Dist < SmallObject_Dist) ){ | |
746 | + //人に当たった処理 | |
747 | + HitBulletHuman(HumanLeg_id, 2, bx + vx*(HumanLeg_Dist+TotalDist), by + vy*(HumanLeg_Dist+TotalDist), bz + vz*(HumanLeg_Dist+TotalDist), brx, attacks, humanid); | |
748 | + | |
749 | + //攻撃力と貫通力を計算 | |
750 | + attacks = (int)((float)attacks * 0.7f); | |
751 | + penetration -= 1; | |
752 | + | |
753 | + CheckDist = HumanLeg_Dist + 1.0f; | |
754 | + } | |
755 | + | |
756 | + //小物との衝突距離が最短ならば〜 | |
757 | + if( (SmallObject_Dist <= speed)&&(SmallObject_Dist < map_Dist)&&(SmallObject_Dist < HumanHead_Dist)&&(SmallObject_Dist < HumanUp_Dist)&&(SmallObject_Dist < HumanLeg_Dist) ){ | |
758 | + //小物に当たった処理 | |
759 | + HitBulletSmallObject(SmallObject_id, bx + vx*(SmallObject_Dist+TotalDist), by + vy*(SmallObject_Dist+TotalDist), bz + vz*(SmallObject_Dist+TotalDist), attacks); | |
760 | + | |
761 | + //小物の種類番号を取得 | |
762 | + int id; | |
763 | + int decide; | |
764 | + SmallObjectIndex[SmallObject_id].GetParamData(&id, NULL); | |
765 | + | |
766 | + //小物の設定値を取得 | |
767 | + SmallObjectParameter Param; | |
768 | + GameParamInfo->GetSmallObject(id, &Param); | |
769 | + decide = (int)( (float)Param.decide*SMALLOBJECT_SCALE ); | |
770 | + | |
771 | + //貫通力を計算 | |
772 | + for(int i=0; i<decide; i++){ | |
773 | + attacks = (int)((float)attacks * 0.7f); | |
774 | + } | |
775 | + | |
776 | + CheckDist = SmallObject_Dist + 1.0f; | |
777 | + } | |
778 | + | |
779 | + //設定を適用(特に攻撃力・貫通力) | |
780 | + in_bullet->SetParamData(attacks, penetration, speed, teamid, humanid, false); | |
781 | + } | |
782 | + | |
783 | + return CollideFlag; | |
784 | +} | |
785 | + | |
786 | +//! @brief 弾がマップに当たった処理 | |
787 | +//! @param x 着弾X座標 | |
788 | +//! @param y 着弾Y座標 | |
789 | +//! @param z 着弾Z座標 | |
790 | +void ObjectManager::HitBulletMap(float x, float y, float z) | |
791 | +{ | |
792 | + //エフェクト(煙)を表示 | |
793 | + AddEffect(x, y, z, 0.0f, 0.05f, 0.0f, 5.0f, (float)M_PI/18*GetRand(18), (int)(GAMEFPS * 0.5f), Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY); | |
794 | + | |
795 | + //効果音を再生 | |
796 | + GameSound->HitMap(x, y, z); | |
797 | +} | |
798 | + | |
799 | +//! @brief 弾が人に当たった処理 | |
800 | +//! @param HitHuman_id 人の番号 | |
801 | +//! @param Hit_id 被弾箇所(頭:0 胴体:1 足:2) | |
802 | +//! @param x 被弾X座標 | |
803 | +//! @param y 被弾Y座標 | |
804 | +//! @param z 被弾Z座標 | |
805 | +//! @param brx 水平角度 | |
806 | +//! @param attacks 攻撃力 | |
807 | +//! @param Shothuman_id 発射した人の番号 | |
808 | +void ObjectManager::HitBulletHuman(int HitHuman_id, int Hit_id, float x, float y, float z, float brx, int attacks, int Shothuman_id) | |
809 | +{ | |
810 | + //使用されていないか、死亡していれば処理しない。 | |
811 | + if( HumanIndex[HitHuman_id].GetDrawFlag() == false ){ return; } | |
812 | + if( HumanIndex[HitHuman_id].GetHP() <= 0 ){ return; } | |
813 | + | |
814 | + //人にダメージと衝撃を与える | |
815 | + if( Hit_id == 0 ){ HumanIndex[HitHuman_id].HitBulletHead(attacks); } | |
816 | + if( Hit_id == 1 ){ HumanIndex[HitHuman_id].HitBulletUp(attacks); } | |
817 | + if( Hit_id == 2 ){ HumanIndex[HitHuman_id].HitBulletLeg(attacks); } | |
818 | + HumanIndex[HitHuman_id].AddPosOrder(brx, 0.0f, 1.0f); | |
819 | + | |
820 | + //エフェクト(血)を表示 | |
821 | + SetHumanBlood(x, y, z); | |
822 | + | |
823 | + //効果音を再生 | |
824 | + GameSound->HitHuman(x, y, z); | |
825 | + | |
826 | + //弾を発射した人の成果に加算 | |
827 | + Human_ontarget[Shothuman_id] += 1; | |
828 | + if( Hit_id == 0 ){ Human_headshot[Shothuman_id] += 1; } | |
829 | + if( HumanIndex[HitHuman_id].GetHP() <= 0 ){ | |
830 | + Human_kill[Shothuman_id] += 1; | |
831 | + } | |
832 | +} | |
833 | + | |
834 | +//! @brief 弾が小物に当たった処理 | |
835 | +//! @param HitSmallObject_id 小物の番号 | |
836 | +//! @param x 着弾X座標 | |
837 | +//! @param y 着弾Y座標 | |
838 | +//! @param z 着弾Z座標 | |
839 | +//! @param attacks 攻撃力 | |
840 | +void ObjectManager::HitBulletSmallObject(int HitSmallObject_id, float x, float y, float z, int attacks) | |
841 | +{ | |
842 | + int hp; | |
843 | + | |
844 | + //使用されていなければ処理しない。 | |
845 | + if( SmallObjectIndex[HitSmallObject_id].GetDrawFlag() == false ){ return; } | |
846 | + | |
847 | + //体力がなければ処理しない | |
848 | + hp = SmallObjectIndex[HitSmallObject_id].GetHP(); | |
849 | + if( hp <= 0 ){ return; } | |
850 | + | |
851 | + //小物にダメージを与える | |
852 | + SmallObjectIndex[HitSmallObject_id].HitBullet(attacks); | |
853 | + | |
854 | + //エフェクト(煙)を表示 | |
855 | + AddEffect(x, y, z, 0.0f, 0.05f, 0.0f, 5.0f, (float)M_PI/18*GetRand(18), (int)(GAMEFPS * 0.5f), Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY); | |
856 | + | |
857 | + //効果音を再生 | |
858 | + int id; | |
859 | + SmallObjectIndex[HitSmallObject_id].GetParamData(&id, NULL); | |
860 | + GameSound->HitSmallObject(x, y, z, id); | |
861 | +} | |
862 | + | |
863 | +//! @brief 手榴弾のダメージ判定と処理 | |
864 | +//! @param in_grenade 対象の手榴弾オブジェクト | |
865 | +//! @return 当たった:true 当たっていない:false | |
866 | +//! @attention 判定を行う対象は「人」と「小物」です。 | |
867 | +//! @attention ダメージ判定に限らず、ダメージ計算や効果音再生まで一貫して行います。 | |
868 | +bool ObjectManager::GrenadeExplosion(grenade *in_grenade) | |
869 | +{ | |
870 | + bool returnflag = false; | |
871 | + | |
872 | + //座標を取得 | |
873 | + float gx, gy, gz; | |
874 | + int humanid; | |
875 | + in_grenade->GetPosData(&gx, &gy, &gz, NULL, NULL); | |
876 | + in_grenade->GetParamData(NULL, NULL, NULL, NULL, &humanid); | |
877 | + | |
878 | + //人に爆風の当たり判定 | |
879 | + for(int i=0; i<MAX_HUMAN; i++){ | |
880 | + //初期化されていないか、死亡していれば処理しない。 | |
881 | + if( HumanIndex[i].GetDrawFlag() == false ){ continue; } | |
882 | + if( HumanIndex[i].GetHP() <= 0 ){ continue; } | |
883 | + | |
884 | + float hx, hy, hz; | |
885 | + float x, y, z, r; | |
886 | + | |
887 | + //人の座標を取得し、距離を計算 | |
888 | + HumanIndex[i].GetPosData(&hx, &hy, &hz, NULL); | |
889 | + x = hx - gx; | |
890 | + y = hy - gy; | |
891 | + z = hz - gz; | |
892 | + r = sqrt(x*x + y*y + z*z); | |
893 | + | |
894 | + //100.0より遠ければ計算しない | |
895 | + if( r > MAX_DAMAGE_GRENADE_DISTANCE + HUMAN_HEIGTH ){ continue; } | |
896 | + | |
897 | + float dummy = 0.0f; | |
898 | + int total_damage = 0; | |
899 | + int damage; | |
900 | + | |
901 | + //足元に当たり判定 | |
902 | + y = hy + 2.0f - gy; | |
903 | + r = sqrt(x*x + y*y + z*z); | |
904 | + //ブロックが遮っていなければ (レイで当たり判定を行い、当たっていなければ) | |
905 | + if( CollD->CheckALLBlockIntersectRay(gx, gy, gz, x/r, y/r, z/r, NULL, NULL, &dummy, r) == false ){ | |
906 | + //ダメージ量を計算 | |
907 | + damage = HUMAN_DAMAGE_GRENADE_LEG - (int)((float)HUMAN_DAMAGE_GRENADE_LEG/MAX_DAMAGE_GRENADE_DISTANCE * r); | |
908 | + if( damage > 0 ){ | |
909 | + total_damage += damage; | |
910 | + } | |
911 | + } | |
912 | + | |
913 | + //頭に当たり判定 | |
914 | + y = hy + 18.0f - gy; | |
915 | + r = sqrt(x*x + y*y + z*z); | |
916 | + //ブロックが遮っていなければ (レイで当たり判定を行い、当たっていなければ) | |
917 | + if( CollD->CheckALLBlockIntersectRay(gx, gy, gz, x/r, y/r, z/r, NULL, NULL, &dummy, r) == false ){ | |
918 | + //ダメージ量を計算 | |
919 | + damage = HUMAN_DAMAGE_GRENADE_HEAD - (int)((float)HUMAN_DAMAGE_GRENADE_HEAD/MAX_DAMAGE_GRENADE_DISTANCE * r); | |
920 | + if( damage > 0 ){ | |
921 | + total_damage += damage; | |
922 | + } | |
923 | + } | |
924 | + | |
925 | + if( total_damage > 0 ){ | |
926 | + //ダメージを反映 | |
927 | + HumanIndex[i].HitGrenadeExplosion(total_damage); | |
928 | + | |
929 | + float y2; | |
930 | + float arx, ary; | |
931 | + | |
932 | + //倒していれば、発射した人の成果に加算 | |
933 | + if( HumanIndex[i].GetHP() <= 0 ){ | |
934 | + Human_kill[humanid] += 1; | |
935 | + } | |
936 | + | |
937 | + //エフェクト(血)を表示 | |
938 | + SetHumanBlood(hx, hy+15.0f, hz); | |
939 | + | |
940 | + //人と手榴弾の距離を算出 | |
941 | + x = gx - hx; | |
942 | + y = gy - (hy + 1.0f); | |
943 | + z = gz - hz; | |
944 | + | |
945 | + //角度を求める | |
946 | + arx = atan2(z, x); | |
947 | + | |
948 | + if( sin(atan2(y, sqrt(x*x + z*z))) < 0.0f ){ //上方向に飛ぶなら、角度を計算 | |
949 | + y2 = gy - (hy + HUMAN_HEIGTH); | |
950 | + ary = atan2(y2, sqrt(x*x + z*z)) + (float)M_PI; | |
951 | + } | |
952 | + else{ //下方向に飛ぶなら、垂直角度は無効。(爆風で地面にめり込むのを防止) | |
953 | + ary = 0.0f; | |
954 | + } | |
955 | + | |
956 | + //爆風による風圧 | |
957 | + HumanIndex[i].AddPosOrder(arx, ary, 2.2f/MAX_DAMAGE_GRENADE_DISTANCE * (MAX_DAMAGE_GRENADE_DISTANCE - sqrt(x*x + y*y + z*z))); | |
958 | + | |
959 | + returnflag = true; | |
960 | + } | |
961 | + } | |
962 | + | |
963 | + //小物に爆風の当たり判定 | |
964 | + for(int i=0; i<MAX_SMALLOBJECT; i++){ | |
965 | + //使用されていれば処理しない | |
966 | + if( SmallObjectIndex[i].GetDrawFlag() == false ){ continue; } | |
967 | + | |
968 | + float sx, sy, sz; | |
969 | + float x, y, z, r; | |
970 | + | |
971 | + //小物の座標を取得し、距離を計算 | |
972 | + SmallObjectIndex[i].GetPosData(&sx, &sy, &sz, NULL); | |
973 | + x = sx - gx; | |
974 | + y = sy - gy; | |
975 | + z = sz - gz; | |
976 | + r = sqrt(x*x + y*y + z*z); | |
977 | + | |
978 | + //100.0より遠ければ計算しない | |
979 | + if( r > MAX_DAMAGE_GRENADE_DISTANCE ){ continue; } | |
980 | + | |
981 | + float dummy = 0.0f; | |
982 | + | |
983 | + //ブロックが遮っていなければ (レイで当たり判定を行い、当たっていなければ) | |
984 | + if( CollD->CheckALLBlockIntersectRay(gx, gy, gz, x/r, y/r, z/r, NULL, NULL, &dummy, r) == false ){ | |
985 | + int id, damage; | |
986 | + SmallObjectIndex[i].GetParamData(&id, NULL); | |
987 | + | |
988 | + //ダメージ量を計算し、反映 | |
989 | + damage = SMALLOBJECT_DAMAGE_GRENADE - (int)((float)SMALLOBJECT_DAMAGE_GRENADE/MAX_DAMAGE_GRENADE_DISTANCE * r); | |
990 | + SmallObjectIndex[i].HitGrenadeExplosion(damage); | |
991 | + | |
992 | + //小物から効果音を発する | |
993 | + GameSound->HitSmallObject(sx, sy, sz, id); | |
994 | + | |
995 | + returnflag = true; | |
996 | + } | |
997 | + } | |
998 | + | |
999 | + //エフェクト(フラッシュ)の表示 | |
1000 | + AddEffect(gx, gy, gz, 0.0f, 0.0f, 0.0f, 30.0f, 0.0f, 2, Resource->GetEffectMflashTexture(), EFFECT_NORMAL); | |
1001 | + | |
1002 | + //エフェクト(煙)の表示 | |
1003 | + float rnd = (float)M_PI/18*GetRand(18); | |
1004 | + AddEffect(gx+1.0f, gy+1.0f, gz+1.0f, 0.0f, 0.05f, 0.0f, 10.0f, rnd, (int)GAMEFPS * 3, Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY | EFFECT_ROTATION); | |
1005 | + AddEffect(gx-1.0f, gy-1.0f, gz-1.0f, 0.0f, 0.05f, 0.0f, 10.0f, rnd*-1, (int)GAMEFPS * 3, Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY | EFFECT_ROTATION); | |
1006 | + AddEffect(gx-1.0f, gy-1.0f, gz+1.0f, 0.0f, 0.05f, 0.0f, 10.0f, rnd, (int)GAMEFPS * 3, Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY | EFFECT_ROTATION); | |
1007 | + AddEffect(gx+1.0f, gy+1.0f, gz-1.0f, 0.0f, 0.05f, 0.0f, 10.0f, rnd*-1, (int)GAMEFPS * 3, Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY | EFFECT_ROTATION); | |
1008 | + | |
1009 | + //効果音を再生 | |
1010 | + GameSound->GrenadeExplosion(gx, gy, gz); | |
1011 | + | |
1012 | + return returnflag; | |
1013 | +} | |
1014 | + | |
1015 | +//! @brief 倒れた際のエフェクト設定 | |
1016 | +//! @param in_human 対象の人オブジェクト | |
1017 | +void ObjectManager::DeadEffect(human *in_human) | |
1018 | +{ | |
1019 | + if( in_human == NULL ){ return; } | |
1020 | + | |
1021 | + int paramid; | |
1022 | + float hx, hy, hz, hrx, hry; | |
1023 | + HumanParameter data; | |
1024 | + | |
1025 | + //各種パラメーターを取得 | |
1026 | + in_human->GetParamData(¶mid, NULL, NULL, NULL); | |
1027 | + in_human->GetPosData(&hx, &hy, &hz, &hrx); | |
1028 | + hry = in_human->GetDeadRy(); | |
1029 | + | |
1030 | + //設定値を取得 | |
1031 | + if( GameParamInfo->GetHuman(paramid, &data) != 0 ){ return; } | |
1032 | + | |
1033 | + //もしロボットならば | |
1034 | + if( data.type == 1 ){ | |
1035 | + | |
1036 | + //腰辺りの座標を算出 | |
1037 | + hx += cos(hrx*-1 - (float)M_PI/2) * sin(hry) * HUMAN_HEIGTH/2; | |
1038 | + hz += sin(hrx*-1 - (float)M_PI/2) * sin(hry) * HUMAN_HEIGTH/2; | |
1039 | + | |
1040 | + //エフェクト(煙)の表示 | |
1041 | + float rnd = (float)M_PI/18*GetRand(18); | |
1042 | + AddEffect(hx+1.0f, hy+1.0f, hz+1.0f, 0.0f, 0.05f, 0.0f, 10.0f, rnd, (int)GAMEFPS * 3, Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY | EFFECT_ROTATION); | |
1043 | + AddEffect(hx-1.0f, hy-1.0f, hz-1.0f, 0.0f, 0.05f, 0.0f, 10.0f, rnd*-1, (int)GAMEFPS * 3, Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY | EFFECT_ROTATION); | |
1044 | + AddEffect(hx-1.0f, hy-1.0f, hz+1.0f, 0.0f, 0.05f, 0.0f, 10.0f, rnd, (int)GAMEFPS * 3, Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY | EFFECT_ROTATION); | |
1045 | + AddEffect(hx+1.0f, hy+1.0f, hz-1.0f, 0.0f, 0.05f, 0.0f, 10.0f, rnd*-1, (int)GAMEFPS * 3, Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY | EFFECT_ROTATION); | |
1046 | + } | |
1047 | +} | |
1048 | + | |
1049 | +//! @brief 武器を拾う | |
1050 | +//! @param in_human 対象の人オブジェクト | |
1051 | +//! @param in_weapon 対象の武器オブジェクト | |
1052 | +void ObjectManager::PickupWeapon(human *in_human, weapon *in_weapon) | |
1053 | +{ | |
1054 | + //無効な人ならば処理しない | |
1055 | + if( in_human->GetDrawFlag() == false ){ return; } | |
1056 | + if( in_human->GetHP() <= 0 ){ return; } | |
1057 | + | |
1058 | + //初期化されている武器で、かつ誰も使っていない武器ならば〜 | |
1059 | + if( (in_weapon->GetDrawFlag() == true)&&(in_weapon->GetUsingFlag() == false) ){ | |
1060 | + float human_x, human_y, human_z; | |
1061 | + float weapon_x, weapon_y, weapon_z; | |
1062 | + float x, z; | |
1063 | + float r; | |
1064 | + | |
1065 | + //人と武器の座標を取得 | |
1066 | + in_human->GetPosData(&human_x, &human_y, &human_z, NULL); | |
1067 | + in_weapon->GetPosData(&weapon_x, &weapon_y, &weapon_z, NULL); | |
1068 | + | |
1069 | + //高さが範囲内ならば | |
1070 | + if( (human_y-2.0f <= weapon_y)&&(human_y+16.0f > weapon_y) ){ | |
1071 | + //距離を計算 | |
1072 | + x = human_x - weapon_x; | |
1073 | + z = human_z - weapon_z; | |
1074 | + r = x*x + z*z; | |
1075 | + //距離も範囲内ならば、拾わせる。 | |
1076 | + if( r < (5.0f * 5.0f) ){ | |
1077 | + in_human->PickupWeapon(in_weapon); | |
1078 | + } | |
1079 | + } | |
1080 | + } | |
1081 | +} | |
1082 | + | |
1083 | +//! @brief オブジェクトを解放 | |
1084 | +void ObjectManager::CleanupPointDataToObject() | |
1085 | +{ | |
1086 | + for(int i=0; i<MAX_HUMAN; i++){ | |
1087 | + HumanIndex[i].SetDrawFlag(false); | |
1088 | + } | |
1089 | + | |
1090 | + for(int i=0; i<MAX_WEAPON; i++){ | |
1091 | + WeaponIndex[i].SetDrawFlag(false); | |
1092 | + } | |
1093 | + | |
1094 | + for(int i=0; i<MAX_SMALLOBJECT; i++){ | |
1095 | + SmallObjectIndex[i].SetDrawFlag(false); | |
1096 | + } | |
1097 | + | |
1098 | + for(int i=0; i<MAX_BULLET; i++){ | |
1099 | + BulletIndex[i].SetDrawFlag(false); | |
1100 | + } | |
1101 | + | |
1102 | + for(int i=0; i<MAX_GRENADE; i++){ | |
1103 | + GrenadeIndex[i].SetDrawFlag(false); | |
1104 | + } | |
1105 | + | |
1106 | + for(int i=0; i<MAX_EFFECT; i++){ | |
1107 | + EffectIndex[i].SetDrawFlag(false); | |
1108 | + } | |
1109 | + | |
1110 | + | |
1111 | + if( Resource != NULL ){ | |
1112 | + Resource->CleanupHumanTexture(); | |
1113 | + } | |
1114 | +} | |
1115 | + | |
1116 | +//! @brief ポイントデータを元にオブジェクトを配置 | |
1117 | +void ObjectManager::LoadPointData() | |
1118 | +{ | |
1119 | + Player_HumanID = 0; | |
1120 | + | |
1121 | + /* | |
1122 | + //人情報ポイントを探す | |
1123 | + for(int i=0; i<PointData->GetTotaldatas(); i++){ | |
1124 | + pointdata data; | |
1125 | + PointData->Getdata(&data, i); | |
1126 | + | |
1127 | + if( data.p1 == 4 ){ | |
1128 | + //人のテクスチャを登録 | |
1129 | + Resource->AddHumanTexture(data.p2); | |
1130 | + } | |
1131 | + } | |
1132 | + */ | |
1133 | + | |
1134 | + //人・武器・小物を探す | |
1135 | + for(int i=0; i<PointData->GetTotaldatas(); i++){ | |
1136 | + pointdata data; | |
1137 | + PointData->Getdata(&data, i); | |
1138 | + | |
1139 | + //人ならば | |
1140 | + if( (data.p1 == 1)||(data.p1 == 6) ){ | |
1141 | + pointdata humaninfodata; | |
1142 | + | |
1143 | + //人情報ポイントを探す | |
1144 | + if( PointData->SearchPointdata(&humaninfodata, 0x01 + 0x08, 4, 0, 0, data.p2, 0) == 0 ){ | |
1145 | + //continue; | |
1146 | + | |
1147 | + //人情報ポイントが見つからなかったら、とりあえず「特殊 黒 A」として追加。(バグの再現) | |
1148 | + | |
1149 | + HumanParameter HumanParam; | |
1150 | + int Weapon[TOTAL_HAVEWEAPON]; | |
1151 | + GameParamInfo->GetHuman(0, &HumanParam); | |
1152 | + for(int j=0; j<TOTAL_HAVEWEAPON; j++){ | |
1153 | + Weapon[j] = HumanParam.Weapon[j]; | |
1154 | + } | |
1155 | + | |
1156 | + //人のテクスチャを登録 | |
1157 | + Resource->AddHumanTexture(0); | |
1158 | + | |
1159 | + //人を追加 | |
1160 | + if( data.p1 == 6 ){ | |
1161 | + Weapon[1] = ID_WEAPON_NONE; | |
1162 | + } | |
1163 | + | |
1164 | + //プレイヤーならば、番号を記録 | |
1165 | + if( (data.p4 == 0)&&(Player_HumanID == 0) ){ | |
1166 | + Player_HumanID = AddHumanIndex(data.x, data.y, data.z, data.r, 0, i, Weapon); | |
1167 | + } | |
1168 | + else{ | |
1169 | + AddHumanIndex(data.x, data.y, data.z, data.r, 0, i, Weapon); | |
1170 | + } | |
1171 | + } | |
1172 | + else{ | |
1173 | + //人のテクスチャを登録 | |
1174 | + Resource->AddHumanTexture(humaninfodata.p2); | |
1175 | + | |
1176 | + //人として追加 | |
1177 | + AddHumanIndex(data, humaninfodata); | |
1178 | + } | |
1179 | + } | |
1180 | + | |
1181 | + //武器ならば | |
1182 | + if( (data.p1 == 2)||(data.p1 == 7) ){ | |
1183 | + AddWeaponIndex(data); | |
1184 | + } | |
1185 | + | |
1186 | + //小物ならば | |
1187 | + if( data.p1 == 5 ){ | |
1188 | + AddSmallObjectIndex(data); | |
1189 | + } | |
1190 | + } | |
1191 | +} | |
1192 | + | |
1193 | +//! @brief プレイヤー番号を取得 | |
1194 | +//! @return プレイヤーのデータ番号 | |
1195 | +int ObjectManager::GetPlayerID() | |
1196 | +{ | |
1197 | + return Player_HumanID; | |
1198 | +} | |
1199 | + | |
1200 | +//! @brief プレイヤー番号を設定 | |
1201 | +//! @param id プレイヤーのデータ番号 | |
1202 | +void ObjectManager::SetPlayerID(int id) | |
1203 | +{ | |
1204 | + Player_HumanID = id; | |
1205 | +} | |
1206 | + | |
1207 | +//! @brief 指定したデータ番号のhumanクラスを取得 | |
1208 | +//! @param id データ番号 | |
1209 | +//! @return 人オブジェクトのポインタ (無効なデータ番号で NULL) | |
1210 | +human* ObjectManager::GeHumanObject(int id) | |
1211 | +{ | |
1212 | + if( (id < 0)||(MAX_HUMAN-1 < id) ){ return NULL; } | |
1213 | + return &(HumanIndex[id]); | |
1214 | +} | |
1215 | + | |
1216 | +//! @brief プレイヤーのhumanクラスを取得 | |
1217 | +//! @return 人オブジェクト(プレイヤー)のポインタ | |
1218 | +human* ObjectManager::GetPlayerHumanObject() | |
1219 | +{ | |
1220 | + return GeHumanObject(Player_HumanID); | |
1221 | +} | |
1222 | + | |
1223 | +//! @brief 指定したデータ番号のweaponクラスを取得 | |
1224 | +//! @param id データ番号 | |
1225 | +//! @return 武器オブジェクトのポインタ (無効なデータ番号で NULL) | |
1226 | +weapon* ObjectManager::GetWeaponObject(int id) | |
1227 | +{ | |
1228 | + if( (id < 0)||(MAX_WEAPON-1 < id) ){ return NULL; } | |
1229 | + return &(WeaponIndex[id]); | |
1230 | +} | |
1231 | + | |
1232 | +//! @brief 指定したデータ番号のsmallobjectクラスを取得 | |
1233 | +//! @param id データ番号 | |
1234 | +//! @return 小物オブジェクトのポインタ (無効なデータ番号で NULL) | |
1235 | +smallobject* ObjectManager::GetSmallObject(int id) | |
1236 | +{ | |
1237 | + if( (id < 0)||(MAX_SMALLOBJECT-1 < id) ){ return NULL; } | |
1238 | + return &(SmallObjectIndex[id]); | |
1239 | +} | |
1240 | + | |
1241 | +//! @brief 指定したデータ番号のbulletクラスを取得 | |
1242 | +//! @param id データ番号 | |
1243 | +//! @return 弾オブジェクトのポインタ (無効なデータ番号で NULL) | |
1244 | +bullet* ObjectManager::GetBulletObject(int id) | |
1245 | +{ | |
1246 | + if( (id < 0)||(MAX_BULLET-1 < id) ){ return NULL; } | |
1247 | + return &(BulletIndex[id]); | |
1248 | +} | |
1249 | + | |
1250 | +//! @brief 使用されていないbulletクラスを取得 | |
1251 | +//! @return 現在未使用の弾オブジェクトのポインタ (失敗すると NULL) | |
1252 | +bullet* ObjectManager::GetNewBulletObject() | |
1253 | +{ | |
1254 | + for(int i=0; i<MAX_BULLET; i++){ | |
1255 | + if( BulletIndex[i].GetDrawFlag() == false ){ | |
1256 | + return &(BulletIndex[i]); | |
1257 | + } | |
1258 | + } | |
1259 | + return NULL; | |
1260 | +} | |
1261 | + | |
1262 | +//! @brief 使用されていないgrenadeクラスを取得 | |
1263 | +//! @return 現在未使用の手榴弾オブジェクトのポインタ (失敗すると NULL) | |
1264 | +grenade* ObjectManager::GetNewGrenadeObject() | |
1265 | +{ | |
1266 | + for(int i=0; i<MAX_GRENADE; i++){ | |
1267 | + if( GrenadeIndex[i].GetDrawFlag() == false ){ | |
1268 | + return &(GrenadeIndex[i]); | |
1269 | + } | |
1270 | + } | |
1271 | + return NULL; | |
1272 | +} | |
1273 | + | |
1274 | +//! @brief 人を検索 | |
1275 | +//! @param p4 検索対象の認識番号 | |
1276 | +//! @return 該当したhumanクラスのポインタ (見つからない場合はNULL) | |
1277 | +//! @attention 複数該当する場合、最初に該当したデータを返します。 | |
1278 | +human* ObjectManager::SearchHuman(signed char p4) | |
1279 | +{ | |
1280 | + signed char humanp4; | |
1281 | + | |
1282 | + for(int i=0; i<MAX_HUMAN; i++){ | |
1283 | + //使われていない人ならば処理しない | |
1284 | + if( HumanIndex[i].GetDrawFlag() == false ){ continue; } | |
1285 | + | |
1286 | + //第4パラメータを取得 | |
1287 | + HumanIndex[i].GetParamData(NULL, NULL, &humanp4, NULL); | |
1288 | + | |
1289 | + //指定されたp4と一致すれば返す | |
1290 | + if( humanp4 == p4 ){ | |
1291 | + return &(HumanIndex[i]); | |
1292 | + } | |
1293 | + } | |
1294 | + return NULL; | |
1295 | +} | |
1296 | + | |
1297 | +//! @brief 小物を検索 | |
1298 | +//! @param p4 検索対象の認識番号 | |
1299 | +//! @return 該当したsmallobjectクラスのポインタ (見つからない場合はNULL) | |
1300 | +//! @attention 複数該当する場合、最初に該当したデータを返します。 | |
1301 | +smallobject* ObjectManager::SearchSmallobject(signed char p4) | |
1302 | +{ | |
1303 | + signed char smallobjectp4; | |
1304 | + | |
1305 | + for(int i=0; i<MAX_SMALLOBJECT; i++){ | |
1306 | + //使われていない人ならば処理しない | |
1307 | + // 【破壊積みのオブジェクトも判定するため、無効】 | |
1308 | + //if( SmallObjectIndex[i].GetDrawFlag() == false ){ continue; } | |
1309 | + | |
1310 | + //第4パラメータを取得 | |
1311 | + SmallObjectIndex[i].GetParamData(NULL, &smallobjectp4); | |
1312 | + | |
1313 | + //指定されたp4と一致すれば返す | |
1314 | + if( smallobjectp4 == p4 ){ | |
1315 | + return &(SmallObjectIndex[i]); | |
1316 | + } | |
1317 | + } | |
1318 | + return NULL; | |
1319 | +} | |
1320 | + | |
1321 | +//! @brief 前進(走り)を実行 | |
1322 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1323 | +void ObjectManager::MoveForward(int human_id) | |
1324 | +{ | |
1325 | + //値の範囲をチェック | |
1326 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return; } | |
1327 | + | |
1328 | + //オブジェクトにフラグを設定 | |
1329 | + HumanIndex[human_id].SetMoveForward(); | |
1330 | + | |
1331 | + //走る足音追加 | |
1332 | + float posx, posy, posz; | |
1333 | + int teamid; | |
1334 | + HumanIndex[human_id].GetPosData(&posx, &posy, &posz, NULL); | |
1335 | + HumanIndex[human_id].GetParamData(NULL, NULL, NULL, &teamid); | |
1336 | + GameSound->SetFootsteps(posx, posy, posz, teamid); | |
1337 | +} | |
1338 | + | |
1339 | +//! @brief 後退を実行 | |
1340 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1341 | +void ObjectManager::MoveBack(int human_id) | |
1342 | +{ | |
1343 | + //値の範囲をチェック | |
1344 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return; } | |
1345 | + | |
1346 | + //オブジェクトにフラグを設定 | |
1347 | + HumanIndex[human_id].SetMoveBack(); | |
1348 | + | |
1349 | + //走る足音追加 | |
1350 | + float posx, posy, posz; | |
1351 | + int teamid; | |
1352 | + HumanIndex[human_id].GetPosData(&posx, &posy, &posz, NULL); | |
1353 | + HumanIndex[human_id].GetParamData(NULL, NULL, NULL, &teamid); | |
1354 | + GameSound->SetFootsteps(posx, posy, posz, teamid); | |
1355 | +} | |
1356 | + | |
1357 | +//! @brief 左走りを実行 | |
1358 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1359 | +void ObjectManager::MoveLeft(int human_id) | |
1360 | +{ | |
1361 | + //値の範囲をチェック | |
1362 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return; } | |
1363 | + | |
1364 | + //オブジェクトにフラグを設定 | |
1365 | + HumanIndex[human_id].SetMoveLeft(); | |
1366 | + | |
1367 | + //走る足音追加 | |
1368 | + float posx, posy, posz; | |
1369 | + int teamid; | |
1370 | + HumanIndex[human_id].GetPosData(&posx, &posy, &posz, NULL); | |
1371 | + HumanIndex[human_id].GetParamData(NULL, NULL, NULL, &teamid); | |
1372 | + GameSound->SetFootsteps(posx, posy, posz, teamid); | |
1373 | +} | |
1374 | + | |
1375 | +//! @brief 右走りを実行 | |
1376 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1377 | +void ObjectManager::MoveRight(int human_id) | |
1378 | +{ | |
1379 | + //値の範囲をチェック | |
1380 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return; } | |
1381 | + | |
1382 | + //オブジェクトにフラグを設定 | |
1383 | + HumanIndex[human_id].SetMoveRight(); | |
1384 | + | |
1385 | + //走る足音追加 | |
1386 | + float posx, posy, posz; | |
1387 | + int teamid; | |
1388 | + HumanIndex[human_id].GetPosData(&posx, &posy, &posz, NULL); | |
1389 | + HumanIndex[human_id].GetParamData(NULL, NULL, NULL, &teamid); | |
1390 | + GameSound->SetFootsteps(posx, posy, posz, teamid); | |
1391 | +} | |
1392 | + | |
1393 | +//! @brief 歩きを実行 | |
1394 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1395 | +void ObjectManager::MoveWalk(int human_id) | |
1396 | +{ | |
1397 | + //値の範囲をチェック | |
1398 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return; } | |
1399 | + | |
1400 | + //オブジェクトにフラグを設定 | |
1401 | + HumanIndex[human_id].SetMoveWalk(); | |
1402 | +} | |
1403 | + | |
1404 | +//! @brief ジャンプ | |
1405 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1406 | +void ObjectManager::MoveJump(int human_id) | |
1407 | +{ | |
1408 | + //値の範囲をチェック | |
1409 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return; } | |
1410 | + | |
1411 | + HumanIndex[human_id].Jump(); | |
1412 | +} | |
1413 | + | |
1414 | +//! @brief 発砲 | |
1415 | +//! @param human_id 発砲する人番号 | |
1416 | +//! @return 通常弾発射:1 手榴弾発射:2 失敗:0 | |
1417 | +int ObjectManager::ShotWeapon(int human_id) | |
1418 | +{ | |
1419 | + //値の範囲をチェック | |
1420 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return 0; } | |
1421 | + | |
1422 | + human *MyHuman = &(HumanIndex[human_id]); | |
1423 | + | |
1424 | + float pos_x, pos_y, pos_z; | |
1425 | + int teamid; | |
1426 | + float rotation_x, armrotation_y; | |
1427 | + int weapon_paramid; | |
1428 | + int GunsightErrorRange; | |
1429 | + WeaponParameter ParamData; | |
1430 | + bool playerflag; | |
1431 | + bool grenadeflag; | |
1432 | + | |
1433 | + //人の座標と角度を取得 | |
1434 | + MyHuman->GetPosData(&pos_x, &pos_y, &pos_z, NULL); | |
1435 | + MyHuman->GetParamData(NULL, NULL, NULL, &teamid); | |
1436 | + MyHuman->GetRxRy(&rotation_x, &armrotation_y); | |
1437 | + | |
1438 | + //対象者がプレイヤー自身か判定 | |
1439 | + if( MyHuman == &(HumanIndex[Player_HumanID]) ){ | |
1440 | + playerflag = true; | |
1441 | + } | |
1442 | + else{ | |
1443 | + playerflag = false; | |
1444 | + } | |
1445 | + | |
1446 | + //弾の発射を要求 | |
1447 | + if( MyHuman->ShotWeapon(&weapon_paramid, &GunsightErrorRange) == false ){ return 0; } | |
1448 | + | |
1449 | + //武器の情報を取得 | |
1450 | + if( GameParamInfo->GetWeapon(weapon_paramid, &ParamData) != 0 ){ return 0; } | |
1451 | + | |
1452 | + //誤差の範囲を計算 | |
1453 | + int ErrorRange; | |
1454 | + ErrorRange = GunsightErrorRange; | |
1455 | + if( ErrorRange < ParamData.ErrorRangeMIN ){ ErrorRange = ParamData.ErrorRangeMIN; } | |
1456 | + | |
1457 | + //手榴弾か判定 | |
1458 | + if( weapon_paramid == ID_WEAPON_GRENADE ){ grenadeflag = true; } | |
1459 | + else{ grenadeflag = false; } | |
1460 | + | |
1461 | + class bullet* newbullet; | |
1462 | + class grenade* newgrenade; | |
1463 | + | |
1464 | + //(ショットガンなど)発射する弾の数分繰り返す | |
1465 | + for(int i=0; i<ParamData.burst; i++){ | |
1466 | + //発射角度を決定 | |
1467 | + float rx, ry; | |
1468 | + rx = rotation_x*-1 + (float)M_PI/2; | |
1469 | + ry = armrotation_y; | |
1470 | + | |
1471 | + //誤差分 加算する | |
1472 | + float a; | |
1473 | + a = (float)M_PI/180 * GetRand(360); | |
1474 | + rx += cos(a)*ErrorRange * ((float)M_PI/180*0.15f); | |
1475 | + ry += sin(a)*ErrorRange * ((float)M_PI/180*0.15f); | |
1476 | + | |
1477 | + //手榴弾でなければ | |
1478 | + if( grenadeflag == false ){ | |
1479 | + int attacks; | |
1480 | + | |
1481 | + //(ショットガンなど)発射する弾が複数あれば | |
1482 | + if( ParamData.burst > 1 ){ | |
1483 | + //1個の弾当たりの攻撃力を算出 | |
1484 | + // 全弾合わせて、攻撃力の2倍になるようにする。 | |
1485 | + attacks = (int)( (float)ParamData.attacks / ((float)ParamData.burst/2) ); | |
1486 | + } | |
1487 | + else{ | |
1488 | + //そのまま攻撃力へ反映 | |
1489 | + attacks = ParamData.attacks; | |
1490 | + } | |
1491 | + | |
1492 | + //発射する未使用のオブジェクトを取得 | |
1493 | + newbullet = GetNewBulletObject(); | |
1494 | + if( newbullet == NULL ){ break; } | |
1495 | + | |
1496 | + //銃弾を発射 | |
1497 | + newbullet->SetPosData(pos_x, pos_y + WEAPONSHOT_HEIGHT, pos_z, rx, ry); | |
1498 | + newbullet->SetParamData(attacks, ParamData.penetration, ParamData.speed * BULLET_SPEEDSCALE, teamid, human_id, true); | |
1499 | + newbullet->SetDrawFlag(true); | |
1500 | + } | |
1501 | + else{ | |
1502 | + //発射する未使用のオブジェクトを取得 | |
1503 | + newgrenade = GetNewGrenadeObject(); | |
1504 | + if( newgrenade == NULL ){ break; } | |
1505 | + | |
1506 | + //手榴弾発射 | |
1507 | + newgrenade->SetPosData(pos_x, pos_y + WEAPONSHOT_HEIGHT, pos_z, rx, ry); | |
1508 | + newgrenade->SetParamData(8.0f, human_id, true); | |
1509 | + newgrenade->SetDrawFlag(true); | |
1510 | + } | |
1511 | + | |
1512 | + //誤差を加算(ショットガン用) | |
1513 | + ErrorRange += ParamData.ErrorRangeMIN; | |
1514 | + } | |
1515 | + | |
1516 | + //手榴弾でなければ | |
1517 | + if( grenadeflag == false ){ | |
1518 | + //発砲フラグを設定 | |
1519 | + Human_ShotFlag[human_id] = true; | |
1520 | + } | |
1521 | + | |
1522 | + if( ParamData.soundvolume > 0 ){ | |
1523 | + //銃声を再生 | |
1524 | + GameSound->ShotWeapon(pos_x, pos_y + WEAPONSHOT_HEIGHT, pos_z, weapon_paramid, teamid, playerflag); | |
1525 | + } | |
1526 | + | |
1527 | + if( grenadeflag == true ){ | |
1528 | + return 2; | |
1529 | + } | |
1530 | + return 1; | |
1531 | +} | |
1532 | + | |
1533 | +//! @brief マズルフラッシュを設定 | |
1534 | +//! @param humanid 人の番号 | |
1535 | +//! @attention この関数の呼び出しタイミングを誤ると、銃口に対してマズルフラッシュが合いません。 | |
1536 | +void ObjectManager::ShotWeaponEffect(int humanid) | |
1537 | +{ | |
1538 | + float pos_x, pos_y, pos_z; | |
1539 | + float rotation_x, armrotation_y; | |
1540 | + int weapon_paramid; | |
1541 | + WeaponParameter ParamData; | |
1542 | + float x, y, z; | |
1543 | + float flashsize, smokesize, yakkyousize; | |
1544 | + float rx, mx, my, mz; | |
1545 | + | |
1546 | + //人の座標と角度を取得 | |
1547 | + HumanIndex[humanid].GetPosData(&pos_x, &pos_y, &pos_z, NULL); | |
1548 | + HumanIndex[humanid].GetRxRy(&rotation_x, &armrotation_y); | |
1549 | + | |
1550 | + //武器の情報を取得 | |
1551 | + weapon_paramid = HumanIndex[humanid].GetMainWeaponTypeNO(); | |
1552 | + if( GameParamInfo->GetWeapon(weapon_paramid, &ParamData) != 0 ){ return; } | |
1553 | + | |
1554 | + //マズルフラッシュと煙のサイズを決定 | |
1555 | + flashsize = 0.06f * ParamData.attacks; | |
1556 | + smokesize = flashsize; | |
1557 | + yakkyousize = 0.01f * ParamData.attacks; | |
1558 | + if( ParamData.silencer == true ){ | |
1559 | + flashsize /= 2; | |
1560 | + } | |
1561 | + | |
1562 | + //薬莢の移動量を決定 | |
1563 | + rx = rotation_x*-1 + (float)M_PI/2; | |
1564 | + mx = cos(rx - (float)M_PI/2) * ParamData.yakkyou_sx /10; | |
1565 | + my = (ParamData.yakkyou_sy + (GetRand(3)-1)) /10; | |
1566 | + mz = sin(rx - (float)M_PI/2) * ParamData.yakkyou_sx /10; | |
1567 | + | |
1568 | + //行列でエフェクト座標を計算 | |
1569 | + d3dg->SetWorldTransformHumanWeapon(pos_x, pos_y + 16.0f, pos_z, ParamData.flashx/10, ParamData.flashy/10, ParamData.flashz/10, rotation_x, armrotation_y*-1, 1.0f); | |
1570 | + d3dg->GetWorldTransformPos(&x, &y, &z); | |
1571 | + d3dg->ResetWorldTransform(); | |
1572 | + | |
1573 | + //マズルフラッシュ描画 | |
1574 | + AddEffect(x, y, z, 0.0f, 0.0f, 0.0f, flashsize, (float)M_PI/18*GetRand(18), 1, Resource->GetEffectMflashTexture(), EFFECT_NORMAL); | |
1575 | + | |
1576 | + //行列でエフェクト座標を計算 | |
1577 | + d3dg->SetWorldTransformHumanWeapon(pos_x, pos_y + 16.0f, pos_z, ParamData.flashx/10, ParamData.flashy/10, ParamData.flashz/10 - 0.1f, rotation_x, armrotation_y*-1, 1.0f); | |
1578 | + d3dg->GetWorldTransformPos(&x, &y, &z); | |
1579 | + d3dg->ResetWorldTransform(); | |
1580 | + | |
1581 | + //エフェクト(煙)の表示 | |
1582 | + AddEffect(x, y, z, 0.0f, 0.05f, 0.0f, smokesize, (float)M_PI/18*GetRand(18), (int)(GAMEFPS/3), Resource->GetEffectSmokeTexture(), EFFECT_DISAPPEAR | EFFECT_MAGNIFY | EFFECT_ROTATION); | |
1583 | + | |
1584 | + //行列でエフェクト座標を計算 | |
1585 | + d3dg->SetWorldTransformHumanWeapon(pos_x, pos_y + 16.0f, pos_z, ParamData.yakkyou_px/10, ParamData.yakkyou_py/10, ParamData.yakkyou_pz/10, rotation_x, armrotation_y*-1, 1.0f); | |
1586 | + d3dg->GetWorldTransformPos(&x, &y, &z); | |
1587 | + d3dg->ResetWorldTransform(); | |
1588 | + | |
1589 | + //薬莢描画 | |
1590 | + AddEffect(x, y, z, mx, my, mz, yakkyousize, (float)M_PI/18*GetRand(18), (int)(GAMEFPS/2), Resource->GetEffectYakkyouTexture(), EFFECT_ROTATION | EFFECT_FALL); | |
1591 | +} | |
1592 | + | |
1593 | +//! @brief 武器をリロード | |
1594 | +//! @param human_id 対象の人番号 | |
1595 | +void ObjectManager::ReloadWeapon(int human_id) | |
1596 | +{ | |
1597 | + //値の範囲をチェック | |
1598 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return; } | |
1599 | + | |
1600 | + //無効な人ならば処理しない | |
1601 | + if( HumanIndex[human_id].GetDrawFlag() == false ){ return; } | |
1602 | + if( HumanIndex[human_id].GetHP() <= 0 ){ return; } | |
1603 | + | |
1604 | + //リロードを実行 | |
1605 | + if( HumanIndex[human_id].ReloadWeapon() == true ){ | |
1606 | + float x, y, z; | |
1607 | + int id; | |
1608 | + | |
1609 | + //人の座標とチーム番号を取得 | |
1610 | + HumanIndex[human_id].GetPosData(&x, &y, &z, NULL); | |
1611 | + HumanIndex[human_id].GetParamData(NULL, NULL, NULL, &id); | |
1612 | + y += 16.0f; | |
1613 | + | |
1614 | + //音源を配置 | |
1615 | + GameSound->ReloadWeapon(x, y, z, id); | |
1616 | + } | |
1617 | +} | |
1618 | + | |
1619 | +//! @brief 武器を切り替える(持ち替える) | |
1620 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1621 | +//! @param id 持ち替える武器 (-1 で次の武器) | |
1622 | +void ObjectManager::ChangeWeapon(int human_id, int id) | |
1623 | +{ | |
1624 | + //値の範囲をチェック | |
1625 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return; } | |
1626 | + | |
1627 | + HumanIndex[human_id].ChangeWeapon(id); | |
1628 | +} | |
1629 | + | |
1630 | +//! @brief 武器を捨てる | |
1631 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1632 | +//! @return 成功:true 失敗:false | |
1633 | +bool ObjectManager::DumpWeapon(int human_id) | |
1634 | +{ | |
1635 | + //値の範囲をチェック | |
1636 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return false; } | |
1637 | + | |
1638 | + return HumanIndex[human_id].DumpWeapon(); | |
1639 | +} | |
1640 | + | |
1641 | +//! @brief スコープモードを切り替え | |
1642 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1643 | +void ObjectManager::ChangeScopeMode(int human_id) | |
1644 | +{ | |
1645 | + //値の範囲をチェック | |
1646 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return; } | |
1647 | + | |
1648 | + if( HumanIndex[human_id].GetScopeMode() == 0 ){ //スコープを使用していなければ、スコープを設定 | |
1649 | + HumanIndex[human_id].SetEnableScope(); | |
1650 | + } | |
1651 | + else{ //使用中なら、解除 | |
1652 | + HumanIndex[human_id].SetDisableScope(); | |
1653 | + } | |
1654 | +} | |
1655 | + | |
1656 | +//! @brief 武器のショットモード切り替え | |
1657 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1658 | +//! @return 成功:0 失敗:1 | |
1659 | +int ObjectManager::ChangeShotMode(int human_id) | |
1660 | +{ | |
1661 | + //値の範囲をチェック | |
1662 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return 1; } | |
1663 | + | |
1664 | + return HumanIndex[human_id].ChangeShotMode(); | |
1665 | +} | |
1666 | + | |
1667 | +//! @brief 裏技・所持している武器の弾を追加 | |
1668 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1669 | +//! @return 成功:true 失敗:false | |
1670 | +bool ObjectManager::CheatAddBullet(int human_id) | |
1671 | +{ | |
1672 | + //値の範囲をチェック | |
1673 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return false; } | |
1674 | + | |
1675 | + int selectweapon; | |
1676 | + weapon *weapon[TOTAL_HAVEWEAPON]; | |
1677 | + int id_param, lnbs, nbs; | |
1678 | + WeaponParameter ParamData; | |
1679 | + | |
1680 | + //所持している武器を取得 | |
1681 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
1682 | + weapon[i] = NULL; | |
1683 | + } | |
1684 | + HumanIndex[human_id].GetWeapon(&selectweapon, weapon); | |
1685 | + | |
1686 | + //何かしらの武器を持っていれば | |
1687 | + if( weapon[selectweapon] != NULL ){ | |
1688 | + //武器の種類と弾数、武器の設定値を取得 | |
1689 | + weapon[selectweapon]->GetParamData(&id_param, &lnbs, &nbs); | |
1690 | + if( GameParamInfo->GetWeapon(id_param, &ParamData) == 0 ){ | |
1691 | + //最大弾数分加算し、適用 | |
1692 | + nbs += ParamData.nbsmax; | |
1693 | + weapon[selectweapon]->ResetWeaponParam(Resource, id_param, lnbs, nbs); | |
1694 | + return true; | |
1695 | + } | |
1696 | + } | |
1697 | + | |
1698 | + return false; | |
1699 | +} | |
1700 | + | |
1701 | +//! @brief 裏技・所持している武器を変更 | |
1702 | +//! @param human_id 人の番号(0〜MAX_HUMAN-1) | |
1703 | +//! @param new_weaponID 新たに設定する武器の種類番号 | |
1704 | +//! @return 成功:true 失敗:false | |
1705 | +bool ObjectManager::CheatNewWeapon(int human_id, int new_weaponID) | |
1706 | +{ | |
1707 | + //値の範囲をチェック | |
1708 | + if( (human_id < 0)||(MAX_HUMAN <= human_id) ){ return false; } | |
1709 | + if( (new_weaponID < 0)||(TOTAL_PARAMETERINFO_WEAPON <= new_weaponID) ){ return false; } | |
1710 | + | |
1711 | + human *myHuman = &(HumanIndex[human_id]); | |
1712 | + | |
1713 | + int selectweapon; | |
1714 | + weapon *weapon[TOTAL_HAVEWEAPON]; | |
1715 | + int lnbs, nbs; | |
1716 | + | |
1717 | + //所持している武器を取得 | |
1718 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
1719 | + weapon[i] = NULL; | |
1720 | + } | |
1721 | + myHuman->GetWeapon(&selectweapon, weapon); | |
1722 | + | |
1723 | + //現在武器を所有しておらず、新たに持たせる武器もないなら | |
1724 | + if( (weapon[selectweapon] == NULL)&&(new_weaponID == ID_WEAPON_NONE) ){ | |
1725 | + return false; //処理自体が無意味 | |
1726 | + } | |
1727 | + | |
1728 | + if( weapon[selectweapon] == NULL ){ //武器を所有していなければ | |
1729 | + int dataid = -1; | |
1730 | + | |
1731 | + //新しい武器を配置 | |
1732 | + dataid = AddVisualWeaponIndex(new_weaponID, false); | |
1733 | + | |
1734 | + //武器が配置できれば、武器を持たせる | |
1735 | + if( dataid != -1 ){ | |
1736 | + weapon[selectweapon] = &(WeaponIndex[dataid]); | |
1737 | + myHuman->SetWeapon(weapon); | |
1738 | + return true; | |
1739 | + } | |
1740 | + } | |
1741 | + else{ //武器を所有していれば | |
1742 | + if( new_weaponID == ID_WEAPON_NONE ){ //武器を消すなら | |
1743 | + //一度武器を捨てた上で、その武器を削除 | |
1744 | + if( myHuman->DumpWeapon() == true ){ | |
1745 | + weapon[selectweapon]->SetDrawFlag(false); | |
1746 | + return true; | |
1747 | + } | |
1748 | + } | |
1749 | + else{ //武器を変更するなら | |
1750 | + //武器設定を取得(弾数設定を引き継ぐため) | |
1751 | + weapon[selectweapon]->GetParamData(NULL, &lnbs, &nbs); | |
1752 | + | |
1753 | + //武器設定を適用 | |
1754 | + weapon[selectweapon]->ResetWeaponParam(Resource, new_weaponID, lnbs, nbs); | |
1755 | + | |
1756 | + return true; | |
1757 | + } | |
1758 | + } | |
1759 | + | |
1760 | + return false; | |
1761 | +} | |
1762 | + | |
1763 | +//! @brief ゾンビの攻撃を受けるか判定 | |
1764 | +//! @param MyHuman 攻撃する人オブジェクト(ゾンビ側)のポインタ | |
1765 | +//! @param EnemyHuman 攻撃を受けた人オブジェクトのポインタ | |
1766 | +//! @return 成立:true 不成立:false | |
1767 | +//! @warning MyHuman はゾンビ以外も指定できます。<b>ゾンビかどうかは判定しない</b>ため、ゾンビであるか予め確認しておく必要があります。 | |
1768 | +//! @attention 判定のみを実施します。この判定が成立したら HitZombieAttack()関数 を呼び出してください。 | |
1769 | +bool ObjectManager::CheckZombieAttack(human* MyHuman, human* EnemyHuman) | |
1770 | +{ | |
1771 | + if( MyHuman == NULL ){ return false; } | |
1772 | + if( EnemyHuman == NULL ){ return false; } | |
1773 | + | |
1774 | + //使用されていないか、死亡していれば処理しない。 | |
1775 | + if( MyHuman->GetDrawFlag() == false ){ return false; } | |
1776 | + if( MyHuman->GetHP() <= 0 ){ return false; } | |
1777 | + if( EnemyHuman->GetDrawFlag() == false ){ return false; } | |
1778 | + if( EnemyHuman->GetHP() <= 0 ){ return false; } | |
1779 | + | |
1780 | + float mx, my, mz, mrx, tx, ty, tz; | |
1781 | + int mteam, tteam; | |
1782 | + float AttackPoint_x, AttackPoint_y, AttackPoint_z; | |
1783 | + float ax, az; | |
1784 | + | |
1785 | + MyHuman->GetPosData(&mx, &my, &mz, &mrx); | |
1786 | + MyHuman->GetParamData(NULL, NULL, NULL, &mteam); | |
1787 | + my += VIEW_HEIGHT; | |
1788 | + EnemyHuman->GetPosData(&tx, &ty, &tz, NULL); | |
1789 | + EnemyHuman->GetParamData(NULL, NULL, NULL, &tteam); | |
1790 | + ty += VIEW_HEIGHT; | |
1791 | + | |
1792 | + //味方ならば処理しない | |
1793 | + if( mteam == tteam ){ return false; } | |
1794 | + | |
1795 | + //攻撃ポイント(腕の先端)を求める | |
1796 | + AttackPoint_x = mx + cos(mrx*-1 + (float)M_PI/2) * 2.0f; | |
1797 | + AttackPoint_y = my + VIEW_HEIGHT - 0.5f; | |
1798 | + AttackPoint_z = mz + sin(mrx*-1 + (float)M_PI/2) * 2.0f; | |
1799 | + ax = AttackPoint_x - tx; | |
1800 | + az = AttackPoint_z - tz; | |
1801 | + | |
1802 | + //敵(攻撃対象)が攻撃ポイントに触れていれば、当たっている | |
1803 | + if( (ax*ax + az*az) < 3.3f*3.3f ){ | |
1804 | + if( (AttackPoint_y >= ty)&&(AttackPoint_y <= (ty + HUMAN_HEIGTH)) ){ | |
1805 | + return true; | |
1806 | + } | |
1807 | + } | |
1808 | + | |
1809 | + return false; | |
1810 | +} | |
1811 | + | |
1812 | +//! @brief ゾンビの攻撃を受けた処理 | |
1813 | +//! @param EnemyHuman 攻撃を受けた人オブジェクトのポインタ | |
1814 | +void ObjectManager::HitZombieAttack(human* EnemyHuman) | |
1815 | +{ | |
1816 | + if( EnemyHuman == NULL ){ return; } | |
1817 | + | |
1818 | + //使用されていないか、死亡していれば処理しない。 | |
1819 | + if( EnemyHuman->GetDrawFlag() == false ){ return; } | |
1820 | + if( EnemyHuman->GetHP() <= 0 ){ return; } | |
1821 | + | |
1822 | + float tx, ty, tz; | |
1823 | + | |
1824 | + EnemyHuman->GetPosData(&tx, &ty, &tz, NULL); | |
1825 | + ty += VIEW_HEIGHT; | |
1826 | + | |
1827 | + //ダメージなどを計算 | |
1828 | + EnemyHuman->HitZombieAttack(); | |
1829 | + | |
1830 | + //エフェクト(血)を表示 | |
1831 | + SetHumanBlood(tx, ty, tz); | |
1832 | + | |
1833 | + //効果音を再生 | |
1834 | + GameSound->HitHuman(tx, ty, tz); | |
1835 | +} | |
1836 | + | |
1837 | +//! @brief 死者を蘇生する | |
1838 | +//! @param id 人の番号(0〜MAX_HUMAN-1) | |
1839 | +//! @return true:成功 false:失敗 | |
1840 | +//! @warning 手ぶらのまま蘇生します | |
1841 | +//! @attention 無効な人番号が指定された場合や、指定した人が生存していた場合、あるいは謎人間に対して実行した場合、この関数は失敗します。 | |
1842 | +bool ObjectManager::HumanResuscitation(int id) | |
1843 | +{ | |
1844 | + if( (id < 0)||(MAX_HUMAN-1 < id) ){ return false; } | |
1845 | + | |
1846 | + //使用されていないか、生存していれば処理しない。 | |
1847 | + if( HumanIndex[id].GetDrawFlag() == false ){ return false; } | |
1848 | + if( HumanIndex[id].GetDeadFlag() == false ){ return false; } | |
1849 | + | |
1850 | + int id_param, dataid, team; | |
1851 | + signed char p4; | |
1852 | + HumanIndex[id].GetParamData(&id_param, &dataid, &p4, &team); | |
1853 | + if( (id_param < 0)||( TOTAL_PARAMETERINFO_HUMAN-1 < id_param) ){ return false; } //謎人間なら処理しない | |
1854 | + HumanIndex[id].SetParamData(id_param, dataid, p4, team, true); | |
1855 | + | |
1856 | + return true; | |
1857 | +} | |
1858 | + | |
1859 | +//! @brief ゲームクリアー・ゲームオーバーの判定 | |
1860 | +//! @return ゲームクリアー:1 ゲームオーバー:2 判定なし:0 | |
1861 | +//! @attention ゲームクリア―とゲームオーバーが同時に成立する条件では、本家XOPSと同様に「ゲームクリアー」と判定されます。 | |
1862 | +int ObjectManager::CheckGameOverorComplete() | |
1863 | +{ | |
1864 | + //メモ: | |
1865 | + // | |
1866 | + // 本来は、ゲームオーバー判定を先に行い、次にゲームクリアー判定を実装した方が効率的です。 | |
1867 | + // プレイヤーのHPが 0 ならば即ゲームオーバーとして判定し、敵の中でHPが残っている者を見つけた時点で 判定なし、 | |
1868 | + // 2つの条件に当てはまらなければ、自動的にゲームクリアーとなります。 | |
1869 | + // | |
1870 | + // しかし、本家XOPSはゲームクリアーの判定を優先するため、先にゲームクリアーの判定を行っています。 | |
1871 | + // 生きている敵の数を(総HPとして)数え、敵の数(総HP)が 0 ならば、ゲームクリアーと判定します。 | |
1872 | + // まぁこのように1つの関数で処理しようとせずに、ゲームクリアーとゲームオーバーで関数自体を分けても良いのですがね・・。 | |
1873 | + | |
1874 | + //ゲームクリアー判定 | |
1875 | + int MyTeamid, teamid; | |
1876 | + int TotalEnemyHP = 0; | |
1877 | + HumanIndex[Player_HumanID].GetParamData(NULL, NULL, NULL, &MyTeamid); //プレイヤーのチーム番号を取得 | |
1878 | + for(int i=0; i<MAX_HUMAN; i++){ | |
1879 | + //初期化されていなければ処理しない | |
1880 | + if( HumanIndex[i].GetDrawFlag() == false ){ continue; } | |
1881 | + | |
1882 | + //調べる対象のチーム番号を取得 | |
1883 | + HumanIndex[i].GetParamData(NULL, NULL, NULL, &teamid); | |
1884 | + | |
1885 | + //異なるチーム番号(=敵)ならば | |
1886 | + if( teamid != MyTeamid ){ | |
1887 | + //生きていれば、敵のHPとして加算 | |
1888 | + //if( HumanIndex[i].GetHP() > 0 ){ | |
1889 | + if( HumanIndex[i].GetDeadFlag() == false ){ | |
1890 | + TotalEnemyHP += HumanIndex[i].GetHP(); | |
1891 | + } | |
1892 | + } | |
1893 | + } | |
1894 | + if( TotalEnemyHP == 0 ){ //全敵のHPが 0 ならば | |
1895 | + return 1; | |
1896 | + } | |
1897 | + | |
1898 | + | |
1899 | + //ゲームオーバー判定 | |
1900 | + if( HumanIndex[Player_HumanID].GetDrawFlag() == true ){ //操作対象が有効ならば (注:裏技による変更対策) | |
1901 | + if( HumanIndex[Player_HumanID].GetDeadFlag() == true ){ //プレイヤーが死亡していれば | |
1902 | + return 2; | |
1903 | + } | |
1904 | + } | |
1905 | + | |
1906 | + return 0; | |
1907 | +} | |
1908 | + | |
1909 | +//! @brief オブジェクトの情報を取得 | |
1910 | +//! @param camera_x カメラのX座標 | |
1911 | +//! @param camera_y カメラのY座標 | |
1912 | +//! @param camera_z カメラのZ座標 | |
1913 | +//! @param camera_rx カメラの横軸角度 | |
1914 | +//! @param camera_ry カメラの縦軸角度 | |
1915 | +//! @param color 色を取得するポインタ | |
1916 | +//! @param infostr 文字を取得するポインタ | |
1917 | +//! @return 表示情報あり:true 表示情報なし:false | |
1918 | +bool ObjectManager::GetObjectInfoTag(float camera_x, float camera_y, float camera_z, float camera_rx, float camera_ry, int *color, char *infostr) | |
1919 | +{ | |
1920 | + float dist = 50.0f; | |
1921 | + float px, py, pz; | |
1922 | + float rx, ry; | |
1923 | + float r; | |
1924 | + int Player_teamID; | |
1925 | + | |
1926 | + //文字を初期化 | |
1927 | + infostr[0] = NULL; | |
1928 | + | |
1929 | + //プレイヤーのチーム番号を取得 | |
1930 | + HumanIndex[Player_HumanID].GetParamData(NULL, NULL, NULL, &Player_teamID); | |
1931 | + | |
1932 | + //人 | |
1933 | + for(int i=0; i<MAX_HUMAN; i++){ | |
1934 | + //プレイヤー自身なら処理しない | |
1935 | + if( i == Player_HumanID ){ continue; } | |
1936 | + | |
1937 | + if( HumanIndex[i].GetDrawFlag() == true ){ | |
1938 | + HumanIndex[i].GetPosData(&px, &py, &pz, NULL); | |
1939 | + | |
1940 | + //視点を基準に対象までの角度を算出 | |
1941 | + if( CheckTargetAngle(camera_x, camera_y, camera_z, camera_rx, 0.0f, px, py, pz, dist, &rx, NULL, &r) == true ){ | |
1942 | + int team; | |
1943 | + | |
1944 | + //角度上、視界に入っていれば | |
1945 | + if( abs(rx) < (float)M_PI/18 ){ | |
1946 | + HumanIndex[i].GetParamData(NULL, NULL, NULL, &team); | |
1947 | + if( team == Player_teamID ){ | |
1948 | + *color = d3dg->GetColorCode(0.0f,0.0f,1.0f,1.0f); | |
1949 | + sprintf(infostr, "Human[%d] HP %d : Friend", i, HumanIndex[i].GetHP()); | |
1950 | + } | |
1951 | + else{ | |
1952 | + *color = d3dg->GetColorCode(1.0f,0.0f,0.0f,1.0f); | |
1953 | + sprintf(infostr, "Human[%d] HP %d : Enemy", i, HumanIndex[i].GetHP()); | |
1954 | + } | |
1955 | + dist = sqrt(r); | |
1956 | + } | |
1957 | + } | |
1958 | + } | |
1959 | + } | |
1960 | + | |
1961 | + //武器 | |
1962 | + for(int i=0; i<MAX_WEAPON; i++){ | |
1963 | + if( (WeaponIndex[i].GetDrawFlag() == true)&&(WeaponIndex[i].GetUsingFlag() == false) ){ | |
1964 | + int lnbs, nbs; | |
1965 | + | |
1966 | + WeaponIndex[i].GetPosData(&px, &py, &pz, NULL); | |
1967 | + WeaponIndex[i].GetParamData(NULL, &lnbs, &nbs); | |
1968 | + | |
1969 | + //視点を基準に対象までの角度を算出 | |
1970 | + if( CheckTargetAngle(camera_x, camera_y, camera_z, camera_rx, camera_ry, px, py, pz, dist, &rx, &ry, &r) == true ){ | |
1971 | + //角度上、視界に入っていれば | |
1972 | + if( (abs(rx) < (float)M_PI/18)&&(abs(ry) < (float)M_PI/18) ){ | |
1973 | + *color = d3dg->GetColorCode(0.0f,1.0f,0.0f,1.0f); | |
1974 | + sprintf(infostr, "Weapon[%d] %d:%d", i, lnbs, (nbs - lnbs)); | |
1975 | + dist = sqrt(r); | |
1976 | + } | |
1977 | + } | |
1978 | + } | |
1979 | + } | |
1980 | + | |
1981 | + //小物 | |
1982 | + for(int i=0; i<MAX_SMALLOBJECT; i++){ | |
1983 | + if( SmallObjectIndex[i].GetDrawFlag() == true ){ | |
1984 | + SmallObjectIndex[i].GetPosData(&px, &py, &pz, NULL); | |
1985 | + | |
1986 | + //視点を基準に対象までの角度を算出 | |
1987 | + if( CheckTargetAngle(camera_x, camera_y, camera_z, camera_rx, camera_ry, px, py, pz, dist, &rx, &ry, &r) == true ){ | |
1988 | + //角度上、視界に入っていれば | |
1989 | + if( (abs(rx) < (float)M_PI/18)&&(abs(ry) < (float)M_PI/18) ){ | |
1990 | + *color = d3dg->GetColorCode(1.0f,1.0f,0.0f,1.0f); | |
1991 | + sprintf(infostr, "SmallObject[%d] HP %d", i, SmallObjectIndex[i].GetHP()); | |
1992 | + dist = sqrt(r); | |
1993 | + } | |
1994 | + } | |
1995 | + } | |
1996 | + } | |
1997 | + | |
1998 | + //文字が設定されているかどうかで、有効な処理がされたか判定。 | |
1999 | + if( infostr[0] == NULL ){ | |
2000 | + return false; | |
2001 | + } | |
2002 | + return true; | |
2003 | +} | |
2004 | + | |
2005 | +//! @brief オブジェクトの主計算処理 | |
2006 | +//! @param cmdF5id 上昇機能(F5裏技)させる人データ番号(-1で機能無効) | |
2007 | +//! @param camera_rx カメラの横軸角度 | |
2008 | +//! @param camera_ry カメラの縦軸角度 | |
2009 | +//! @return 常に 0 | |
2010 | +//! @attention 一般的に cmdF5id は、F5裏技使用中はプレイヤー番号(GetPlayerID()関数で取得)、未使用時は -1 を指定します。 | |
2011 | +int ObjectManager::Process(int cmdF5id, float camera_rx, float camera_ry) | |
2012 | +{ | |
2013 | + //このフレームの戦歴を初期化 | |
2014 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2015 | + Human_ontarget[i] = 0; | |
2016 | + Human_kill[i] = 0; | |
2017 | + Human_headshot[i] = 0; | |
2018 | + } | |
2019 | + | |
2020 | + //人オブジェクトの処理 | |
2021 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2022 | + bool cmdF5; | |
2023 | + | |
2024 | + if( i == cmdF5id ){ | |
2025 | + cmdF5 = true; | |
2026 | + } | |
2027 | + else{ | |
2028 | + cmdF5 = false; | |
2029 | + } | |
2030 | + | |
2031 | + if( HumanIndex[i].RunFrame(CollD, BlockData, cmdF5) == 2 ){ | |
2032 | + //死亡時のエフェクト | |
2033 | + DeadEffect(&(HumanIndex[i])); | |
2034 | + } | |
2035 | + } | |
2036 | + | |
2037 | + //武器オブジェクトの処理 | |
2038 | + for(int i=0; i<MAX_WEAPON; i++){ | |
2039 | + WeaponIndex[i].RunFrame(CollD); | |
2040 | + } | |
2041 | + | |
2042 | + //小物オブジェクトの処理 | |
2043 | + for(int i=0; i<MAX_SMALLOBJECT; i++){ | |
2044 | + SmallObjectIndex[i].RunFrame(); | |
2045 | + } | |
2046 | + | |
2047 | + //弾オブジェクトの処理 | |
2048 | + for(int i=0; i<MAX_BULLET; i++){ | |
2049 | + float bx, by, bz, brx, bry; | |
2050 | + int speed; | |
2051 | + float mx, my, mz; | |
2052 | + | |
2053 | + CollideBullet(&BulletIndex[i]); //当たり判定を実行 | |
2054 | + BulletIndex[i].RunFrame(); //主計算 | |
2055 | + | |
2056 | + if( BulletIndex[i].GetDrawFlag() == true ){ | |
2057 | + //弾の座標と角度を取得 | |
2058 | + BulletIndex[i].GetParamData(NULL, NULL, &speed, NULL, NULL); | |
2059 | + BulletIndex[i].GetPosData(&bx, &by, &bz, &brx, &bry); | |
2060 | + mx = cos(brx)*cos(bry)*speed; | |
2061 | + my = sin(bry)*speed; | |
2062 | + mz = sin(brx)*cos(bry)*speed; | |
2063 | + GameSound->PassingBullet(bx, by, bz, mx, my, mz); | |
2064 | + } | |
2065 | + } | |
2066 | + | |
2067 | + //武器を発砲した際のエフェクトを出す | |
2068 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2069 | + if( Human_ShotFlag[i] == true ){ | |
2070 | + ShotWeaponEffect(i); | |
2071 | + Human_ShotFlag[i] = false; | |
2072 | + } | |
2073 | + } | |
2074 | + | |
2075 | + //エフェクトオブジェクトの処理 | |
2076 | + for(int i=0; i<MAX_EFFECT; i++){ | |
2077 | + EffectIndex[i].RunFrame(camera_rx, camera_ry); | |
2078 | + } | |
2079 | + | |
2080 | + //手榴弾の処理 | |
2081 | + for(int i=0; i<MAX_GRENADE; i++){ | |
2082 | + float speed = GrenadeIndex[i].GetSpeed(); | |
2083 | + | |
2084 | + //主計算 | |
2085 | + int rcr = GrenadeIndex[i].RunFrame(CollD, BlockData); | |
2086 | + | |
2087 | + //バウンド・跳ね返ったならば | |
2088 | + if( rcr == 1 ){ | |
2089 | + if( speed > 3.4f ){ | |
2090 | + //座標を取得し、効果音再生 | |
2091 | + float x, y, z; | |
2092 | + GrenadeIndex[i].GetPosData(&x, &y, &z, NULL, NULL); | |
2093 | + GameSound->GrenadeBound(x, y, z); | |
2094 | + } | |
2095 | + } | |
2096 | + | |
2097 | + //爆発したなら | |
2098 | + if( rcr == 2 ){ | |
2099 | + GrenadeExplosion(&(GrenadeIndex[i])); | |
2100 | + } | |
2101 | + } | |
2102 | + | |
2103 | + | |
2104 | + //武器を拾う処理 | |
2105 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2106 | + //武器を拾うだけで毎フレーム総当たりで処理する意味はないので、各武器2フレームに1回処理にケチってます (^^; | |
2107 | + //フレーム数が偶数目の時は、データ番号が偶数の武器。奇数の時は、奇数の武器を処理。 | |
2108 | + for(int j=(framecnt%2); j<MAX_WEAPON; j+=2){ | |
2109 | + PickupWeapon(&HumanIndex[i], &WeaponIndex[j]); | |
2110 | + } | |
2111 | + } | |
2112 | + | |
2113 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2114 | + for(int j=i+1; j<MAX_HUMAN; j++){ | |
2115 | + //人同士の当たり判定(押し合い) | |
2116 | + CollideHuman(&HumanIndex[i], &HumanIndex[j]); | |
2117 | + } | |
2118 | + } | |
2119 | + | |
2120 | + framecnt += 1; | |
2121 | + | |
2122 | + return 0; | |
2123 | +} | |
2124 | + | |
2125 | +//! @brief 現フレームの 命中率・倒した敵の数・ヘットショット数 の取得 | |
2126 | +//! @param id 取得する人のデータ番号 | |
2127 | +//! @param ontarget 命中数を受け取るポインタ | |
2128 | +//! @param kill 倒した敵の数を受け取るポインタ | |
2129 | +//! @param headshot 敵の頭部に命中した数を受け取るポインタ | |
2130 | +//! @return 成功:true 失敗:false | |
2131 | +bool ObjectManager::GetHumanShotInfo(int id, int *ontarget, int *kill, int *headshot) | |
2132 | +{ | |
2133 | + if( (id < 0)||(MAX_HUMAN-1 < id) ){ return false; } | |
2134 | + *ontarget = Human_ontarget[id]; | |
2135 | + *kill = Human_kill[id]; | |
2136 | + *headshot = Human_headshot[id]; | |
2137 | + return true; | |
2138 | +} | |
2139 | + | |
2140 | +//! @brief エフェクトをソートする | |
2141 | +//! @param camera_x カメラのX座標 | |
2142 | +//! @param camera_y カメラのY座標 | |
2143 | +//! @param camera_z カメラのZ座標 | |
2144 | +//! @param data 結果を受け取る effectdata構造体 (要素数:MAX_EFFECT) | |
2145 | +//! @return 有効なエフェクトの数 | |
2146 | +int ObjectManager::SortEffect(float camera_x, float camera_y, float camera_z, effectdata data[]) | |
2147 | +{ | |
2148 | + int cnt = 0; | |
2149 | + | |
2150 | + //カメラからの距離を求めつつ、総数を数える。 | |
2151 | + for(int i=0; i<MAX_EFFECT; i++){ | |
2152 | + if( EffectIndex[i].GetDrawFlag() == true ){ | |
2153 | + float ex, ey, ez; | |
2154 | + float x, y, z; | |
2155 | + | |
2156 | + //座標を取得し、距離を計算、データに登録。 | |
2157 | + EffectIndex[i].GetPosData(&ex, &ey, &ez, NULL); | |
2158 | + x = ex - camera_x; | |
2159 | + y = ey - camera_y; | |
2160 | + z = ez - camera_z; | |
2161 | + data[cnt].id = i; | |
2162 | + data[cnt].dist = x*x + y*y + z*z; | |
2163 | + | |
2164 | + //カウントを加算 | |
2165 | + cnt += 1; | |
2166 | + } | |
2167 | + } | |
2168 | + | |
2169 | + //単純挿入ソート | |
2170 | + effectdata temp; | |
2171 | + for(int i=1; i<cnt; i++) { | |
2172 | + int j; | |
2173 | + temp = data[i]; | |
2174 | + for(j=i; j>0 && data[j-1].dist<temp.dist; j--){ | |
2175 | + data[j] = data[j-1]; | |
2176 | + } | |
2177 | + data[j] = temp; | |
2178 | + } | |
2179 | + | |
2180 | + return cnt; | |
2181 | +} | |
2182 | + | |
2183 | +//! @brief オブジェクトの描画処理 | |
2184 | +//! @param camera_x カメラのX座標 | |
2185 | +//! @param camera_y カメラのY座標 | |
2186 | +//! @param camera_z カメラのZ座標 | |
2187 | +//! @param HidePlayer プレイヤーの非表示設定 (表示:0 非表示:1 腕と武器のみ表示:2) | |
2188 | +void ObjectManager::Render(float camera_x, float camera_y, float camera_z, int HidePlayer) | |
2189 | +{ | |
2190 | + //ワールド座標を原点へ | |
2191 | + d3dg->ResetWorldTransform(); | |
2192 | + | |
2193 | + //人描画 | |
2194 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2195 | + bool DrawArm, player; | |
2196 | + | |
2197 | + //腕の表示 | |
2198 | + if( HidePlayer == 0 ){ | |
2199 | + DrawArm = false; | |
2200 | + } | |
2201 | + else if( Player_HumanID != i ){ // HidePlayer != 0 | |
2202 | + DrawArm = false; | |
2203 | + } | |
2204 | + else if( HidePlayer == 2 ){ // Player_HumanID == i | |
2205 | + DrawArm = true; | |
2206 | + } | |
2207 | + else{ // Player_HumanID == i && HidePlayer == 1 | |
2208 | + continue; //プレイヤー自身を表示しないならスキップ | |
2209 | + } | |
2210 | + | |
2211 | + //プレイヤーかどうか判定 | |
2212 | + if( Player_HumanID == i ){ | |
2213 | + player = true; | |
2214 | + } | |
2215 | + else{ | |
2216 | + player = false; | |
2217 | + } | |
2218 | + | |
2219 | + HumanIndex[i].Render(d3dg, Resource, DrawArm, player); | |
2220 | + } | |
2221 | + | |
2222 | + //武器描画 | |
2223 | + for(int i=0; i<MAX_WEAPON; i++){ | |
2224 | + WeaponIndex[i].Render(d3dg); | |
2225 | + } | |
2226 | + | |
2227 | + //小物描画 | |
2228 | + for(int i=0; i<MAX_SMALLOBJECT; i++){ | |
2229 | + SmallObjectIndex[i].Render(d3dg); | |
2230 | + } | |
2231 | + | |
2232 | + //弾描画 | |
2233 | + for(int i=0; i<MAX_BULLET; i++){ | |
2234 | + BulletIndex[i].Render(d3dg); | |
2235 | + } | |
2236 | + | |
2237 | + //手榴弾描画 | |
2238 | + for(int i=0; i<MAX_GRENADE; i++){ | |
2239 | + GrenadeIndex[i].Render(d3dg); | |
2240 | + } | |
2241 | + | |
2242 | + //エフェクト描画 | |
2243 | + /* | |
2244 | + for(int i=0; i<MAX_EFFECT; i++){ | |
2245 | + EffectIndex[i].Render(d3dg); | |
2246 | + } | |
2247 | + */ | |
2248 | + effectdata data[MAX_EFFECT]; | |
2249 | + int cnt = SortEffect(camera_x, camera_y, camera_z, data); | |
2250 | + for(int i=0; i<cnt; i++) { | |
2251 | + EffectIndex[ data[i].id ].Render(d3dg); | |
2252 | + } | |
2253 | +} | |
2254 | + | |
2255 | +//! @brief データの解放 | |
2256 | +void ObjectManager::Cleanup() | |
2257 | +{ | |
2258 | + //ポイントデータ解放 | |
2259 | + CleanupPointDataToObject(); | |
2260 | +} | |
\ No newline at end of file |
@@ -0,0 +1,1508 @@ | ||
1 | +//! @file d3dgraphics.cpp | |
2 | +//! @brief D3DGraphicsクラスの定義 | |
3 | + | |
4 | +//-------------------------------------------------------------------------------- | |
5 | +// | |
6 | +// OpenXOPS | |
7 | +// Copyright (c) 2014-2015, OpenXOPS Project / [-_-;](mikan) All rights reserved. | |
8 | +// | |
9 | +// Redistribution and use in source and binary forms, with or without | |
10 | +// modification, are permitted provided that the following conditions are met: | |
11 | +// * Redistributions of source code must retain the above copyright notice, | |
12 | +// this list of conditions and the following disclaimer. | |
13 | +// * Redistributions in binary form must reproduce the above copyright notice, | |
14 | +// this list of conditions and the following disclaimer in the documentation | |
15 | +// and/or other materials provided with the distribution. | |
16 | +// * Neither the name of the OpenXOPS Project nor the names of its contributors | |
17 | +// may be used to endorse or promote products derived from this software | |
18 | +// without specific prior written permission. | |
19 | +// | |
20 | +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
21 | +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
22 | +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
23 | +// DISCLAIMED. IN NO EVENT SHALL OpenXOPS Project BE LIABLE FOR ANY | |
24 | +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
25 | +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
26 | +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
27 | +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 | +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
29 | +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | +//-------------------------------------------------------------------------------- | |
31 | + | |
32 | +#include "d3dgraphics.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +D3DGraphics::D3DGraphics() | |
36 | +{ | |
37 | + pD3D = NULL; | |
38 | + pd3dDevice = NULL; | |
39 | + aspect = 1.0f; | |
40 | + fullscreenflag = false; | |
41 | + for(int i=0; i<MAX_MODEL; i++){ | |
42 | + pmesh[i] = NULL; | |
43 | + } | |
44 | + for(int i=0; i<MAX_TEXTURE; i++){ | |
45 | + ptextures[i] = NULL; | |
46 | + } | |
47 | + | |
48 | + blockdata = NULL; | |
49 | + for(int i=0; i<TOTAL_BLOCKTEXTURE; i++){ | |
50 | + mapTextureID[i] = -1; | |
51 | + } | |
52 | + | |
53 | + StartRenderFlag = false; | |
54 | + | |
55 | + //ptextsprite = NULL; | |
56 | + pxmsfont = NULL; | |
57 | + TextureFont = -1; | |
58 | +} | |
59 | + | |
60 | +//! @brief ディストラクタ | |
61 | +D3DGraphics::~D3DGraphics() | |
62 | +{ | |
63 | + //リソース解放 | |
64 | + CleanupD3Dresource(); | |
65 | + | |
66 | + if( pd3dDevice != NULL ) pd3dDevice->Release(); | |
67 | + if( pD3D != NULL ) pD3D->Release(); | |
68 | +} | |
69 | + | |
70 | +//! @brief 初期化@n | |
71 | +//! (DirectX 9) | |
72 | +//! @param hWnd ウィンドウハンドル | |
73 | +//! @param TextureFontFilename 使用するテクスチャフォントのファイル名 | |
74 | +//! @param fullscreen false:ウィンドウ表示 true:フルスクリーン用表示 | |
75 | +//! @return 成功:0 失敗:1 | |
76 | +int D3DGraphics::InitD3D(HWND hWnd, char *TextureFontFilename, bool fullscreen) | |
77 | +{ | |
78 | + D3DPRESENT_PARAMETERS d3dpp; | |
79 | + RECT rec; | |
80 | + | |
81 | + GetClientRect( hWnd, &rec); | |
82 | + | |
83 | + fullscreenflag = fullscreen; | |
84 | + | |
85 | + //D3D9の作成 | |
86 | + pD3D = Direct3DCreate9(D3D_SDK_VERSION); | |
87 | + if( pD3D == NULL ){ | |
88 | + return 1; | |
89 | + } | |
90 | + | |
91 | + //D3Dデバイスの作成 | |
92 | + ZeroMemory(&d3dpp, sizeof(d3dpp)); | |
93 | + if( fullscreenflag == false ){ | |
94 | + d3dpp.Windowed = TRUE; | |
95 | + d3dpp.BackBufferWidth = rec.right; | |
96 | + d3dpp.BackBufferHeight = rec.bottom; | |
97 | + d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; | |
98 | + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; | |
99 | + d3dpp.EnableAutoDepthStencil = TRUE; | |
100 | + d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; | |
101 | + d3dpp.FullScreen_RefreshRateInHz = 0; | |
102 | + } | |
103 | + else{ | |
104 | + D3DDISPLAYMODE dispmode; | |
105 | + pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispmode); | |
106 | + | |
107 | + d3dpp.Windowed = FALSE; | |
108 | + d3dpp.BackBufferWidth = rec.right; | |
109 | + d3dpp.BackBufferHeight = rec.bottom; | |
110 | + d3dpp.BackBufferFormat = dispmode.Format; | |
111 | + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; | |
112 | + d3dpp.EnableAutoDepthStencil = TRUE; | |
113 | + d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; | |
114 | + d3dpp.FullScreen_RefreshRateInHz = dispmode.RefreshRate; | |
115 | + } | |
116 | + | |
117 | + if( FAILED( pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &pd3dDevice) ) ){ | |
118 | + if( FAILED( pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pd3dDevice) ) ){ | |
119 | + return 1; | |
120 | + } | |
121 | + } | |
122 | + | |
123 | + //テクスチャフォント用画像のファイル名を設定 | |
124 | + strcpy(TextureFontFname, TextureFontFilename); | |
125 | + | |
126 | + //描画関係の詳細な設定 | |
127 | + if( InitSubset() != 0){ | |
128 | + return 1; | |
129 | + } | |
130 | + | |
131 | + | |
132 | + //アスペクト比を設定 | |
133 | + aspect = (float)rec.right / (float)rec.bottom; | |
134 | + | |
135 | + //マウスカーソルを消す | |
136 | + //ShowCursor(FALSE); | |
137 | + | |
138 | + | |
139 | + float aspecth, prx, pry, r; | |
140 | + aspecth = (float)SCREEN_WIDTH/SCREEN_HEIGHT; | |
141 | + | |
142 | + //HUD_myweapon [奥行き, 縦, 横] | |
143 | + | |
144 | + //HUD_A 現在持っている武器を表示する座標 | |
145 | + prx = (float)M_PI/180*-39 * aspecth /2; | |
146 | + pry = (float)M_PI/180*-55 /2; | |
147 | + r = 7.5f; | |
148 | + HUD_myweapon_x[0] = cos(pry)*r; | |
149 | + HUD_myweapon_y[0] = sin(pry)*r; | |
150 | + HUD_myweapon_z[0] = sin(prx)*r; | |
151 | + | |
152 | + //HUD_A 予備の武器を表示する座標 | |
153 | + prx = (float)M_PI/180*-52 * aspecth /2; | |
154 | + pry = (float)M_PI/180*-60 /2; | |
155 | + r = 16.0f; | |
156 | + HUD_myweapon_x[1] = cos(pry)*r; | |
157 | + HUD_myweapon_y[1] = sin(pry)*r; | |
158 | + HUD_myweapon_z[1] = sin(prx)*r; | |
159 | + | |
160 | + return 0; | |
161 | +} | |
162 | + | |
163 | +//! @brief リセット@n | |
164 | +//! (ウィンドウ最小化からの復帰 など) | |
165 | +//! @param hWnd ウィンドウハンドル | |
166 | +//! @return 成功:0 待ち:1 失敗:2 | |
167 | +int D3DGraphics::ResetD3D(HWND hWnd) | |
168 | +{ | |
169 | + //フォーカスを失っているなら待たせる | |
170 | + if( pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICELOST ){ | |
171 | + return 1; | |
172 | + } | |
173 | + | |
174 | + //リソース解放 | |
175 | + CleanupD3Dresource(); | |
176 | + | |
177 | + D3DPRESENT_PARAMETERS d3dpp; | |
178 | + RECT rec; | |
179 | + | |
180 | + GetClientRect( hWnd, &rec); | |
181 | + | |
182 | + //D3Dデバイスの作成 | |
183 | + ZeroMemory(&d3dpp, sizeof(d3dpp)); | |
184 | + if( fullscreenflag == false ){ | |
185 | + d3dpp.Windowed = TRUE; | |
186 | + d3dpp.BackBufferWidth = rec.right; | |
187 | + d3dpp.BackBufferHeight = rec.bottom; | |
188 | + d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; | |
189 | + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; | |
190 | + d3dpp.EnableAutoDepthStencil = TRUE; | |
191 | + d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; | |
192 | + d3dpp.FullScreen_RefreshRateInHz = 0; | |
193 | + } | |
194 | + else{ | |
195 | + D3DDISPLAYMODE dispmode; | |
196 | + pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispmode); | |
197 | + | |
198 | + d3dpp.Windowed = FALSE; | |
199 | + d3dpp.BackBufferWidth = rec.right; | |
200 | + d3dpp.BackBufferHeight = rec.bottom; | |
201 | + d3dpp.BackBufferFormat = dispmode.Format; | |
202 | + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; | |
203 | + d3dpp.EnableAutoDepthStencil = TRUE; | |
204 | + d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; | |
205 | + d3dpp.FullScreen_RefreshRateInHz = dispmode.RefreshRate; | |
206 | + } | |
207 | + | |
208 | + if( FAILED( pd3dDevice->Reset(&d3dpp) ) ){ | |
209 | + return 2; | |
210 | + } | |
211 | + | |
212 | + //描画関係の詳細な設定 | |
213 | + if( InitSubset() != 0){ | |
214 | + return 2; | |
215 | + } | |
216 | + | |
217 | + return 0; | |
218 | +} | |
219 | + | |
220 | +//! @brief 描画関係の細部設定 | |
221 | +//! @attention 初期化時に1度だけ実行してください。 | |
222 | +int D3DGraphics::InitSubset() | |
223 | +{ | |
224 | + //ライト | |
225 | + //pd3dDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0,255,255,255) ); | |
226 | + pd3dDevice->LightEnable(0, FALSE); | |
227 | + pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); | |
228 | + | |
229 | + //フォグ | |
230 | + float fog_st = 100; | |
231 | + float fog_end = 800; | |
232 | + pd3dDevice->SetRenderState(D3DRS_FOGENABLE, TRUE); | |
233 | + pd3dDevice->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_RGBA(0, 0, 0, 0)); | |
234 | + pd3dDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR); | |
235 | + pd3dDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE); | |
236 | + pd3dDevice->SetRenderState(D3DRS_FOGSTART,*(DWORD*)(&fog_st)); | |
237 | + pd3dDevice->SetRenderState(D3DRS_FOGEND, *(DWORD*)(&fog_end)); | |
238 | + | |
239 | + // テクスチャフィルタを使う | |
240 | + pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); | |
241 | + pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); | |
242 | + pd3dDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); | |
243 | + | |
244 | + //ミップマップの詳細レベル (LOD) バイアスを指定する。 | |
245 | + float LODBias = -0.2f; | |
246 | + pd3dDevice->SetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, *((LPDWORD)(&LODBias)) ); | |
247 | + | |
248 | + //アルファ・ブレンディングを行う | |
249 | + pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); | |
250 | + | |
251 | + //透過処理を行う | |
252 | + pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); | |
253 | + pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); | |
254 | + | |
255 | + //アルファテストに対応しているかチェック | |
256 | + D3DCAPS9 Caps; | |
257 | + pd3dDevice->GetDeviceCaps(&Caps); | |
258 | + if( Caps.AlphaCmpCaps & D3DPCMPCAPS_GREATEREQUAL ){ | |
259 | + //アルファテスト設定 | |
260 | + // 完全に透明なピクセルは描画しない | |
261 | + pd3dDevice->SetRenderState(D3DRS_ALPHAREF, (DWORD)0x00000001); | |
262 | + pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); | |
263 | + pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); | |
264 | + } | |
265 | + | |
266 | + //深度バッファ比較関数 | |
267 | + pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); | |
268 | + pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS); | |
269 | + | |
270 | + //ポリゴンの裏・表 | |
271 | + pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); | |
272 | + | |
273 | + | |
274 | + //テキストスプライト初期化 | |
275 | + if( FAILED( D3DXCreateSprite( pd3dDevice, &ptextsprite ) ) ){ | |
276 | + return 1; | |
277 | + } | |
278 | + //フォント名:MS ゴシック サイズ:18 | |
279 | + HRESULT hr = D3DXCreateFont( pd3dDevice, -18, 0, FW_NORMAL, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, | |
280 | + DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "MS ゴシック", &pxmsfont); | |
281 | + if( FAILED(hr) ) return 1; | |
282 | + | |
283 | + //テクスチャフォント用画像を取得 | |
284 | + TextureFont = LoadTexture(TextureFontFname, true, false); | |
285 | + return 0; | |
286 | +} | |
287 | + | |
288 | +//! @brief デバイスのリソースを解放 | |
289 | +void D3DGraphics::CleanupD3Dresource() | |
290 | +{ | |
291 | + if( TextureFont != -1 ){ CleanupTexture(TextureFont); } | |
292 | + if( pxmsfont != NULL ){ | |
293 | + pxmsfont->Release(); | |
294 | + pxmsfont = NULL; | |
295 | + } | |
296 | + if( ptextsprite != NULL ){ ptextsprite->Release(); } | |
297 | + | |
298 | + CleanupMapdata(); | |
299 | + | |
300 | + for(int i=0; i<MAX_MODEL; i++){ | |
301 | + CleanupModel(i); | |
302 | + } | |
303 | + for(int i=0; i<MAX_TEXTURE; i++){ | |
304 | + CleanupTexture(i); | |
305 | + } | |
306 | +} | |
307 | + | |
308 | +//! @brief モデルファイルを読み込む(.x) | |
309 | +//! @param filename ファイル名 | |
310 | +//! @return 成功:モデル認識番号(0以上) 失敗:-1 | |
311 | +int D3DGraphics::LoadModel(char* filename) | |
312 | +{ | |
313 | + int id = -1; | |
314 | + | |
315 | + //空いている要素を探す | |
316 | + for(int i=0; i<MAX_MODEL; i++){ | |
317 | + if( pmesh[i] == NULL ){ | |
318 | + id = i; | |
319 | + break; | |
320 | + } | |
321 | + } | |
322 | + if( id == -1 ){ return -1; } | |
323 | + | |
324 | + LPD3DXBUFFER pD3DXMtrlBuffer; | |
325 | + | |
326 | + //.xファイルをバッファーに読み込む | |
327 | + if( FAILED( D3DXLoadMeshFromX( filename, D3DXMESH_SYSTEMMEM, pd3dDevice, NULL, | |
328 | + &pD3DXMtrlBuffer, NULL, &nummaterials[id], &pmesh[id] ) ) ) { | |
329 | + return -1; | |
330 | + } | |
331 | + | |
332 | + //マテリアル情報を取得 | |
333 | + D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer(); | |
334 | + int num = nummaterials[id]; | |
335 | + pmaterials[id] = new D3DMATERIAL9[num]; | |
336 | + if( pmaterials[id] == NULL ) return -3; | |
337 | + | |
338 | + //構造体に代入 | |
339 | + for( int i=0; i<num; i=i+1 ){ | |
340 | + pmaterials[id][i] = d3dxMaterials[i].MatD3D; | |
341 | + pmaterials[id][i].Ambient = pmaterials[id][i].Diffuse; | |
342 | + } | |
343 | + | |
344 | + //バッファを開放 | |
345 | + pD3DXMtrlBuffer->Release(); | |
346 | + | |
347 | + return id; | |
348 | +} | |
349 | + | |
350 | +//! @brief モデルファイルの中間データを作成(モーフィング) | |
351 | +//! @param idA モデルAの認識番号 | |
352 | +//! @param idB モデルBの認識番号 | |
353 | +//! @return 成功:新しいモデル認識番号(0以上) 失敗:-1 | |
354 | +//! @attention モデルAとモデルBは、頂点数・ポリゴン数・インデックスが同じである必要があります。 | |
355 | +//! @attention それぞれのモデルデータが正しくないか 頂点数が異なる場合、実行に失敗します。 | |
356 | +int D3DGraphics::MorphingModel(int idA, int idB) | |
357 | +{ | |
358 | + //データが正しいか調べる | |
359 | + if( (idA < 0)||((MAX_MODEL -1) < idA) ){ return -1; } | |
360 | + if( pmesh[idA] == NULL ){ return -1; } | |
361 | + if( (idB < 0)||((MAX_MODEL -1) < idB) ){ return -1; } | |
362 | + if( pmesh[idB] == NULL ){ return -1; } | |
363 | + | |
364 | + int idN = -1; | |
365 | + int numvA, numvB; | |
366 | + LPDIRECT3DVERTEXBUFFER9 pvbA, pvbB, pvbN; | |
367 | + D3DXVECTOR3 *pVerticesA, *pVerticesB, *pVerticesN; | |
368 | + int FVFsize; | |
369 | + | |
370 | + //空いている要素を探す | |
371 | + for(int i=0; i<MAX_MODEL; i++){ | |
372 | + if( pmesh[i] == NULL ){ | |
373 | + idN = i; | |
374 | + break; | |
375 | + } | |
376 | + } | |
377 | + if( idN == -1 ){ return -1; } | |
378 | + | |
379 | + //頂点数を取得 | |
380 | + numvA = pmesh[idA]->GetNumVertices(); | |
381 | + numvB = pmesh[idB]->GetNumVertices(); | |
382 | + | |
383 | + //頂点数が同じかどうか調べる | |
384 | + if( numvA != numvB ){ return -1; } | |
385 | + | |
386 | + //頂点データをコピー(実質的に領域確保用のダミー) | |
387 | + if( pmesh[idA]->CloneMeshFVF(pmesh[idA]->GetOptions(), pmesh[idA]->GetFVF(), pd3dDevice, &pmesh[idN]) != D3D_OK ){ | |
388 | + return -1; | |
389 | + } | |
390 | + | |
391 | + //マテリアル情報をコピー | |
392 | + int num = nummaterials[idA]; | |
393 | + nummaterials[idN] = nummaterials[idA]; | |
394 | + pmaterials[idN] = new D3DMATERIAL9[num]; | |
395 | + if( pmaterials[idN] == NULL ) return -1; | |
396 | + for( int i=0; i<num; i=i+1 ){ | |
397 | + pmaterials[idN][i] = pmaterials[idA][i]; | |
398 | + } | |
399 | + | |
400 | + //バッファーを取得 | |
401 | + pmesh[idA]->GetVertexBuffer(&pvbA); | |
402 | + pmesh[idB]->GetVertexBuffer(&pvbB); | |
403 | + pmesh[idN]->GetVertexBuffer(&pvbN); | |
404 | + | |
405 | + //1頂点当たりのバイト数取得 | |
406 | + FVFsize = D3DXGetFVFVertexSize(pmesh[idN]->GetFVF()); | |
407 | + | |
408 | + //各頂点を読み出し計算 | |
409 | + for(int i=0; i<numvA; i++){ | |
410 | + pvbA->Lock(i*FVFsize, sizeof(D3DXVECTOR3), (void**)&pVerticesA, D3DLOCK_READONLY); | |
411 | + pvbB->Lock(i*FVFsize, sizeof(D3DXVECTOR3), (void**)&pVerticesB, D3DLOCK_READONLY); | |
412 | + pvbN->Lock(i*FVFsize, sizeof(D3DXVECTOR3), (void**)&pVerticesN, 0); | |
413 | + | |
414 | + //平均化 | |
415 | + pVerticesN->x = (pVerticesA->x + pVerticesB->x)/2; | |
416 | + pVerticesN->y = (pVerticesA->y + pVerticesB->y)/2; | |
417 | + pVerticesN->z = (pVerticesA->z + pVerticesB->z)/2; | |
418 | + | |
419 | + pvbA->Unlock(); | |
420 | + pvbB->Unlock(); | |
421 | + pvbN->Unlock(); | |
422 | + } | |
423 | + | |
424 | + return idN; | |
425 | +} | |
426 | + | |
427 | +//! @brief モデルファイルを解放 | |
428 | +//! @param id モデル認識番号 | |
429 | +void D3DGraphics::CleanupModel(int id) | |
430 | +{ | |
431 | + if( (id < 0)||((MAX_MODEL -1) < id) ){ return; } | |
432 | + if( pmesh[id] != NULL ){ | |
433 | + delete [] pmaterials[id]; | |
434 | + | |
435 | + pmesh[id]->Release(); | |
436 | + pmesh[id] = NULL; | |
437 | + } | |
438 | +} | |
439 | + | |
440 | +//! @brief テクスチャを読み込む | |
441 | +//! @param filename ファイル名 | |
442 | +//! @param texturefont テクスチャフォントフラグ | |
443 | +//! @param BlackTransparent 黒を透過する | |
444 | +//! @return 成功:テクスチャ認識番号(0以上) 失敗:-1 | |
445 | +int D3DGraphics::LoadTexture(char* filename, bool texturefont, bool BlackTransparent) | |
446 | +{ | |
447 | + int id = -1; | |
448 | + int MipLevels; | |
449 | + | |
450 | + //空いている認識番号を探す | |
451 | + for(int i=0; i<MAX_TEXTURE; i++){ | |
452 | + if( ptextures[i] == NULL ){ | |
453 | + id = i; | |
454 | + break; | |
455 | + } | |
456 | + } | |
457 | + if( id == -1 ){ return -1; } | |
458 | + | |
459 | + //ミップマップレベルを設定 | |
460 | + if( texturefont == true ){ | |
461 | + MipLevels = 1; | |
462 | + } | |
463 | + else{ | |
464 | + MipLevels = 4;//D3DX_DEFAULT; | |
465 | + } | |
466 | + | |
467 | + //テクスチャを読み込む | |
468 | + if( BlackTransparent == false ){ | |
469 | + if( FAILED( D3DXCreateTextureFromFileEx(pd3dDevice, filename, D3DX_DEFAULT, D3DX_DEFAULT, MipLevels, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0x00000000, NULL, NULL, &ptextures[id]) ) ) { | |
470 | + return -1; | |
471 | + } | |
472 | + } | |
473 | + else{ | |
474 | + if( FAILED( D3DXCreateTextureFromFileEx(pd3dDevice, filename, D3DX_DEFAULT, D3DX_DEFAULT, MipLevels, 0, D3DFMT_A1R5G5B5, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_ARGB(255, 0, 0, 0), NULL, NULL, &ptextures[id]) ) ) { | |
475 | + return -1; | |
476 | + } | |
477 | + } | |
478 | + return id; | |
479 | +} | |
480 | + | |
481 | +//! @brief テクスチャのサイズを取得 | |
482 | +//! @param id テクスチャ認識番号 | |
483 | +//! @param width 幅を受け取るポインタ | |
484 | +//! @param height 高さを受け取るポインタ | |
485 | +//! @return 成功:0 失敗:1 | |
486 | +//! @attention サーフェイスのサイズを取得します。GPUにロードされたサイズであり、テクスチャ(現物)と異なる場合があります。 | |
487 | +int D3DGraphics::GetTextureSize(int id, int *width, int *height) | |
488 | +{ | |
489 | + //無効な認識番号が指定されていたら、処理せず返す。 | |
490 | + if( id == -1 ){ return 1; } | |
491 | + if( ptextures[id] == NULL ){ return 1; } | |
492 | + | |
493 | + IDirect3DSurface9 *surface; | |
494 | + D3DSURFACE_DESC desc; | |
495 | + | |
496 | + //サーフェイスを取得 | |
497 | + ptextures[id]->GetSurfaceLevel(0, &surface); | |
498 | + | |
499 | + //幅と高さを取得 | |
500 | + surface->GetDesc(&desc); | |
501 | + *width = desc.Width; | |
502 | + *height = desc.Height; | |
503 | + | |
504 | + //サーフェイスを開放 | |
505 | + surface->Release(); | |
506 | + | |
507 | + return 0; | |
508 | +} | |
509 | + | |
510 | +//! @brief テクスチャを解放 | |
511 | +//! @param id テクスチャ認識番号 | |
512 | +void D3DGraphics::CleanupTexture(int id) | |
513 | +{ | |
514 | + if( (id < 0)||((MAX_TEXTURE -1) < id) ){ return; } | |
515 | + if( ptextures[id] != NULL ){ | |
516 | + ptextures[id]->Release(); | |
517 | + ptextures[id] = NULL; | |
518 | + } | |
519 | +} | |
520 | + | |
521 | +//! @brief 全ての描画処理を開始 | |
522 | +//! @return 成功:0 失敗:1 | |
523 | +//! @attention 描画処理の最初に呼び出す必要があります。 | |
524 | +int D3DGraphics::StartRender() | |
525 | +{ | |
526 | + if( StartRenderFlag == true ){ return 1; } | |
527 | + | |
528 | + //領域を初期化 | |
529 | + pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); | |
530 | + | |
531 | + if( SUCCEEDED( pd3dDevice->BeginScene() ) ){ | |
532 | + //Zバッファ初期化 | |
533 | + pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); | |
534 | + | |
535 | + //座標ゼロ地点にワールド変換行列 | |
536 | + ResetWorldTransform(); | |
537 | + | |
538 | + //描画中のフラグを立てる | |
539 | + StartRenderFlag = true; | |
540 | + return 0; | |
541 | + } | |
542 | + | |
543 | + return 1; | |
544 | +} | |
545 | + | |
546 | +//! @brief 全ての描画処理を終了 | |
547 | +//! @return 成功:false 失敗:true | |
548 | +//! @attention 描画処理の最後に呼び出す必要があります。 | |
549 | +bool D3DGraphics::EndRender() | |
550 | +{ | |
551 | + //描画中なら終了 | |
552 | + if( StartRenderFlag == true ){ | |
553 | + pd3dDevice->EndScene(); | |
554 | + } | |
555 | + | |
556 | + HRESULT hr = pd3dDevice->Present(NULL, NULL, NULL, NULL); | |
557 | + | |
558 | + //フラグを false に | |
559 | + StartRenderFlag = false; | |
560 | + | |
561 | + if( hr == D3DERR_DEVICELOST ){ | |
562 | + return true; | |
563 | + } | |
564 | + return false; | |
565 | +} | |
566 | + | |
567 | +//! @brief Zバッファをリセット | |
568 | +void D3DGraphics::ResetZbuffer() | |
569 | +{ | |
570 | + //Zバッファを一度無効にし、初期化後、再度有効に | |
571 | + pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); | |
572 | + pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); | |
573 | + pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); | |
574 | +} | |
575 | + | |
576 | +//! @brief ワールド空間を原点(0,0,0)に戻す など | |
577 | +void D3DGraphics::ResetWorldTransform() | |
578 | +{ | |
579 | + D3DXMATRIX matWorld; | |
580 | + D3DXMatrixIdentity(&matWorld); | |
581 | + pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld); | |
582 | +} | |
583 | + | |
584 | +//! @brief ワールド空間の座標・角度・拡大率を設定 | |
585 | +//! @param x X座標 | |
586 | +//! @param y Y座標 | |
587 | +//! @param z Z座標 | |
588 | +//! @param rx 横軸角度 | |
589 | +//! @param ry 縦軸角度 | |
590 | +//! @param size 拡大率 | |
591 | +void D3DGraphics::SetWorldTransform(float x, float y, float z, float rx, float ry, float size) | |
592 | +{ | |
593 | + SetWorldTransform(x, y, z, rx, ry, 0.0f, size); | |
594 | +} | |
595 | + | |
596 | +//! @brief ワールド空間の座標・角度・拡大率を設定 | |
597 | +//! @param x X座標 | |
598 | +//! @param y Y座標 | |
599 | +//! @param z Z座標 | |
600 | +//! @param rx 横軸角度 | |
601 | +//! @param ry1 縦軸角度 | |
602 | +//! @param ry2 縦軸角度 | |
603 | +//! @param size 拡大率 | |
604 | +void D3DGraphics::SetWorldTransform(float x, float y, float z, float rx, float ry1, float ry2, float size) | |
605 | +{ | |
606 | + D3DXMATRIX matWorld; | |
607 | + D3DXMATRIX matWorld1, matWorld2, matWorld3, matWorld4, matWorld5; | |
608 | + | |
609 | + //行列を作成 | |
610 | + D3DXMatrixTranslation(&matWorld1, x, y, z); | |
611 | + D3DXMatrixRotationY(&matWorld2, rx); | |
612 | + D3DXMatrixRotationX(&matWorld3, ry1); | |
613 | + D3DXMatrixRotationZ(&matWorld4, ry2); | |
614 | + D3DXMatrixScaling(&matWorld5, size, size, size); | |
615 | + | |
616 | + //計算 | |
617 | + matWorld = matWorld5 * matWorld4 * matWorld3 * matWorld2 * matWorld1; | |
618 | + | |
619 | + //適用 | |
620 | + pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); | |
621 | +} | |
622 | + | |
623 | +//! @brief ワールド空間の座標・角度・拡大率を設定(エフェクト用) | |
624 | +//! @param x X座標 | |
625 | +//! @param y Y座標 | |
626 | +//! @param z Z座標 | |
627 | +//! @param rx 横軸角度 | |
628 | +//! @param ry 縦軸角度 | |
629 | +//! @param rt 回転角度 | |
630 | +//! @param size 拡大率 | |
631 | +void D3DGraphics::SetWorldTransformEffect(float x, float y, float z, float rx, float ry, float rt, float size) | |
632 | +{ | |
633 | + D3DXMATRIX matWorld; | |
634 | + D3DXMATRIX matWorld1, matWorld2, matWorld3, matWorld4, matWorld5; | |
635 | + | |
636 | + //行列を作成 | |
637 | + D3DXMatrixTranslation(&matWorld1, x, y, z); | |
638 | + D3DXMatrixRotationY(&matWorld2, rx); | |
639 | + D3DXMatrixRotationZ(&matWorld3, ry); | |
640 | + D3DXMatrixRotationX(&matWorld4, rt); | |
641 | + D3DXMatrixScaling(&matWorld5, size, size, size); | |
642 | + | |
643 | + //計算 | |
644 | + matWorld = matWorld5 * matWorld4 * matWorld3 * matWorld2 * matWorld1; | |
645 | + | |
646 | + //適用 | |
647 | + pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); | |
648 | +} | |
649 | + | |
650 | +//! @brief ワールド空間を人が武器を持つ場所に設定 | |
651 | +//! @param x X座標 | |
652 | +//! @param y Y座標 | |
653 | +//! @param z Z座標 | |
654 | +//! @param mx 手元を原点にした モデルのX座標 | |
655 | +//! @param my 手元を原点にした モデルのY座標 | |
656 | +//! @param mz 手元を原点にした モデルのZ座標 | |
657 | +//! @param rx 横軸角度 | |
658 | +//! @param ry 縦軸角度 | |
659 | +//! @param size 拡大率 | |
660 | +void D3DGraphics::SetWorldTransformHumanWeapon(float x, float y, float z, float mx, float my, float mz, float rx, float ry, float size) | |
661 | +{ | |
662 | + D3DXMATRIX matWorld; | |
663 | + D3DXMATRIX matWorld1, matWorld2, matWorld3, matWorld4, matWorld5; | |
664 | + | |
665 | + //行列を作成 | |
666 | + D3DXMatrixTranslation(&matWorld1, x, y, z); | |
667 | + D3DXMatrixRotationY(&matWorld2, rx); | |
668 | + D3DXMatrixRotationX(&matWorld3, ry); | |
669 | + D3DXMatrixTranslation(&matWorld4, mx, my, mz); | |
670 | + D3DXMatrixScaling(&matWorld5, size, size, size); | |
671 | + | |
672 | + //計算 | |
673 | + matWorld = matWorld5 * matWorld4 * matWorld3 * matWorld2 * matWorld1; | |
674 | + | |
675 | + //適用 | |
676 | + pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); | |
677 | +} | |
678 | + | |
679 | +//! @brief ワールド空間を所持している武器を表示する場所に設定 | |
680 | +//! @param rotation 武器を回転させる | |
681 | +//! @param camera_x カメラのX座標 | |
682 | +//! @param camera_y カメラのY座標 | |
683 | +//! @param camera_z カメラのZ座標 | |
684 | +//! @param camera_rx カメラの横軸角度 | |
685 | +//! @param camera_ry カメラの縦軸角度 | |
686 | +//! @param rx 武器のの縦軸角度 | |
687 | +//! @param size 表示サイズ | |
688 | +//! @note rotation・・ true:現在持っている武器です。 false:予備の武器です。(rx は無視されます) | |
689 | +//! @todo 位置やサイズの微調整 | |
690 | +void D3DGraphics::SetWorldTransformPlayerWeapon(bool rotation, float camera_x, float camera_y, float camera_z, float camera_rx, float camera_ry, float rx, float size) | |
691 | +{ | |
692 | + D3DXMATRIX matWorld; | |
693 | + D3DXMATRIX matWorld1, matWorld2, matWorld3, matWorld4, matWorld5, matWorld6; | |
694 | + | |
695 | + size = size * 0.3f; | |
696 | + | |
697 | + //行列を作成 | |
698 | + D3DXMatrixTranslation(&matWorld1, camera_x, camera_y, camera_z); | |
699 | + D3DXMatrixRotationY(&matWorld2, camera_rx *-1); | |
700 | + D3DXMatrixRotationZ(&matWorld3, camera_ry); | |
701 | + // matWorld4 = [奥行き, 縦, 横] | |
702 | + if( rotation == true ){ | |
703 | + D3DXMatrixTranslation(&matWorld4, HUD_myweapon_x[0], HUD_myweapon_y[0], HUD_myweapon_z[0]); | |
704 | + D3DXMatrixRotationY(&matWorld5, rx); | |
705 | + } | |
706 | + else{ | |
707 | + D3DXMatrixTranslation(&matWorld4, HUD_myweapon_x[1], HUD_myweapon_y[1], HUD_myweapon_z[1]); | |
708 | + D3DXMatrixRotationY(&matWorld5, D3DX_PI); | |
709 | + } | |
710 | + D3DXMatrixScaling(&matWorld6, size, size, size); | |
711 | + | |
712 | + //計算 | |
713 | + matWorld = matWorld6 * matWorld5 * matWorld4 * matWorld3 * matWorld2 * matWorld1; | |
714 | + | |
715 | + //適用 | |
716 | + pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); | |
717 | +} | |
718 | + | |
719 | +//! @brief ワールド空間の座標を取得 | |
720 | +//! @param *x x軸を受け取るポインタ | |
721 | +//! @param *y y軸を受け取るポインタ | |
722 | +//! @param *z z軸を受け取るポインタ | |
723 | +void D3DGraphics::GetWorldTransformPos(float *x, float *y, float *z) | |
724 | +{ | |
725 | + D3DXMATRIX matWorld; | |
726 | + pd3dDevice->GetTransform( D3DTS_WORLD, &matWorld ); | |
727 | + *x = matWorld._41; | |
728 | + *y = matWorld._42; | |
729 | + *z = matWorld._43; | |
730 | +} | |
731 | + | |
732 | +//! @brief フォグを設定 | |
733 | +//! @param skynumber 空の番号 | |
734 | +void D3DGraphics::SetFog(int skynumber) | |
735 | +{ | |
736 | + D3DCOLOR skycolor; | |
737 | + | |
738 | + //空の番号により色を決定 | |
739 | + switch(skynumber){ | |
740 | + case 1: skycolor = D3DCOLOR_RGBA(64, 64+16, 64, 0); break; | |
741 | + case 2: skycolor = D3DCOLOR_RGBA(16, 16, 16, 0); break; | |
742 | + case 3: skycolor = D3DCOLOR_RGBA(0, 16, 32, 0); break; | |
743 | + case 4: skycolor = D3DCOLOR_RGBA(32, 16, 16, 0); break; | |
744 | + case 5: skycolor = D3DCOLOR_RGBA(64, 32, 32, 0); break; | |
745 | + default: skycolor = D3DCOLOR_RGBA(0, 0, 0, 0); break; | |
746 | + } | |
747 | + | |
748 | + //フォグを設定 | |
749 | + pd3dDevice->SetRenderState(D3DRS_FOGCOLOR, skycolor); | |
750 | +} | |
751 | + | |
752 | +//! @brief カメラ(視点)を設定 | |
753 | +//! @param camera_x カメラのX座標 | |
754 | +//! @param camera_y カメラのY座標 | |
755 | +//! @param camera_z カメラのZ座標 | |
756 | +//! @param camera_rx カメラの横軸角度 | |
757 | +//! @param camera_ry カメラの縦軸角度 | |
758 | +//! @param viewangle 視野角 | |
759 | +void D3DGraphics::SetCamera(float camera_x, float camera_y, float camera_z, float camera_rx, float camera_ry, float viewangle) | |
760 | +{ | |
761 | + float vUpVecF; | |
762 | + D3DXMATRIX matWorld; | |
763 | + D3DXMATRIXA16 matView; | |
764 | + | |
765 | + //camera_ryを -PI〜PI の間に正規化 | |
766 | + for(; camera_ry>D3DX_PI; camera_ry -= D3DX_PI*2){} | |
767 | + for(; camera_ry<D3DX_PI*-1; camera_ry += D3DX_PI*2){} | |
768 | + | |
769 | + //カメラの向きを決定 | |
770 | + if( abs(camera_ry) < D3DX_PI/2 ){ | |
771 | + vUpVecF = 1.0f; | |
772 | + } | |
773 | + else{ | |
774 | + vUpVecF = -1.0f; | |
775 | + } | |
776 | + | |
777 | + D3DXMatrixIdentity(&matWorld); | |
778 | + pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld); | |
779 | + | |
780 | + //カメラ座標 | |
781 | + D3DXVECTOR3 vEyePt( camera_x, camera_y, camera_z ); | |
782 | + D3DXVECTOR3 vLookatPt( cos(camera_rx)*cos(camera_ry) + camera_x, sin(camera_ry) + camera_y, sin(camera_rx)*cos(camera_ry) + camera_z ); | |
783 | + D3DXVECTOR3 vUpVec( 0.0f, vUpVecF, 0.0f ); | |
784 | + D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); | |
785 | + pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); | |
786 | + | |
787 | + //カメラ設定(射影変換行列)viewangle | |
788 | + D3DXMATRIXA16 matProj; | |
789 | + D3DXMatrixPerspectiveFovLH( &matProj, viewangle, aspect, CLIPPINGPLANE_NEAR, CLIPPINGPLANE_FAR); | |
790 | + pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj); | |
791 | +} | |
792 | + | |
793 | +//! @brief マップデータを取り込む | |
794 | +//! @param in_blockdata ブロックデータ | |
795 | +//! @param directory ブロックデータが存在するディレクトリ | |
796 | +void D3DGraphics::LoadMapdata(BlockDataInterface* in_blockdata, char *directory) | |
797 | +{ | |
798 | + //ブロックデータが指定されていなければ、処理しない。 | |
799 | + if( in_blockdata == NULL ){ return; } | |
800 | + | |
801 | + char fname[MAX_PATH]; | |
802 | + char fnamefull[MAX_PATH]; | |
803 | + //int bs; | |
804 | + struct blockdata data; | |
805 | + int vID[4]; | |
806 | + int uvID[4]; | |
807 | + | |
808 | + //クラスを設定 | |
809 | + blockdata = in_blockdata; | |
810 | + | |
811 | + //テクスチャ読み込み | |
812 | + for(int i=0; i<TOTAL_BLOCKTEXTURE; i++){ | |
813 | + //テクスチャ名を取得 | |
814 | + blockdata->GetTexture(fname, i); | |
815 | + | |
816 | + if( strcmp(fname, "") == 0 ){ //指定されていなければ、処理しない | |
817 | + mapTextureID[i] = -1; | |
818 | + } | |
819 | + else{ | |
820 | + //「ディレクトリ+ファイル名」を生成し、読み込む | |
821 | + strcpy(fnamefull, directory); | |
822 | + strcat(fnamefull, fname); | |
823 | + mapTextureID[i] = LoadTexture(fnamefull, false, false); | |
824 | + } | |
825 | + } | |
826 | + | |
827 | +#ifdef BLOCKDATA_GPUMEMORY | |
828 | + VERTEXTXTA* pVertices; | |
829 | + | |
830 | + //ブロック数を取得 | |
831 | + bs = blockdata->GetTotaldatas(); | |
832 | + | |
833 | + //ブロック数分のバッファーを作成 | |
834 | + pd3dDevice->CreateVertexBuffer(bs*6*4*sizeof(VERTEXTXTA),0,D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1,D3DPOOL_DEFAULT,&g_pVB,NULL); | |
835 | + | |
836 | + for(int i=0; i<bs; i++){ | |
837 | + //データを取得 | |
838 | + blockdata->Getdata(&data, i); | |
839 | + | |
840 | + for(int j=0; j<6; j++){ | |
841 | + //面の頂点データの関連付けを取得 | |
842 | + blockdataface(j, &vID[0], &uvID[0]); | |
843 | + | |
844 | + //GPUをロック(1面分) | |
845 | + g_pVB->Lock((i*6+j)*4*sizeof(VERTEXTXTA), 4*sizeof(VERTEXTXTA), (void**)&pVertices, 0); | |
846 | + | |
847 | + //頂点座標・UV座標・色を設定 | |
848 | + pVertices[0].position = D3DXVECTOR3( data.x[ vID[1] ], data.y[ vID[1] ], data.z[ vID[1] ] ); | |
849 | + pVertices[0].tu = data.material[j].u[ uvID[1] ]; | |
850 | + pVertices[0].tv = data.material[j].v[ uvID[1] ]; | |
851 | + pVertices[1].position = D3DXVECTOR3( data.x[ vID[2] ], data.y[ vID[2] ], data.z[ vID[2] ] ); | |
852 | + pVertices[1].tu = data.material[j].u[ uvID[2] ]; | |
853 | + pVertices[1].tv = data.material[j].v[ uvID[2] ]; | |
854 | + pVertices[2].position = D3DXVECTOR3( data.x[ vID[0] ], data.y[ vID[0] ], data.z[ vID[0] ] ); | |
855 | + pVertices[2].tu = data.material[j].u[ uvID[0] ]; | |
856 | + pVertices[2].tv = data.material[j].v[ uvID[0] ]; | |
857 | + pVertices[3].position = D3DXVECTOR3( data.x[ vID[3] ], data.y[ vID[3] ], data.z[ vID[3] ] ); | |
858 | + pVertices[3].tu = data.material[j].u[ uvID[3] ]; | |
859 | + pVertices[3].tv = data.material[j].v[ uvID[3] ]; | |
860 | + for(int k=0; k<4; k++){ | |
861 | + pVertices[k].color = D3DCOLOR_COLORVALUE(data.material[j].shadow, data.material[j].shadow, data.material[j].shadow, 1.0f); | |
862 | + } | |
863 | + | |
864 | + //GPUのロックを解除 | |
865 | + g_pVB->Unlock(); | |
866 | + } | |
867 | + } | |
868 | +#else | |
869 | + //ブロック数を取得 | |
870 | + bs = blockdata->GetTotaldatas(); | |
871 | + | |
872 | + for(int i=0; i<bs; i++){ | |
873 | + //データを取得 | |
874 | + blockdata->Getdata(&data, i); | |
875 | + | |
876 | + for(int j=0; j<6; j++){ | |
877 | + //面の頂点データの関連付けを取得 | |
878 | + blockdataface(j, vID, uvID); | |
879 | + | |
880 | + //頂点座標・UV座標・色を設定 | |
881 | + g_pVertices[i][j][0].position = D3DXVECTOR3( data.x[ vID[1] ], data.y[ vID[1] ], data.z[ vID[1] ] ); | |
882 | + g_pVertices[i][j][0].tu = data.material[j].u[ uvID[1] ]; | |
883 | + g_pVertices[i][j][0].tv = data.material[j].v[ uvID[1] ]; | |
884 | + g_pVertices[i][j][1].position = D3DXVECTOR3( data.x[ vID[2] ], data.y[ vID[2] ], data.z[ vID[2] ] ); | |
885 | + g_pVertices[i][j][1].tu = data.material[j].u[ uvID[2] ]; | |
886 | + g_pVertices[i][j][1].tv = data.material[j].v[ uvID[2] ]; | |
887 | + g_pVertices[i][j][2].position = D3DXVECTOR3( data.x[ vID[0] ], data.y[ vID[0] ], data.z[ vID[0] ] ); | |
888 | + g_pVertices[i][j][2].tu = data.material[j].u[ uvID[0] ]; | |
889 | + g_pVertices[i][j][2].tv = data.material[j].v[ uvID[0] ]; | |
890 | + g_pVertices[i][j][3].position = D3DXVECTOR3( data.x[ vID[3] ], data.y[ vID[3] ], data.z[ vID[3] ] ); | |
891 | + g_pVertices[i][j][3].tu = data.material[j].u[ uvID[3] ]; | |
892 | + g_pVertices[i][j][3].tv = data.material[j].v[ uvID[3] ]; | |
893 | + for(int k=0; k<4; k++){ | |
894 | + g_pVertices[i][j][k].color = D3DCOLOR_COLORVALUE(data.material[j].shadow, data.material[j].shadow, data.material[j].shadow, 1.0f); | |
895 | + } | |
896 | + } | |
897 | + } | |
898 | +#endif | |
899 | +} | |
900 | + | |
901 | +//! @brief マップデータを描画 | |
902 | +//! @param wireframe ワイヤーフレーム表示 | |
903 | +void D3DGraphics::DrawMapdata(bool wireframe) | |
904 | +{ | |
905 | + //ブロックデータが読み込まれていなければ、処理しない。 | |
906 | + if( blockdata == NULL ){ return; } | |
907 | + | |
908 | + struct blockdata data; | |
909 | + int textureID; | |
910 | + | |
911 | + if( wireframe == true ){ | |
912 | + //ワイヤーフレーム表示 | |
913 | + for(int i=0; i<bs; i++){ | |
914 | + blockdata->Getdata(&data, i); | |
915 | + Drawline(data.x[0], data.y[0], data.z[0], data.x[1], data.y[1], data.z[1]); | |
916 | + Drawline(data.x[1], data.y[1], data.z[1], data.x[2], data.y[2], data.z[2]); | |
917 | + Drawline(data.x[2], data.y[2], data.z[2], data.x[3], data.y[3], data.z[3]); | |
918 | + Drawline(data.x[3], data.y[3], data.z[3], data.x[0], data.y[0], data.z[0]); | |
919 | + Drawline(data.x[4], data.y[4], data.z[4], data.x[5], data.y[5], data.z[5]); | |
920 | + Drawline(data.x[5], data.y[5], data.z[5], data.x[6], data.y[6], data.z[6]); | |
921 | + Drawline(data.x[6], data.y[6], data.z[6], data.x[7], data.y[7], data.z[7]); | |
922 | + Drawline(data.x[7], data.y[7], data.z[7], data.x[4], data.y[4], data.z[4]); | |
923 | + Drawline(data.x[0], data.y[0], data.z[0], data.x[4], data.y[4], data.z[4]); | |
924 | + Drawline(data.x[1], data.y[1], data.z[1], data.x[5], data.y[5], data.z[5]); | |
925 | + Drawline(data.x[2], data.y[2], data.z[2], data.x[6], data.y[6], data.z[6]); | |
926 | + Drawline(data.x[3], data.y[3], data.z[3], data.x[7], data.y[7], data.z[7]); | |
927 | + } | |
928 | + return; | |
929 | + } | |
930 | + | |
931 | + //深度バッファ比較関数を設定 | |
932 | + //pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS); | |
933 | + | |
934 | + | |
935 | +#ifdef BLOCKDATA_GPUMEMORY | |
936 | + //データ設定 | |
937 | + pd3dDevice->SetStreamSource(0,g_pVB,0,sizeof(VERTEXTXTA)); | |
938 | + | |
939 | + for(textureID=0; textureID<TOTAL_BLOCKTEXTURE; textureID++){ | |
940 | + //テクスチャが正常に読み込めていなければ設定 | |
941 | + if( mapTextureID[textureID] == -1 ){ | |
942 | + pd3dDevice->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE); | |
943 | + pd3dDevice->SetTexture(0, NULL); | |
944 | + } | |
945 | + else{ | |
946 | + pd3dDevice->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); | |
947 | + pd3dDevice->SetTexture(0, ptextures[mapTextureID[textureID]] ); | |
948 | + } | |
949 | + | |
950 | + for(int i=0; i<bs; i++){ | |
951 | + //データ取得 | |
952 | + blockdata->Getdata(&data, i); | |
953 | + | |
954 | + for(int j=0; j<6; j++){ | |
955 | + //テクスチャ認識番号を取得 | |
956 | + int ID = data.material[j].textureID; | |
957 | + | |
958 | + if( textureID == ID ){ | |
959 | + //面を描画 | |
960 | + pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, (i*6+j)*4, 2); | |
961 | + } | |
962 | + } | |
963 | + } | |
964 | + } | |
965 | +#else | |
966 | + //データを設定 | |
967 | + pd3dDevice->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); | |
968 | + | |
969 | + for(textureID=0; textureID<TOTAL_BLOCKTEXTURE; textureID++){ | |
970 | + //テクスチャが正常に読み込めていなければ設定 | |
971 | + if( mapTextureID[textureID] == -1 ){ | |
972 | + pd3dDevice->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE); | |
973 | + pd3dDevice->SetTexture(0, NULL); | |
974 | + } | |
975 | + else{ | |
976 | + pd3dDevice->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); | |
977 | + pd3dDevice->SetTexture(0, ptextures[mapTextureID[textureID]] ); | |
978 | + } | |
979 | + | |
980 | + for(int i=0; i<bs; i++){ | |
981 | + //データ取得 | |
982 | + blockdata->Getdata(&data, i); | |
983 | + | |
984 | + for(int j=0; j<6; j++){ | |
985 | + //テクスチャ認識番号を取得 | |
986 | + int ID = data.material[j].textureID; | |
987 | + | |
988 | + if( textureID == ID ){ | |
989 | + //面を描画 | |
990 | + pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_pVertices[i][j], sizeof(VERTEXTXTA)); | |
991 | + } | |
992 | + } | |
993 | + } | |
994 | + } | |
995 | +#endif | |
996 | + | |
997 | + //深度バッファ比較関数を元に戻す | |
998 | + //pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); | |
999 | +} | |
1000 | + | |
1001 | +//! @brief マップテクスチャを取得 | |
1002 | +//! @param id テクスチャ番号 | |
1003 | +//! @return テクスチャ認識番号(失敗:-1) | |
1004 | +int D3DGraphics::GetMapTextureID(int id) | |
1005 | +{ | |
1006 | + if( (id < 0)||((TOTAL_BLOCKTEXTURE -1) < id ) ){ return -1; } | |
1007 | + return mapTextureID[id]; | |
1008 | +} | |
1009 | + | |
1010 | +//! @brief マップデータを解放 | |
1011 | +void D3DGraphics::CleanupMapdata() | |
1012 | +{ | |
1013 | + //テクスチャを開放 | |
1014 | + for(int i=0; i<TOTAL_BLOCKTEXTURE; i++){ | |
1015 | + CleanupTexture(mapTextureID[i]); | |
1016 | + } | |
1017 | + | |
1018 | +#ifdef BLOCKDATA_GPUMEMORY | |
1019 | + //頂点データ解放 | |
1020 | + if( g_pVB != NULL ){ | |
1021 | + g_pVB->Release(); | |
1022 | + g_pVB = NULL; | |
1023 | + } | |
1024 | +#endif | |
1025 | + bs = 0; | |
1026 | + | |
1027 | + blockdata = NULL; | |
1028 | +} | |
1029 | + | |
1030 | +//! @brief モデルファイルを描画 | |
1031 | +//! @param id_model モデル認識番号 | |
1032 | +//! @param id_texture テクスチャ認識番号 | |
1033 | +void D3DGraphics::RenderModel(int id_model, int id_texture) | |
1034 | +{ | |
1035 | + //無効な引数が設定されていれば失敗 | |
1036 | + if( id_model == -1 ){ return; } | |
1037 | + if( id_texture == -1 ){ return; } | |
1038 | + | |
1039 | + //指定したモデルが初期化されていなければ失敗 | |
1040 | + if( pmesh[id_model] == NULL) return; | |
1041 | + | |
1042 | + //描画 | |
1043 | + for(int i=0; i<(signed)nummaterials[id_model]; i=i+1){ | |
1044 | + pd3dDevice->SetMaterial( &pmaterials[id_model][i] ); | |
1045 | + if( ptextures[id_texture] == NULL ){ | |
1046 | + pd3dDevice->SetTexture(0, NULL); | |
1047 | + } | |
1048 | + else{ | |
1049 | + pd3dDevice->SetTexture( 0, ptextures[id_texture] ); | |
1050 | + } | |
1051 | + pmesh[id_model]->DrawSubset(i); | |
1052 | + } | |
1053 | +} | |
1054 | + | |
1055 | +//! @brief 板を描画 | |
1056 | +//! @param id_texture テクスチャ認識番号 | |
1057 | +//! @param alpha 透明度 (0.0〜1.0 0.0:完全透明) | |
1058 | +void D3DGraphics::RenderBoard(int id_texture, float alpha) | |
1059 | +{ | |
1060 | + //テクスチャが設定されていなければ、処理しない。 | |
1061 | + if( id_texture == -1 ){ return; } | |
1062 | + | |
1063 | + VERTEXTXTA BoardVertices[4]; | |
1064 | + | |
1065 | + //頂点座標・UV座標・色/透明度を設定 | |
1066 | + BoardVertices[0].position = D3DXVECTOR3(0.0f, 0.5f, -0.5f); | |
1067 | + BoardVertices[0].tu = 1.0f; | |
1068 | + BoardVertices[0].tv = 0.0f; | |
1069 | + BoardVertices[1].position = D3DXVECTOR3(0.0f, -0.5f, -0.5f); | |
1070 | + BoardVertices[1].tu = 1.0f; | |
1071 | + BoardVertices[1].tv = 1.0f; | |
1072 | + BoardVertices[2].position = D3DXVECTOR3(0.0f, 0.5f, 0.5f); | |
1073 | + BoardVertices[2].tu = 0.0f; | |
1074 | + BoardVertices[2].tv = 0.0f; | |
1075 | + BoardVertices[3].position = D3DXVECTOR3(0.0f, -0.5f, 0.5f); | |
1076 | + BoardVertices[3].tu = 0.0f; | |
1077 | + BoardVertices[3].tv = 1.0f; | |
1078 | + for(int i=0; i<4; i++){ | |
1079 | + BoardVertices[i].color = D3DCOLOR_COLORVALUE(1.0f, 1.0f, 1.0f, alpha); | |
1080 | + } | |
1081 | + | |
1082 | + //アルファブレンドを設定 | |
1083 | + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); | |
1084 | + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); | |
1085 | + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); | |
1086 | + | |
1087 | + //テクスチャとデータ形式を設定し描画 | |
1088 | + pd3dDevice->SetTexture(0, ptextures[id_texture]); | |
1089 | + pd3dDevice->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); | |
1090 | + pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, BoardVertices, sizeof(VERTEXTXTA)); | |
1091 | + | |
1092 | + //アルファブレンドを元に戻す | |
1093 | + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); | |
1094 | + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); | |
1095 | +} | |
1096 | + | |
1097 | +//! @brief 画面の明るさを設定 | |
1098 | +//! @param Width 幅 | |
1099 | +//! @param Height 高さ | |
1100 | +//! @param Brightness 画面の明るさ (0 で不変、1 以上で明るさの度合い) | |
1101 | +void D3DGraphics::ScreenBrightness(int Width, int Height, int Brightness) | |
1102 | +{ | |
1103 | + //明るさ不変なら処理しない(軽量化) | |
1104 | + if( Brightness == 0 ){ return; } | |
1105 | + | |
1106 | + //透明度を設定し、描画 | |
1107 | + float alpha = 0.02f * Brightness; | |
1108 | + Draw2DBox(0, 0, Width, Height, D3DCOLOR_COLORVALUE(1.0f,1.0f,1.0f,alpha)); | |
1109 | +} | |
1110 | + | |
1111 | +//! @brief 【デバック用】中心線描画 | |
1112 | +void D3DGraphics::Centerline() | |
1113 | +{ | |
1114 | + ResetWorldTransform(); | |
1115 | + Drawline(100.0f, 0.0f, 0.0f, -100.0f, 0.0f, 0.0f); | |
1116 | + Drawline(0.0f, 100.0f, 0.0f, 0.0f, -100.0f, 0.0f); | |
1117 | + Drawline(0.0f, 0.0f, 100.0f, 0.0f, 0.0f, -100.0f); | |
1118 | +} | |
1119 | + | |
1120 | +//! @brief 【デバック用】緑線描画 | |
1121 | +void D3DGraphics::Drawline(float x1, float y1, float z1, float x2, float y2, float z2) | |
1122 | +{ | |
1123 | + VERTEXTXTA mv[2]; | |
1124 | + | |
1125 | + mv[0].position = D3DXVECTOR3(x1, y1, z1); | |
1126 | + mv[1].position = D3DXVECTOR3(x2, y2, z2); | |
1127 | + for(int i=0; i<2; i++){ | |
1128 | + mv[i].color = 0xFF00FF00; | |
1129 | + mv[i].tu = 0.0f; | |
1130 | + mv[i].tv = 0.0f; | |
1131 | + } | |
1132 | + | |
1133 | + pd3dDevice->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); | |
1134 | + pd3dDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, mv, sizeof(VERTEXTXTA)); | |
1135 | +} | |
1136 | + | |
1137 | +//! @brief 2D システムフォントによるテキスト描画を開始 | |
1138 | +//! @attention DirectXの ID3DXSprite を初期化しています。 | |
1139 | +void D3DGraphics::Start2DMSFontTextRender() | |
1140 | +{ | |
1141 | + ptextsprite->Begin(D3DXSPRITE_ALPHABLEND); | |
1142 | +} | |
1143 | + | |
1144 | +//! @brief 文字を描画(システムフォント使用) | |
1145 | +//! @param x x座標 | |
1146 | +//! @param y y座標 | |
1147 | +//! @param str 文字列 (改行コード:可) | |
1148 | +//! @param color 色 | |
1149 | +//! @warning <b>描画は非常に低速です。</b>画面内で何度も呼び出すとパフォーマンスに影響します。 | |
1150 | +//! @warning「改行コードを活用し一度に描画する」「日本語が必要ない文字はテクスチャフォントを活用する」などの対応を講じてください。 | |
1151 | +//! @attention DirectXの ID3DXSprite を使用し、システムフォントで描画ています。 | |
1152 | +//! @attention フォントの種類やサイズは固定です。 文字を二重に重ねて立体感を出さないと見にくくなります。 | |
1153 | +void D3DGraphics::Draw2DMSFontText(int x, int y, char *str, int color) | |
1154 | +{ | |
1155 | + //if( ptextsprite == NULL ){ return; } | |
1156 | + | |
1157 | + //テキストスプライト初期化 | |
1158 | + Start2DMSFontTextRender(); | |
1159 | + | |
1160 | + //基準座標を設定 | |
1161 | + D3DXMATRIX matWorld; | |
1162 | + D3DXMatrixIdentity(&matWorld); | |
1163 | + ptextsprite->SetTransform(&matWorld); | |
1164 | + | |
1165 | + //文字をを描画 | |
1166 | + RECT rc = {x, y, 0, 0}; | |
1167 | + pxmsfont->DrawText(ptextsprite, str, -1, &rc, DT_NOCLIP, color); | |
1168 | + | |
1169 | + //テキストスプライト解放 | |
1170 | + End2DMSFontTextRender(); | |
1171 | +} | |
1172 | + | |
1173 | +//! @brief 文字を中央揃えで描画(システムフォント使用) | |
1174 | +//! @param x x座標 | |
1175 | +//! @param y y座標 | |
1176 | +//! @param w 横の大きさ | |
1177 | +//! @param h 縦の大きさ | |
1178 | +//! @param str 文字列 (改行コード:可) | |
1179 | +//! @param color 色 | |
1180 | +//! @warning <b>描画は非常に低速です。</b>画面内で何度も呼び出すとパフォーマンスに影響します。 | |
1181 | +//! @warning「改行コードを活用し一度に描画する」「日本語が必要ない文字はテクスチャフォントを活用する」などの対応を講じてください。 | |
1182 | +//! @attention DirectXの ID3DXSprite を使用し、システムフォントで描画ています。 | |
1183 | +//! @attention フォントの種類やサイズは固定です。 文字を二重に重ねて立体感を出さないと見にくくなります。 | |
1184 | +void D3DGraphics::Draw2DMSFontTextCenter(int x, int y, int w, int h, char *str, int color) | |
1185 | +{ | |
1186 | + //if( ptextsprite == NULL ){ return; } | |
1187 | + | |
1188 | + //テキストスプライト初期化 | |
1189 | + Start2DMSFontTextRender(); | |
1190 | + | |
1191 | + //基準座標を設定 | |
1192 | + D3DXMATRIX matWorld; | |
1193 | + D3DXMatrixIdentity(&matWorld); | |
1194 | + ptextsprite->SetTransform(&matWorld); | |
1195 | + | |
1196 | + //文字をを描画 | |
1197 | + RECT rc = {x, y, x+w, y+h}; | |
1198 | + pxmsfont->DrawText(ptextsprite, str, -1, &rc, DT_CENTER, color); | |
1199 | + | |
1200 | + //テキストスプライト解放 | |
1201 | + End2DMSFontTextRender(); | |
1202 | +} | |
1203 | + | |
1204 | +//! @brief 2D システムフォントによるテキスト描画を終了 | |
1205 | +//! @attention DirectXの ID3DXSprite を解放しています。 | |
1206 | +void D3DGraphics::End2DMSFontTextRender() | |
1207 | +{ | |
1208 | + ptextsprite->End(); | |
1209 | +} | |
1210 | + | |
1211 | +//! @brief 2D描画用設定 | |
1212 | +void D3DGraphics::Start2DRender() | |
1213 | +{ | |
1214 | + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); | |
1215 | + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); | |
1216 | + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); | |
1217 | + | |
1218 | + //深度バッファ比較関数を設定 | |
1219 | + pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); | |
1220 | +} | |
1221 | + | |
1222 | +//! @brief 文字を描画(テクスチャフォント使用) | |
1223 | +//! @param x x座標 | |
1224 | +//! @param y y座標 | |
1225 | +//! @param str 文字列 (改行コード:<b>不可</b>) | |
1226 | +//! @param color 色 | |
1227 | +//! @param fontwidth 一文字の幅 | |
1228 | +//! @param fontheight 一文字の高さ | |
1229 | +//! @attention 文字を二重に重ねて立体感を出さないと見にくくなります。 | |
1230 | +void D3DGraphics::Draw2DTextureFontText(int x, int y, char *str, int color, int fontwidth, int fontheight) | |
1231 | +{ | |
1232 | + //テクスチャフォントの取得に失敗していれば、処理しない | |
1233 | + if( TextureFont == -1 ){ return; } | |
1234 | + | |
1235 | + //2D描画用設定を適用 | |
1236 | + Start2DRender(); | |
1237 | + | |
1238 | + int w; | |
1239 | + float font_u, font_v; | |
1240 | + float t_u, t_v; | |
1241 | + TLVERTX pBoxVertices[4]; | |
1242 | + | |
1243 | + //1文字のUV座標を計算 | |
1244 | + font_u = 1.0f / 16; | |
1245 | + font_v = 1.0f / 16; | |
1246 | + | |
1247 | + //ワールド座標を原点に戻す | |
1248 | + ResetWorldTransform(); | |
1249 | + | |
1250 | + //テクスチャをフォントテクスチャに設定 | |
1251 | + pd3dDevice->SetTexture( 0, ptextures[TextureFont] ); | |
1252 | + | |
1253 | + //データ形式を設定 | |
1254 | + pd3dDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); | |
1255 | + | |
1256 | + // 与えられた文字数分ループ | |
1257 | + for(int i=0; i<(int)strlen(str); i++){ | |
1258 | + //UV座標を計算 | |
1259 | + w = str[i]; | |
1260 | + if( w < 0 ){ w += 256; } | |
1261 | + t_u = (w % 16) * font_u; | |
1262 | + t_v = (w / 16) * font_v; | |
1263 | + | |
1264 | + //頂点座標・UV座標・色を設定 | |
1265 | + pBoxVertices[0].x = (float)x + i*fontwidth; | |
1266 | + pBoxVertices[0].y = (float)y; | |
1267 | + pBoxVertices[0].tu = t_u; | |
1268 | + pBoxVertices[0].tv = t_v; | |
1269 | + pBoxVertices[1].x = (float)x + fontwidth + i*fontwidth; | |
1270 | + pBoxVertices[1].y = (float)y; | |
1271 | + pBoxVertices[1].tu = t_u + font_u; | |
1272 | + pBoxVertices[1].tv = t_v; | |
1273 | + pBoxVertices[2].x = (float)x + i*fontwidth; | |
1274 | + pBoxVertices[2].y = (float)y + fontheight; | |
1275 | + pBoxVertices[2].tu = t_u; | |
1276 | + pBoxVertices[2].tv = t_v + font_v; | |
1277 | + pBoxVertices[3].x = (float)x + fontwidth + i*fontwidth; | |
1278 | + pBoxVertices[3].y = (float)y + fontheight; | |
1279 | + pBoxVertices[3].tu = t_u + font_u; | |
1280 | + pBoxVertices[3].tv = t_v + font_v; | |
1281 | + for(int j=0; j<4; j++){ | |
1282 | + pBoxVertices[j].z = 0.0f; | |
1283 | + pBoxVertices[j].rhw = 1.0f; | |
1284 | + pBoxVertices[j].color = color; | |
1285 | + } | |
1286 | + | |
1287 | + //描画 | |
1288 | + pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pBoxVertices, sizeof(TLVERTX)); | |
1289 | + } | |
1290 | + | |
1291 | + //2D描画用設定を解除 | |
1292 | + End2DRender(); | |
1293 | +} | |
1294 | + | |
1295 | +//! @brief 線を描画 | |
1296 | +//! @param x1 始点の x座標 | |
1297 | +//! @param y1 始点の y座標 | |
1298 | +//! @param x2 終点の x座標 | |
1299 | +//! @param y2 終点の y座標 | |
1300 | +//! @param color 色 | |
1301 | +void D3DGraphics::Draw2DLine(int x1, int y1, int x2, int y2, int color) | |
1302 | +{ | |
1303 | + TLVERTX pLineVertices[2]; | |
1304 | + | |
1305 | + //2D描画用設定を適用 | |
1306 | + Start2DRender(); | |
1307 | + | |
1308 | + //ワールド座標を原点に戻す | |
1309 | + ResetWorldTransform(); | |
1310 | + | |
1311 | + //頂点座標と色などを設定 | |
1312 | + pLineVertices[0].x = (float)x1; | |
1313 | + pLineVertices[0].y = (float)y1; | |
1314 | + pLineVertices[1].x = (float)x2; | |
1315 | + pLineVertices[1].y = (float)y2; | |
1316 | + for(int i=0; i<2; i++){ | |
1317 | + pLineVertices[i].z = 0.0f; | |
1318 | + pLineVertices[i].rhw = 1.0f; | |
1319 | + pLineVertices[i].color = color; | |
1320 | + pLineVertices[i].tu = 0.0f; | |
1321 | + pLineVertices[i].tv = 0.0f; | |
1322 | + } | |
1323 | + | |
1324 | + pd3dDevice->SetTexture(0, NULL); | |
1325 | + | |
1326 | + //データ形式を設定し、描画。 | |
1327 | + pd3dDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); | |
1328 | + pd3dDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, pLineVertices, sizeof(TLVERTX)); | |
1329 | + | |
1330 | + //2D描画用設定を解除 | |
1331 | + End2DRender(); | |
1332 | +} | |
1333 | + | |
1334 | +//! @brief 円(16角形)を描画 | |
1335 | +//! @param x 中心の x座標 | |
1336 | +//! @param y 中心の y座標 | |
1337 | +//! @param r 半径 | |
1338 | +//! @param color 色 | |
1339 | +void D3DGraphics::Draw2DCycle(int x, int y, int r, int color) | |
1340 | +{ | |
1341 | + TLVERTX pLineVertices[16+1]; | |
1342 | + | |
1343 | + //2D描画用設定を適用 | |
1344 | + Start2DRender(); | |
1345 | + | |
1346 | + //ワールド座標を原点に戻す | |
1347 | + ResetWorldTransform(); | |
1348 | + | |
1349 | + //頂点座標と色などを設定 | |
1350 | + for(int i=0; i<16+1; i++){ | |
1351 | + pLineVertices[i].x = (float)x + cos((float)M_PI*2/16 * i) * r; | |
1352 | + pLineVertices[i].y = (float)y + sin((float)M_PI*2/16 * i) * r; | |
1353 | + | |
1354 | + pLineVertices[i].z = 0.0f; | |
1355 | + pLineVertices[i].rhw = 1.0f; | |
1356 | + pLineVertices[i].color = color; | |
1357 | + pLineVertices[i].tu = 0.0f; | |
1358 | + pLineVertices[i].tv = 0.0f; | |
1359 | + } | |
1360 | + | |
1361 | + pd3dDevice->SetTexture(0, NULL); | |
1362 | + | |
1363 | + //データ形式を設定し、描画。 | |
1364 | + pd3dDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); | |
1365 | + pd3dDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, 16, pLineVertices, sizeof(TLVERTX)); | |
1366 | + | |
1367 | + //2D描画用設定を解除 | |
1368 | + End2DRender(); | |
1369 | +} | |
1370 | + | |
1371 | +//! @brief 四角形を描画 | |
1372 | +//! @param x1 左上の x座標 | |
1373 | +//! @param y1 左上の y座標 | |
1374 | +//! @param x2 右下の x座標 | |
1375 | +//! @param y2 右下の y座標 | |
1376 | +//! @param color 色 | |
1377 | +void D3DGraphics::Draw2DBox(int x1, int y1, int x2, int y2, int color) | |
1378 | +{ | |
1379 | + TLVERTX pBoxVertices[4]; | |
1380 | + | |
1381 | + //2D描画用設定を適用 | |
1382 | + Start2DRender(); | |
1383 | + | |
1384 | + //ワールド座標を原点に戻す | |
1385 | + ResetWorldTransform(); | |
1386 | + | |
1387 | + //頂点座標と色などを設定 | |
1388 | + pBoxVertices[0].x = (float)x1; | |
1389 | + pBoxVertices[0].y = (float)y1; | |
1390 | + pBoxVertices[1].x = (float)x2; | |
1391 | + pBoxVertices[1].y = (float)y1; | |
1392 | + pBoxVertices[2].x = (float)x1; | |
1393 | + pBoxVertices[2].y = (float)y2; | |
1394 | + pBoxVertices[3].x = (float)x2; | |
1395 | + pBoxVertices[3].y = (float)y2; | |
1396 | + for(int i=0; i<4; i++){ | |
1397 | + pBoxVertices[i].z = 0.0f; | |
1398 | + pBoxVertices[i].rhw = 1.0f; | |
1399 | + pBoxVertices[i].color = color; | |
1400 | + pBoxVertices[i].tu = 0.0f; | |
1401 | + pBoxVertices[i].tv = 0.0f; | |
1402 | + } | |
1403 | + | |
1404 | + pd3dDevice->SetTexture(0, NULL); | |
1405 | + | |
1406 | + //データ形式を設定し、描画。 | |
1407 | + pd3dDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); | |
1408 | + pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pBoxVertices, sizeof(TLVERTX)); | |
1409 | + | |
1410 | + //2D描画用設定を解除 | |
1411 | + End2DRender(); | |
1412 | +} | |
1413 | + | |
1414 | +//! @brief 画像を描画 | |
1415 | +//! @param x x座標 | |
1416 | +//! @param y y座標 | |
1417 | +//! @param id テクスチャ認識番号 | |
1418 | +//! @param width 幅 | |
1419 | +//! @param height 高さ | |
1420 | +//! @param alpha 透明度(0.0〜1.0) | |
1421 | +void D3DGraphics::Draw2DTexture(int x, int y, int id, int width, int height, float alpha) | |
1422 | +{ | |
1423 | + //無効なテクスチャ番号を指定されていれば処理しない | |
1424 | + if( id == -1 ){ return; } | |
1425 | + | |
1426 | + TLVERTX pBoxVertices[4]; | |
1427 | + | |
1428 | + //2D描画用設定を適用 | |
1429 | + Start2DRender(); | |
1430 | + | |
1431 | + //ワールド座標を原点に戻す | |
1432 | + ResetWorldTransform(); | |
1433 | + | |
1434 | + //頂点座標・UV座標・色を設定 | |
1435 | + pBoxVertices[0].x = (float)x; | |
1436 | + pBoxVertices[0].y = (float)y; | |
1437 | + pBoxVertices[0].tu = 0.0f; | |
1438 | + pBoxVertices[0].tv = 0.0f; | |
1439 | + pBoxVertices[1].x = (float)x + width; | |
1440 | + pBoxVertices[1].y = (float)y; | |
1441 | + pBoxVertices[1].tu = 1.0f; | |
1442 | + pBoxVertices[1].tv = 0.0f; | |
1443 | + pBoxVertices[2].x = (float)x; | |
1444 | + pBoxVertices[2].y = (float)y + height; | |
1445 | + pBoxVertices[2].tu = 0.0f; | |
1446 | + pBoxVertices[2].tv = 1.0f; | |
1447 | + pBoxVertices[3].x = (float)x + width; | |
1448 | + pBoxVertices[3].y = (float)y + height; | |
1449 | + pBoxVertices[3].tu = 1.0f; | |
1450 | + pBoxVertices[3].tv = 1.0f; | |
1451 | + for(int i=0; i<4; i++){ | |
1452 | + pBoxVertices[i].z = 0.0f; | |
1453 | + pBoxVertices[i].rhw = 1.0f; | |
1454 | + pBoxVertices[i].color = D3DCOLOR_COLORVALUE(1.0f,1.0f,1.0f,alpha); | |
1455 | + } | |
1456 | + | |
1457 | + //テクスチャとデータ形式を設定し、描画 | |
1458 | + pd3dDevice->SetTexture( 0, ptextures[id] ); | |
1459 | + pd3dDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); | |
1460 | + pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pBoxVertices, sizeof(TLVERTX)); | |
1461 | + | |
1462 | + //2D描画用設定を解除 | |
1463 | + End2DRender(); | |
1464 | +} | |
1465 | + | |
1466 | +//! @brief 2D描画用設定を解除 | |
1467 | +void D3DGraphics::End2DRender() | |
1468 | +{ | |
1469 | + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); | |
1470 | + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); | |
1471 | + | |
1472 | + //深度バッファ比較関数を元に戻す | |
1473 | + pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); | |
1474 | +} | |
1475 | + | |
1476 | +//! @brief 画面のスクリーンショットを保存 | |
1477 | +//! @param filename ファイル名 | |
1478 | +//! @return 成功:true 失敗:false | |
1479 | +bool D3DGraphics::SaveScreenShot(char* filename) | |
1480 | +{ | |
1481 | + LPDIRECT3DSURFACE9 pSurface = NULL; | |
1482 | + HRESULT hr; | |
1483 | + | |
1484 | + //サーフェースを作成し、画面を取得 | |
1485 | + pd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface); | |
1486 | + | |
1487 | + //サーフェイスを画像に出力 | |
1488 | + hr = D3DXSaveSurfaceToFile(filename, D3DXIFF_BMP, pSurface, NULL, NULL); | |
1489 | + | |
1490 | + //解放 | |
1491 | + pSurface->Release(); | |
1492 | + | |
1493 | + if( hr == D3D_OK ){ | |
1494 | + return true; | |
1495 | + } | |
1496 | + return false; | |
1497 | +} | |
1498 | + | |
1499 | +//! @brief カラーコードを取得 | |
1500 | +//! @param red 赤(0.0f〜1.0f) | |
1501 | +//! @param green 緑(0.0f〜1.0f) | |
1502 | +//! @param blue 青(0.0f〜1.0f) | |
1503 | +//! @param alpha 透明度(0.0f〜1.0f) | |
1504 | +//! @return カラーコード | |
1505 | +int D3DGraphics::GetColorCode(float red, float green, float blue, float alpha) | |
1506 | +{ | |
1507 | + return D3DCOLOR_COLORVALUE(red, green, blue, alpha); | |
1508 | +} | |
\ No newline at end of file |
@@ -0,0 +1,160 @@ | ||
1 | +//! @file d3dgraphics.h | |
2 | +//! @brief D3DGraphicsクラスの宣言 | |
3 | + | |
4 | +//-------------------------------------------------------------------------------- | |
5 | +// | |
6 | +// OpenXOPS | |
7 | +// Copyright (c) 2014-2015, OpenXOPS Project / [-_-;](mikan) All rights reserved. | |
8 | +// | |
9 | +// Redistribution and use in source and binary forms, with or without | |
10 | +// modification, are permitted provided that the following conditions are met: | |
11 | +// * Redistributions of source code must retain the above copyright notice, | |
12 | +// this list of conditions and the following disclaimer. | |
13 | +// * Redistributions in binary form must reproduce the above copyright notice, | |
14 | +// this list of conditions and the following disclaimer in the documentation | |
15 | +// and/or other materials provided with the distribution. | |
16 | +// * Neither the name of the OpenXOPS Project nor the names of its contributors | |
17 | +// may be used to endorse or promote products derived from this software | |
18 | +// without specific prior written permission. | |
19 | +// | |
20 | +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
21 | +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
22 | +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
23 | +// DISCLAIMED. IN NO EVENT SHALL OpenXOPS Project BE LIABLE FOR ANY | |
24 | +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
25 | +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
26 | +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
27 | +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 | +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
29 | +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | +//-------------------------------------------------------------------------------- | |
31 | + | |
32 | +#ifndef DIRECTX_H | |
33 | +#define DIRECTX_H | |
34 | + | |
35 | +#define MAX_MODEL 96 //!< 最大モデル数 | |
36 | +#define MAX_TEXTURE 64 //!< 最大テクスチャ数 | |
37 | + | |
38 | +#define CLIPPINGPLANE_NEAR 1.0f //!< 近クリップ面(≒描画する最小距離) | |
39 | +#define CLIPPINGPLANE_FAR 800.0f //!< 遠クリップ面(≒描画する最大距離) | |
40 | + | |
41 | +#ifndef H_LAYERLEVEL | |
42 | + #define H_LAYERLEVEL 1 //!< Select include file. | |
43 | +#endif | |
44 | +#include "main.h" | |
45 | + | |
46 | +#define BLOCKDATA_GPUMEMORY //!< @brief ブロックデータを格納するメモリーを選択 @details 定数宣言有効:GPUメモリー 定数宣言無効(コメント化):メインメモリー | |
47 | + | |
48 | +#pragma warning(disable:4819) //VC++警告防止 | |
49 | +#include <d3dx9.h> | |
50 | +#pragma warning(default:4819) | |
51 | + | |
52 | +#pragma comment(lib, "d3d9.lib") | |
53 | +#pragma comment(lib, "d3dx9.lib") | |
54 | + | |
55 | +//! 3Dポリゴン描画用構造体 | |
56 | +struct VERTEXTXTA | |
57 | +{ | |
58 | + D3DXVECTOR3 position; //!< The position | |
59 | + DWORD color; //!< The color | |
60 | + FLOAT tu; //!< The texture coordinates | |
61 | + FLOAT tv; //!< The texture coordinates | |
62 | +}; | |
63 | + | |
64 | +//! 2Dポリゴン描画用構造体 | |
65 | +struct TLVERTX { | |
66 | + FLOAT x; //!< position | |
67 | + FLOAT y; //!< position | |
68 | + FLOAT z; //!< position | |
69 | + FLOAT rhw; //!< vector | |
70 | + D3DCOLOR color; //!< color | |
71 | + FLOAT tu; //!< texture coordinates | |
72 | + FLOAT tv; //!< texture coordinates | |
73 | +}; | |
74 | + | |
75 | +//! @brief 画面描画を行うクラス | |
76 | +//! @details 画面の描画機能やそれに直接関連する処理を行います。 | |
77 | +//! @details 具体的に、3D描画・2D描画・モデルファイルやテクスチャ管理 を行う機能があります。 | |
78 | +//! @details 内部ではDirectX 9を使用しています。 | |
79 | +class D3DGraphics | |
80 | +{ | |
81 | + LPDIRECT3D9 pD3D; //!< DIRECT3D9のポインタ | |
82 | + LPDIRECT3DDEVICE9 pd3dDevice; //!< DIRECT3DDEVICE9のポインタ | |
83 | + float aspect; //!< 画面のアスペクト比 | |
84 | + bool fullscreenflag; //!< フルスクリーン表示 | |
85 | + LPD3DXMESH pmesh[MAX_MODEL]; //!< (Xファイル用)D3DXMESHのポインタ | |
86 | + D3DMATERIAL9* pmaterials[MAX_MODEL]; //!< (Xファイル用)D3DMATERIAL9のポインタ | |
87 | + DWORD nummaterials[MAX_MODEL]; //!< (Xファイル用)マテリアル数 | |
88 | + LPDIRECT3DTEXTURE9 ptextures[MAX_TEXTURE]; //!< テクスチャを格納 | |
89 | + | |
90 | + class BlockDataInterface* blockdata; //!< 読み込んだブロックデータを格納するクラスへのポインタ | |
91 | + int bs; //!< ブロック数 | |
92 | + int mapTextureID[TOTAL_BLOCKTEXTURE]; //!< テクスチャ番号 | |
93 | +#ifdef BLOCKDATA_GPUMEMORY | |
94 | + LPDIRECT3DVERTEXBUFFER9 g_pVB; //!< 頂点情報(GPU管理) | |
95 | +#else | |
96 | + VERTEXTXTA g_pVertices[MAX_BLOCKS][6][4]; //!< 頂点情報(CPU管理) | |
97 | +#endif | |
98 | + | |
99 | + float HUD_myweapon_x[TOTAL_HAVEWEAPON]; //!< HUD_Aの武器表示 X座標 | |
100 | + float HUD_myweapon_y[TOTAL_HAVEWEAPON]; //!< HUD_Aの武器表示 Y座標 | |
101 | + float HUD_myweapon_z[TOTAL_HAVEWEAPON]; //!< HUD_Aの武器表示 Z座標 | |
102 | + | |
103 | + bool StartRenderFlag; //!< StartRender()関数 実行中を表すフラグ | |
104 | + | |
105 | + LPD3DXSPRITE ptextsprite; //!< 2Dテクスチャスプライト | |
106 | + LPD3DXFONT pxmsfont; //!< システムフォント | |
107 | + char TextureFontFname[_MAX_PATH]; //!< テクスチャフォントのファイル名 | |
108 | + int TextureFont; //!< テクスチャフォントのテクスチャID | |
109 | + | |
110 | + int InitSubset(); | |
111 | + void CleanupD3Dresource(); | |
112 | + void Start2DMSFontTextRender(); | |
113 | + void End2DMSFontTextRender(); | |
114 | + void Start2DRender(); | |
115 | + void End2DRender(); | |
116 | + | |
117 | +public: | |
118 | + D3DGraphics(); | |
119 | + ~D3DGraphics(); | |
120 | + int InitD3D(HWND hWnd, char *TextureFontFilename, bool fullscreen); | |
121 | + int ResetD3D(HWND hWnd); | |
122 | + int LoadModel(char* filename); | |
123 | + int MorphingModel(int idA, int idB); | |
124 | + void CleanupModel(int id); | |
125 | + int LoadTexture(char* filename, bool texturefont, bool BlackTransparent); | |
126 | + int GetTextureSize(int id, int *width, int *height); | |
127 | + void CleanupTexture(int id); | |
128 | + int StartRender(); | |
129 | + bool EndRender(); | |
130 | + void ResetZbuffer(); | |
131 | + void ResetWorldTransform(); | |
132 | + void SetWorldTransform(float x, float y, float z, float rx, float ry, float size); | |
133 | + void SetWorldTransform(float x, float y, float z, float rx, float ry1, float ry2, float size); | |
134 | + void SetWorldTransformEffect(float x, float y, float z, float rx, float ry, float rt, float size); | |
135 | + void SetWorldTransformHumanWeapon(float x, float y, float z, float mx, float my, float mz, float rx, float ry, float size); | |
136 | + void SetWorldTransformPlayerWeapon(bool rotation, float camera_x, float camera_y, float camera_z, float camera_rx, float camera_ry, float rx, float size); | |
137 | + void GetWorldTransformPos(float *x, float *y, float *z); | |
138 | + void SetFog(int skynumber); | |
139 | + void SetCamera(float camera_x, float camera_y, float camera_z, float camera_rx, float camera_ry, float viewangle); | |
140 | + void LoadMapdata(class BlockDataInterface* in_blockdata, char *directory); | |
141 | + void DrawMapdata(bool wireframe); | |
142 | + int GetMapTextureID(int id); | |
143 | + void CleanupMapdata(); | |
144 | + void RenderModel(int id_model, int id_texture); | |
145 | + void RenderBoard(int id_texture, float alpha); | |
146 | + void ScreenBrightness(int Width, int Height, int Brightness); | |
147 | + void Centerline(); | |
148 | + void Drawline(float x1, float y1, float z1, float x2, float y2, float z2); | |
149 | + void Draw2DMSFontText(int x, int y, char *str, int color); | |
150 | + void Draw2DMSFontTextCenter(int x, int y, int w, int h, char *str, int color); | |
151 | + void Draw2DTextureFontText(int x, int y, char *str, int color, int fontwidth, int fontheight); | |
152 | + void Draw2DLine(int x1, int y1, int x2, int y2, int color); | |
153 | + void Draw2DCycle(int x, int y, int r, int color); | |
154 | + void Draw2DBox(int x1, int y1, int x2, int y2, int color); | |
155 | + void Draw2DTexture(int x, int y, int id, int width, int height, float alpha); | |
156 | + bool SaveScreenShot(char *fname); | |
157 | + int GetColorCode(float red, float green, float blue, float alpha); | |
158 | +}; | |
159 | + | |
160 | +#endif | |
\ No newline at end of file |
@@ -0,0 +1,250 @@ | ||
1 | +//! @file scene.cpp | |
2 | +//! @brief 各画面を管理するクラスの定義 | |
3 | + | |
4 | +//-------------------------------------------------------------------------------- | |
5 | +// | |
6 | +// OpenXOPS | |
7 | +// Copyright (c) 2014-2015, OpenXOPS Project / [-_-;](mikan) All rights reserved. | |
8 | +// | |
9 | +// Redistribution and use in source and binary forms, with or without | |
10 | +// modification, are permitted provided that the following conditions are met: | |
11 | +// * Redistributions of source code must retain the above copyright notice, | |
12 | +// this list of conditions and the following disclaimer. | |
13 | +// * Redistributions in binary form must reproduce the above copyright notice, | |
14 | +// this list of conditions and the following disclaimer in the documentation | |
15 | +// and/or other materials provided with the distribution. | |
16 | +// * Neither the name of the OpenXOPS Project nor the names of its contributors | |
17 | +// may be used to endorse or promote products derived from this software | |
18 | +// without specific prior written permission. | |
19 | +// | |
20 | +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
21 | +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
22 | +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
23 | +// DISCLAIMED. IN NO EVENT SHALL OpenXOPS Project BE LIABLE FOR ANY | |
24 | +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
25 | +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
26 | +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
27 | +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 | +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
29 | +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | +//-------------------------------------------------------------------------------- | |
31 | + | |
32 | +#include "scene.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +scene::scene() | |
36 | +{ | |
37 | + d3dg = NULL; | |
38 | + inputCtrl = NULL; | |
39 | + framecnt = 0; | |
40 | +} | |
41 | + | |
42 | +//! @brief ディストラクタ | |
43 | +scene::~scene() | |
44 | +{} | |
45 | + | |
46 | +//! @brief クラスを設定 | |
47 | +void scene::SetClass(StateMachine *in_GameState, D3DGraphics *in_d3dg, InputControl *in_inputCtrl) | |
48 | +{ | |
49 | + GameState = in_GameState; | |
50 | + d3dg = in_d3dg; | |
51 | + inputCtrl = in_inputCtrl; | |
52 | +} | |
53 | + | |
54 | +//! @brief シーン作成 | |
55 | +int scene::Create() | |
56 | +{ | |
57 | + inputCtrl->MoveMouseCenter(); | |
58 | + framecnt = 0; | |
59 | + | |
60 | + GameState->NextState(); | |
61 | + return 0; | |
62 | +} | |
63 | + | |
64 | +//! @brief シーン入力処理 | |
65 | +void scene::Input() | |
66 | +{ | |
67 | + inputCtrl->GetInputState(false); | |
68 | + | |
69 | + if( inputCtrl->CheckKeyDown(GetEscKeycode()) ){ | |
70 | + GameState->PushBackSpaceKey(); | |
71 | + } | |
72 | + | |
73 | + if( inputCtrl->CheckMouseButtonUpL() ){ | |
74 | + GameState->PushMouseButton(); | |
75 | + } | |
76 | +} | |
77 | + | |
78 | +//! @brief シーン計算処理 | |
79 | +void scene::Process() | |
80 | +{ | |
81 | + framecnt += 1; | |
82 | +} | |
83 | + | |
84 | +//! @brief シーン描画処理 | |
85 | +//! @return 成功:false 失敗:true | |
86 | +//! @attention 失敗した場合、D3DGraphicsクラスのResetD3D()関数を呼び出してください。 | |
87 | +bool scene::RenderMain() | |
88 | +{ | |
89 | + if( d3dg->StartRender() ){ return true; } | |
90 | + | |
91 | + d3dg->Draw2DBox(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
92 | + d3dg->Draw2DTextureFontText(10, 10, "hello world !", d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 20, 32); | |
93 | + | |
94 | + d3dg->ScreenBrightness(SCREEN_WIDTH, SCREEN_HEIGHT, GameConfig.GetBrightness()); | |
95 | + | |
96 | + return d3dg->EndRender(); | |
97 | +} | |
98 | + | |
99 | +//! @brief シーン解放処理 | |
100 | +void scene::Destroy() | |
101 | +{ | |
102 | + GameState->NextState(); | |
103 | +} | |
104 | + | |
105 | +//! @brief フレームカウントを元にアルファ値・透明度を設定(1回) | |
106 | +//! @param tframecnt 対象とするカウント値 | |
107 | +//! @param MaxAlpha 最大アルファ値 | |
108 | +//! @param timingsec 間隔・秒数 | |
109 | +//! @param offsetsec オフセット・秒数 | |
110 | +//! @param reversal 反転フラグ(false:フィールドイン true:フィールドアウト) | |
111 | +//! @return アルファ値 | |
112 | +float scene::GetEffectAlpha(unsigned int tframecnt, float MaxAlpha, float timingsec, float offsetsec, bool reversal) | |
113 | +{ | |
114 | + float alpha; | |
115 | + unsigned int frametiming; | |
116 | + unsigned int frameoffset; | |
117 | + | |
118 | + frametiming = (unsigned int)(timingsec*GAMEFPS); | |
119 | + frameoffset = (unsigned int)(offsetsec*GAMEFPS); | |
120 | + alpha = MaxAlpha/frametiming * (tframecnt - frameoffset); | |
121 | + | |
122 | + if( alpha < 0.0f ){ alpha = 0.0f; } | |
123 | + if( alpha > 1.0f ){ alpha = 1.0f; } | |
124 | + | |
125 | + if( reversal == true ){ | |
126 | + return 1.0f - alpha; | |
127 | + } | |
128 | + return alpha; | |
129 | +} | |
130 | + | |
131 | +//! @brief フレームカウントを元にアルファ値・透明度を設定(ループ) | |
132 | +//! @param tframecnt 対象とするカウント値 | |
133 | +//! @param MaxAlpha 最大アルファ値 | |
134 | +//! @param timingsec 間隔・秒数 | |
135 | +//! @param reversal 反転フラグ(false:フィールドイン true:フィールドアウト) | |
136 | +//! @return アルファ値 | |
137 | +float scene::GetEffectAlphaLoop(unsigned int tframecnt, float MaxAlpha, float timingsec, bool reversal) | |
138 | +{ | |
139 | + float alpha; | |
140 | + unsigned int frametiming; | |
141 | + | |
142 | + frametiming = (unsigned int)(timingsec*GAMEFPS); | |
143 | + alpha = MaxAlpha/frametiming * (tframecnt%frametiming); | |
144 | + | |
145 | + if( reversal == true ){ | |
146 | + return 1.0f - alpha; | |
147 | + } | |
148 | + return alpha; | |
149 | +} | |
150 | + | |
151 | +//! @brief コンストラクタ | |
152 | +D2Dscene::D2Dscene() | |
153 | +{} | |
154 | + | |
155 | +//! @brief ディストラクタ | |
156 | +D2Dscene::~D2Dscene() | |
157 | +{} | |
158 | + | |
159 | +//! @brief 2Dシーン初期化 | |
160 | +int D2Dscene::Create() | |
161 | +{ | |
162 | + gametitle = d3dg->LoadTexture("data\\title.dds", false, false); | |
163 | + GameState->NextState(); | |
164 | + if( gametitle == -1 ){ return 1; } | |
165 | + return 0; | |
166 | +} | |
167 | + | |
168 | +//! @brief 2Dシーン描画処理(2D) | |
169 | +void D2Dscene::Render2D() | |
170 | +{ | |
171 | + d3dg->Draw2DTextureFontText(10, 10, "hello world !", d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 20, 32); | |
172 | +} | |
173 | + | |
174 | +//! @brief 2Dシーン描画処理(メイン) | |
175 | +//! @return 成功:false 失敗:true | |
176 | +//! @attention 失敗した場合、D3DGraphicsクラスのResetD3D()関数を呼び出してください。 | |
177 | +bool D2Dscene::RenderMain() | |
178 | +{ | |
179 | + if( d3dg->StartRender() ){ return true; } | |
180 | + | |
181 | + d3dg->Draw2DTexture(0, 0, gametitle, SCREEN_WIDTH, SCREEN_HEIGHT, 0.4f); | |
182 | + d3dg->Draw2DBox(11, 11, SCREEN_WIDTH - 10, SCREEN_HEIGHT - 10, d3dg->GetColorCode(0.0f,0.0f,0.0f,0.75f)); | |
183 | + | |
184 | + Render2D(); | |
185 | + | |
186 | + d3dg->ScreenBrightness(SCREEN_WIDTH, SCREEN_HEIGHT, GameConfig.GetBrightness()); | |
187 | + | |
188 | + return d3dg->EndRender(); | |
189 | +} | |
190 | + | |
191 | +//! @brief 2Dシーン解放 | |
192 | +void D2Dscene::Destroy() | |
193 | +{ | |
194 | + d3dg->CleanupTexture(gametitle); | |
195 | + GameState->NextState(); | |
196 | +} | |
197 | + | |
198 | + | |
199 | +//! @brief コンストラクタ | |
200 | +D3Dscene::D3Dscene() | |
201 | +{} | |
202 | + | |
203 | +//! @brief ディストラクタ | |
204 | +D3Dscene::~D3Dscene() | |
205 | +{} | |
206 | + | |
207 | +//! @brief 3Dシーンクラスを設定 | |
208 | +void D3Dscene::SetClass(StateMachine *in_GameState, D3DGraphics *in_d3dg, InputControl *in_inputCtrl, SoundManager *in_GameSound) | |
209 | +{ | |
210 | + GameState = in_GameState; | |
211 | + d3dg = in_d3dg; | |
212 | + inputCtrl = in_inputCtrl; | |
213 | + GameSound = in_GameSound; | |
214 | +} | |
215 | + | |
216 | +//! @brief 3Dシーン主計算処理 | |
217 | +void D3Dscene::Process() | |
218 | +{ | |
219 | + GameSound->PlayWorldSound(camera_x, camera_y, camera_z, camera_rx); | |
220 | +} | |
221 | + | |
222 | +//! @brief 3Dシーンサウンド再生処理 | |
223 | +void D3Dscene::Sound() | |
224 | +{ | |
225 | + //サウンドを再生 | |
226 | + GameSound->PlayWorldSound(camera_x, camera_y, camera_z, camera_rx); | |
227 | +} | |
228 | + | |
229 | +//! @brief 3Dシーン描画処理(3D) | |
230 | +void D3Dscene::Render3D() | |
231 | +{} | |
232 | + | |
233 | +//! @brief 3Dシーン描画処理(2D) | |
234 | +void D3Dscene::Render2D() | |
235 | +{} | |
236 | + | |
237 | +//! @brief 3Dシーン描画処理(メイン) | |
238 | +//! @return 成功:false 失敗:true | |
239 | +//! @attention 失敗した場合、D3DGraphicsクラスのResetD3D()関数を呼び出してください。 | |
240 | +bool D3Dscene::RenderMain() | |
241 | +{ | |
242 | + if( d3dg->StartRender() ){ return true; } | |
243 | + | |
244 | + Render3D(); | |
245 | + Render2D(); | |
246 | + | |
247 | + d3dg->ScreenBrightness(SCREEN_WIDTH, SCREEN_HEIGHT, GameConfig.GetBrightness()); | |
248 | + | |
249 | + return d3dg->EndRender(); | |
250 | +} | |
\ No newline at end of file |
@@ -0,0 +1,3100 @@ | ||
1 | +//! @file gamemain.cpp | |
2 | +//! @brief ゲームメイン処理のサンプルコード | |
3 | + | |
4 | +//-------------------------------------------------------------------------------- | |
5 | +// | |
6 | +// OpenXOPS | |
7 | +// Copyright (c) 2014-2015, OpenXOPS Project / [-_-;](mikan) All rights reserved. | |
8 | +// | |
9 | +// Redistribution and use in source and binary forms, with or without | |
10 | +// modification, are permitted provided that the following conditions are met: | |
11 | +// * Redistributions of source code must retain the above copyright notice, | |
12 | +// this list of conditions and the following disclaimer. | |
13 | +// * Redistributions in binary form must reproduce the above copyright notice, | |
14 | +// this list of conditions and the following disclaimer in the documentation | |
15 | +// and/or other materials provided with the distribution. | |
16 | +// * Neither the name of the OpenXOPS Project nor the names of its contributors | |
17 | +// may be used to endorse or promote products derived from this software | |
18 | +// without specific prior written permission. | |
19 | +// | |
20 | +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
21 | +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
22 | +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
23 | +// DISCLAIMED. IN NO EVENT SHALL OpenXOPS Project BE LIABLE FOR ANY | |
24 | +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
25 | +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
26 | +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
27 | +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 | +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
29 | +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | +//-------------------------------------------------------------------------------- | |
31 | + | |
32 | +#include "gamemain.h" | |
33 | + | |
34 | +D3DGraphics d3dg; //!< 描画クラス | |
35 | +InputControl inputCtrl; //!< 入力取得クラス | |
36 | +SoundControl SoundCtrl; //!< サウンド再生クラス | |
37 | + | |
38 | +//! ゲームの設定値 | |
39 | +ParameterInfo GameParamInfo; | |
40 | + | |
41 | +//! リソース管理 | |
42 | +ResourceManager Resource; | |
43 | + | |
44 | +SoundManager GameSound; //!< ゲーム効果音再生クラス | |
45 | + | |
46 | +BlockDataInterface BlockData; //!< ブロックデータ管理クラス | |
47 | +PointDataInterface PointData; //!< ポイントデータ管理クラス | |
48 | +MIFInterface MIFdata; //!< MIFコントロール | |
49 | +AddonList GameAddon; //!< addonのリスト | |
50 | +Collision CollD; //!< 当たり判定管理クラス | |
51 | +ObjectManager ObjMgr; //!< オブジェクト管理クラス | |
52 | +AIcontrol HumanAI[MAX_HUMAN]; //!< AI管理クラス | |
53 | + | |
54 | +GameInfo GameInfoData; //!< ゲームの状態 | |
55 | + | |
56 | +EventControl Event[TOTAL_EVENTLINE]; //!< イベント制御クラス | |
57 | + | |
58 | + | |
59 | +//! @brief 基本的な初期化処理 | |
60 | +int InitGame(HWND hWnd) | |
61 | +{ | |
62 | + //DirectX初期化 | |
63 | + if( d3dg.InitD3D(hWnd, "data\\char.dds", GameConfig.GetFullscreenFlag()) ){ | |
64 | + MessageBox(hWnd, "Direct3Dの作成に失敗しました", "error", MB_OK); | |
65 | + return 1; | |
66 | + } | |
67 | + | |
68 | + //Directinputの初期化 | |
69 | + if( inputCtrl.InitD3Dinput(hWnd) ){ | |
70 | + MessageBox(hWnd, "Input initialization error", "error", MB_OK); | |
71 | + return 1; | |
72 | + } | |
73 | + | |
74 | + //EASY DIRECT SOUND 初期化 | |
75 | + if( SoundCtrl.InitSound(hWnd) ){ | |
76 | + MessageBox(hWnd, "DLL open failed", "error", MB_OK); | |
77 | + return 1; | |
78 | + } | |
79 | + | |
80 | + //設定値を初期化 | |
81 | + GameParamInfo.InitInfo(); | |
82 | + | |
83 | + //リソースの初期設定 | |
84 | + Resource.SetParameterInfo(&GameParamInfo); | |
85 | + Resource.SetD3DGraphics(&d3dg); | |
86 | + Resource.SetSoundControl(&SoundCtrl); | |
87 | + | |
88 | + //リソースを初期化 | |
89 | + Resource.LoadHumanModel(); | |
90 | + Resource.LoadWeaponModelTexture(); | |
91 | + Resource.LoadWeaponSound(); | |
92 | + Resource.LoadSmallObjectModelTexture(); | |
93 | + Resource.LoadSmallObjectSound(); | |
94 | + Resource.LoadScopeTexture(); | |
95 | + Resource.LoadBulletModelTexture(); | |
96 | + Resource.LoadBulletSound(); | |
97 | + Resource.LoadEffectTexture(); | |
98 | + | |
99 | + //効果音初期化 | |
100 | + float volume; | |
101 | + if( GameConfig.GetSoundFlag() == false ){ | |
102 | + volume = 0.0f; | |
103 | + } | |
104 | + else{ | |
105 | + volume = 1.0f; | |
106 | + } | |
107 | + GameSound.SetClass(&SoundCtrl, &Resource, &GameParamInfo); | |
108 | + SoundCtrl.SetVolume(volume); | |
109 | + | |
110 | + //オブジェクトマネージャー初期化 | |
111 | + ObjMgr.SetClass(&GameParamInfo, &d3dg, &Resource, &BlockData, &PointData, &CollD, &GameSound, &MIFdata); | |
112 | + | |
113 | + //addonリスト作成 | |
114 | + GameAddon.LoadFiledata("addon\\"); | |
115 | + | |
116 | + GameInfoData.selectaddon = false; | |
117 | + | |
118 | + return 0; | |
119 | +} | |
120 | + | |
121 | +//! @brief DirectXをリセットする | |
122 | +//! @return 失敗:1 それ以外:0 | |
123 | +//! @attention 通常は、描画処理に失敗した場合に限り呼び出してください。 | |
124 | +int ResetGame(HWND hWnd) | |
125 | +{ | |
126 | + int rtn = d3dg.ResetD3D(hWnd); | |
127 | + | |
128 | + if( rtn == 0 ){ | |
129 | + //リソースを初期化 | |
130 | + Resource.LoadHumanModel(); | |
131 | + Resource.LoadWeaponModelTexture(); | |
132 | + Resource.LoadSmallObjectModelTexture(); | |
133 | + Resource.LoadScopeTexture(); | |
134 | + Resource.LoadBulletModelTexture(); | |
135 | + Resource.LoadEffectTexture(); | |
136 | + | |
137 | + //現在の画面を再スタートさせる | |
138 | + GameState.PushF12Key(); | |
139 | + } | |
140 | + if( rtn == 1 ){ | |
141 | + // | |
142 | + } | |
143 | + if( rtn == 2 ){ | |
144 | + MessageBox(hWnd, "Resetに失敗しました", "ERROR", MB_OK); | |
145 | + PostMessage(hWnd, WM_CLOSE, 0L, 0L); | |
146 | + return 1; | |
147 | + } | |
148 | + return 0; | |
149 | +} | |
150 | + | |
151 | +//! @brief コンストラクタ | |
152 | +opening::opening() | |
153 | +{} | |
154 | + | |
155 | +//! @brief ディストラクタ | |
156 | +opening::~opening() | |
157 | +{} | |
158 | + | |
159 | +int opening::Create() | |
160 | +{ | |
161 | + //ブロックデータ読み込み | |
162 | + if( BlockData.LoadFiledata("data\\map10\\temp.bd1") ){ | |
163 | + //block data open failed | |
164 | + return 1; | |
165 | + } | |
166 | + BlockData.CalculationBlockdata(false); | |
167 | + d3dg->LoadMapdata(&BlockData, "data\\map10\\"); | |
168 | + CollD.InitCollision(&BlockData); | |
169 | + | |
170 | + //ポイントデータ読み込み | |
171 | + if( PointData.LoadFiledata("data\\map10\\op.pd1") ){ | |
172 | + //point data open failed | |
173 | + return 1; | |
174 | + } | |
175 | + ObjMgr.LoadPointData(); | |
176 | + ObjMgr.SetPlayerID(MAX_HUMAN-1); //実在しない人をプレイヤーに(銃声のサウンド再生対策) | |
177 | + | |
178 | + //AI設定 | |
179 | + for(int i=0; i<MAX_HUMAN; i++){ | |
180 | + HumanAI[i].SetClass(&ObjMgr, i, &BlockData, &PointData, &GameParamInfo, &CollD, GameSound); | |
181 | + HumanAI[i].Init(); | |
182 | + } | |
183 | + | |
184 | + //背景空読み込み | |
185 | + Resource.LoadSkyModelTexture(1); | |
186 | + | |
187 | + //opening_banner = d3dg->LoadTexture("banner.png", true, false); | |
188 | + | |
189 | + //サウンド初期化 | |
190 | + GameSound->InitWorldSound(); | |
191 | + | |
192 | + //マウスカーソルを中央へ移動 | |
193 | + inputCtrl->MoveMouseCenter(); | |
194 | + framecnt = 0; | |
195 | + | |
196 | + GameState->NextState(); | |
197 | + return 0; | |
198 | +} | |
199 | + | |
200 | +//! @todo カメラの移動を滑らかにする | |
201 | +void opening::Process() | |
202 | +{ | |
203 | + //オブジェクトマネージャーを実行 | |
204 | + ObjMgr.Process(-1, camera_rx, camera_ry); | |
205 | + | |
206 | + //AIを実行 | |
207 | + for(int i=0; i<MAX_HUMAN; i++){ | |
208 | + HumanAI[i].Process(); | |
209 | + } | |
210 | + | |
211 | + //カメラワークを求める | |
212 | + if( framecnt < 3*((int)GAMEFPS) ){ | |
213 | + camera_x = -5.0f; | |
214 | + camera_y = 58.0f; | |
215 | + camera_z = 29.0f; | |
216 | + camera_rx = (float)M_PI/180*206; | |
217 | + camera_ry = (float)M_PI/180*12; | |
218 | + } | |
219 | + else if( framecnt < 5*((int)GAMEFPS) ){ | |
220 | + camera_rx += (float)M_PI/180*1.1f; | |
221 | + camera_ry -= (float)M_PI/180*0.7f; | |
222 | + } | |
223 | + else if( framecnt < 17*((int)GAMEFPS) ){ | |
224 | + camera_z += 0.08f; | |
225 | + camera_y -= 0.05f; | |
226 | + } | |
227 | + else { | |
228 | + GameState->PushMouseButton(); | |
229 | + } | |
230 | + | |
231 | + framecnt += 1; | |
232 | +} | |
233 | + | |
234 | +void opening::Render3D() | |
235 | +{ | |
236 | + int skymodel, skytexture; | |
237 | + | |
238 | + //フォグとカメラを設定 | |
239 | + d3dg->SetFog(1); | |
240 | + d3dg->SetCamera(camera_x, camera_y, camera_z, camera_rx, camera_ry, VIEWANGLE_NORMAL); | |
241 | + | |
242 | + //カメラ座標に背景空を描画 | |
243 | + d3dg->SetWorldTransform(camera_x, camera_y, camera_z, 0.0f, 0.0f, 2.0f); | |
244 | + Resource.GetSkyModelTexture(&skymodel, &skytexture); | |
245 | + d3dg->RenderModel(skymodel, skytexture); | |
246 | + | |
247 | + //Zバッファを初期化 | |
248 | + d3dg->ResetZbuffer(); | |
249 | + | |
250 | + //マップを描画 | |
251 | + d3dg->ResetWorldTransform(); | |
252 | + d3dg->DrawMapdata(false); | |
253 | + | |
254 | + //オブジェクトを描画 | |
255 | + ObjMgr.Render(camera_x, camera_y, camera_z, 0); | |
256 | +} | |
257 | + | |
258 | +void opening::Render2D() | |
259 | +{ | |
260 | + float effect = 0.0f; | |
261 | + | |
262 | + //ブラックアウト設定 | |
263 | + if( framecnt < (int)(1.0f*GAMEFPS) ){ | |
264 | + effect = GetEffectAlpha(framecnt, 1.0f, 1.0f, 0.0f, true); | |
265 | + } | |
266 | + if( ((int)(1.0f*GAMEFPS) <= framecnt)&&(framecnt < (int)(13.0f*GAMEFPS)) ){ | |
267 | + effect = 0.0f; | |
268 | + } | |
269 | + if( ((int)(11.0f*GAMEFPS) <= framecnt)&&(framecnt < (int)(15.0f*GAMEFPS)) ){ | |
270 | + effect = GetEffectAlpha(framecnt, 1.0f, 4.0f, 11.0f, false); | |
271 | + } | |
272 | + if( (int)(15.0f*GAMEFPS) <= framecnt ){ | |
273 | + effect = 1.0f; | |
274 | + } | |
275 | + d3dg->Draw2DBox(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, d3dg->GetColorCode(0.0f,0.0f,0.0f,effect)); | |
276 | + | |
277 | + //上下の黒縁描画 | |
278 | + d3dg->Draw2DBox(0, 0, SCREEN_WIDTH, 40, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
279 | + d3dg->Draw2DBox(0, SCREEN_HEIGHT - 40, SCREEN_WIDTH, SCREEN_HEIGHT, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
280 | + | |
281 | + //プロジェクト名 | |
282 | + if( ((int)(0.5f*GAMEFPS) < framecnt)&&(framecnt < (int)(4.0f*GAMEFPS)) ){ | |
283 | + char str[32]; | |
284 | + float effectA = 1.0f; | |
285 | + sprintf(str, GAMENAME" project", 0, 0); | |
286 | + if( framecnt < (int)(1.5f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 0.5f, false); } | |
287 | + if( framecnt > (int)(3.0f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 3.0f, true); } | |
288 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - strlen(str)*22/2, SCREEN_HEIGHT - 140, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,effectA), 22, 22); | |
289 | + } | |
290 | + | |
291 | + //スタッフ名・その1 | |
292 | + if( ((int)(4.0f*GAMEFPS) < framecnt)&&(framecnt < (int)(8.0f*GAMEFPS)) ){ | |
293 | + float effectA = 1.0f; | |
294 | + if( framecnt < (int)(5.0f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 4.0f, false); } | |
295 | + if( framecnt > (int)(7.0f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 7.0f, true); } | |
296 | + d3dg->Draw2DTextureFontText(60, 150, "ORIGINAL", d3dg->GetColorCode(1.0f,1.0f,1.0f,effectA), 20, 20); | |
297 | + } | |
298 | + if( ((int)(4.5f*GAMEFPS) < framecnt)&&(framecnt < (int)(8.5f*GAMEFPS)) ){ | |
299 | + float effectA = 1.0f; | |
300 | + if( framecnt < (int)(5.5f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 4.5f, false); } | |
301 | + if( framecnt > (int)(7.5f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 7.5f, true); } | |
302 | + d3dg->Draw2DTextureFontText(100, 180, "nine-two", d3dg->GetColorCode(1.0f,1.0f,1.0f,effectA), 20, 20); | |
303 | + d3dg->Draw2DTextureFontText(100, 210, "TENNKUU", d3dg->GetColorCode(1.0f,1.0f,1.0f,effectA), 20, 20); | |
304 | + } | |
305 | + | |
306 | + //スタッフ名・その2 | |
307 | + if( ((int)(7.0f*GAMEFPS) < framecnt)&&(framecnt < (int)(11.0f*GAMEFPS)) ){ | |
308 | + float effectA = 1.0f; | |
309 | + if( framecnt < (int)(8.0f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 7.0f, false); } | |
310 | + if( framecnt > (int)(10.0f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 10.0f, true); } | |
311 | + d3dg->Draw2DTextureFontText(330, 300, "REMAKE", d3dg->GetColorCode(1.0f,1.0f,1.0f,effectA), 20, 20); | |
312 | + } | |
313 | + if( ((int)(7.5f*GAMEFPS) < framecnt)&&(framecnt < (int)(11.5f*GAMEFPS)) ){ | |
314 | + float effectA = 1.0f; | |
315 | + if( framecnt < (int)(8.5f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 7.5f, false); } | |
316 | + if( framecnt > (int)(10.5f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 10.5f, true); } | |
317 | + d3dg->Draw2DTextureFontText(370, 330, "[-_-;](mikan)", d3dg->GetColorCode(1.0f,1.0f,1.0f,effectA), 20, 20); | |
318 | + //d3dg->Draw2DTexture(410, 360, opening_banner, 200, 40, effectA); | |
319 | + } | |
320 | + | |
321 | + //ゲーム名 | |
322 | + if( (int)(12.0f*GAMEFPS) <= framecnt ){ //framecnt < (int)(17.0f*GAMEFPS) | |
323 | + char str[32]; | |
324 | + float effectA = 1.0f; | |
325 | + sprintf(str, GAMENAME, 0, 0); | |
326 | + if( framecnt < (int)(13.0f*GAMEFPS) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 12.0f, false); } | |
327 | + if( ((int)(16.0f*GAMEFPS) < framecnt)&&(framecnt < (int)(17.0f*GAMEFPS)) ){ effectA = GetEffectAlpha(framecnt, 1.0f, 1.0f, 16.0f, true); } | |
328 | + if( framecnt >= (int)(17.0f*GAMEFPS) ){ effectA = 0.0f; } | |
329 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - strlen(str)*22/2, (SCREEN_HEIGHT-11)/2, str, d3dg->GetColorCode(1.0f,0.0f,0.0f,effectA), 22, 22); | |
330 | + } | |
331 | +} | |
332 | + | |
333 | +void opening::Destroy() | |
334 | +{ | |
335 | + //ブロックデータ解放 | |
336 | + d3dg->CleanupMapdata(); | |
337 | + | |
338 | + //オブジェクトマネージャー解放 | |
339 | + ObjMgr.Cleanup(); | |
340 | + | |
341 | + //背景空解放 | |
342 | + Resource.CleanupSkyModelTexture(); | |
343 | + | |
344 | + //d3dg->CleanupTexture(opening_banner); | |
345 | + | |
346 | + GameState->NextState(); | |
347 | +} | |
348 | + | |
349 | +//! @brief コンストラクタ | |
350 | +mainmenu::mainmenu() | |
351 | +{ | |
352 | + mainmenu_scrollitems_official = 0; | |
353 | + mainmenu_scrollitems_addon = 0; | |
354 | +} | |
355 | + | |
356 | +//! @brief ディストラクタ | |
357 | +mainmenu::~mainmenu() | |
358 | +{} | |
359 | + | |
360 | +int mainmenu::Create() | |
361 | +{ | |
362 | + char path[MAX_PATH]; | |
363 | + char bdata[MAX_PATH]; | |
364 | + char pdata[MAX_PATH]; | |
365 | + | |
366 | + //デモを決定し読み込む | |
367 | + switch( GetRand(6) ){ | |
368 | + case 0: | |
369 | + strcpy(path, "data\\map2\\"); | |
370 | + break; | |
371 | + case 1: | |
372 | + strcpy(path, "data\\map4\\"); | |
373 | + break; | |
374 | + case 2: | |
375 | + strcpy(path, "data\\map5\\"); | |
376 | + break; | |
377 | + case 3: | |
378 | + strcpy(path, "data\\map7\\"); | |
379 | + break; | |
380 | + case 4: | |
381 | + strcpy(path, "data\\map8\\"); | |
382 | + break; | |
383 | + case 5: | |
384 | + strcpy(path, "data\\map16\\"); | |
385 | + break; | |
386 | + } | |
387 | + strcpy(bdata, path); | |
388 | + strcat(bdata, "temp.bd1"); | |
389 | + strcpy(pdata, path); | |
390 | + strcat(pdata, "demo.pd1"); | |
391 | + | |
392 | + //ブロックデータ読み込み | |
393 | + if( BlockData.LoadFiledata(bdata) ){ | |
394 | + //block data open failed | |
395 | + return 1; | |
396 | + } | |
397 | + BlockData.CalculationBlockdata(false); | |
398 | + d3dg->LoadMapdata(&BlockData, path); | |
399 | + CollD.InitCollision(&BlockData); | |
400 | + | |
401 | + //ポイントデータ読み込み | |
402 | + if( PointData.LoadFiledata(pdata) ){ | |
403 | + //point data open failed | |
404 | + return 1; | |
405 | + } | |
406 | + ObjMgr.LoadPointData(); | |
407 | + | |
408 | + //AI設定 | |
409 | + for(int i=0; i<MAX_HUMAN; i++){ | |
410 | + HumanAI[i].SetClass(&ObjMgr, i, &BlockData, &PointData, &GameParamInfo, &CollD, GameSound); | |
411 | + HumanAI[i].Init(); | |
412 | + } | |
413 | + | |
414 | + gametitle = d3dg->LoadTexture("data\\title.dds", false, false); | |
415 | + | |
416 | + //サウンド初期化 | |
417 | + GameSound->InitWorldSound(); | |
418 | + | |
419 | + mainmenu_mouseX = SCREEN_WIDTH/2; | |
420 | + mainmenu_mouseY = SCREEN_HEIGHT/2; | |
421 | + | |
422 | + //標準ミッションのスクロールバーの設定 | |
423 | + if( TOTAL_OFFICIALMISSION > TOTAL_MENUITEMS ){ | |
424 | + mainmenu_scrollbar_official_height = (float)(MAINMENU_H-25) / TOTAL_OFFICIALMISSION * TOTAL_MENUITEMS; | |
425 | + mainmenu_scrollbar_official_scale = ((float)(MAINMENU_H-25) - mainmenu_scrollbar_official_height) / (TOTAL_OFFICIALMISSION - TOTAL_MENUITEMS); | |
426 | + } | |
427 | + else{ | |
428 | + mainmenu_scrollbar_official_height = 0.0f; | |
429 | + mainmenu_scrollbar_official_scale = 0.0f; | |
430 | + } | |
431 | + | |
432 | + //addonのスクロールバーの設定 | |
433 | + if( GameAddon.GetTotaldatas() > TOTAL_MENUITEMS ){ | |
434 | + mainmenu_scrollbar_addon_height = (float)(MAINMENU_H-25) / GameAddon.GetTotaldatas() * TOTAL_MENUITEMS; | |
435 | + mainmenu_scrollbar_addon_scale = ((float)(MAINMENU_H-25) - mainmenu_scrollbar_addon_height) / (GameAddon.GetTotaldatas() - TOTAL_MENUITEMS); | |
436 | + } | |
437 | + else{ | |
438 | + mainmenu_scrollbar_addon_height = 0.0f; | |
439 | + mainmenu_scrollbar_addon_scale = 0.0f; | |
440 | + } | |
441 | + | |
442 | + mainmenu_scrollbar_official_y = 141; | |
443 | + mainmenu_scrollbar_addon_y = 141; | |
444 | + mainmenu_scrollbar_flag = false; | |
445 | + inputCtrl->MoveMouseCenter(); | |
446 | + framecnt = 0; | |
447 | + | |
448 | + GameState->NextState(); | |
449 | + return 0; | |
450 | +} | |
451 | + | |
452 | +void mainmenu::Input() | |
453 | +{ | |
454 | + inputCtrl->GetInputState(false); | |
455 | + | |
456 | + //スクロールバーの情報などを取得 | |
457 | + int scrollitems; | |
458 | + float scrollbar_height; | |
459 | + float scrollbar_scale; | |
460 | + int scrollbar_y; | |
461 | + int totalmission; | |
462 | + if( GameInfoData.selectaddon == false ){ | |
463 | + scrollitems = mainmenu_scrollitems_official; | |
464 | + scrollbar_height = mainmenu_scrollbar_official_height; | |
465 | + scrollbar_scale = mainmenu_scrollbar_official_scale; | |
466 | + scrollbar_y = mainmenu_scrollbar_official_y; | |
467 | + totalmission = TOTAL_OFFICIALMISSION; | |
468 | + } | |
469 | + else{ | |
470 | + scrollitems = mainmenu_scrollitems_addon; | |
471 | + scrollbar_height = mainmenu_scrollbar_addon_height; | |
472 | + scrollbar_scale = mainmenu_scrollbar_addon_scale; | |
473 | + scrollbar_y = mainmenu_scrollbar_addon_y; | |
474 | + totalmission = GameAddon.GetTotaldatas(); | |
475 | + } | |
476 | + | |
477 | + //マウス座標を取得 | |
478 | + int y = mainmenu_mouseY; | |
479 | + inputCtrl->GetMouseMovement(&mainmenu_mouseX, &mainmenu_mouseY); | |
480 | + if( mainmenu_mouseX < 0 ){ mainmenu_mouseX = 0; } | |
481 | + if( mainmenu_mouseX > SCREEN_WIDTH-1 ){ mainmenu_mouseX = SCREEN_WIDTH-1; } | |
482 | + if( mainmenu_mouseY < 0 ){ mainmenu_mouseY = 0; } | |
483 | + if( mainmenu_mouseY > SCREEN_HEIGHT-1 ){ mainmenu_mouseY = SCREEN_HEIGHT-1; } | |
484 | + | |
485 | + //ESCキーを処理 | |
486 | + if( inputCtrl->CheckKeyDown(GetEscKeycode()) ){ | |
487 | + GameState->PushBackSpaceKey(); | |
488 | + } | |
489 | + | |
490 | + //スクロールバーを押したか判定 | |
491 | + if( inputCtrl->CheckMouseButtonDownL() ){ | |
492 | + if( ((MAINMENU_X+341) < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+360))&&(MAINMENU_Y+1 + (int)(scrollbar_scale*scrollitems) < mainmenu_mouseY) | |
493 | + &&(mainmenu_mouseY < MAINMENU_Y+1 + (int)(scrollbar_scale*scrollitems + scrollbar_height)) | |
494 | + ){ | |
495 | + mainmenu_scrollbar_flag = true; | |
496 | + } | |
497 | + } | |
498 | + | |
499 | + if( inputCtrl->CheckMouseButtonUpL() ){ | |
500 | + mainmenu_scrollbar_flag = false; | |
501 | + | |
502 | + // UP | |
503 | + if( (MAINMENU_X < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+340))&&(MAINMENU_Y < mainmenu_mouseY)&&(mainmenu_mouseY < MAINMENU_Y+30) ){ | |
504 | + if( scrollitems > 0 ){ scrollitems -= 1; } | |
505 | + } | |
506 | + | |
507 | + // DOWN | |
508 | + if( (MAINMENU_X < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+340))&&((MAINMENU_Y+MAINMENU_H-55) < mainmenu_mouseY)&&(mainmenu_mouseY < (MAINMENU_Y+MAINMENU_H-55+30)) ){ | |
509 | + if( scrollitems < (totalmission - TOTAL_MENUITEMS) ){ scrollitems += 1; } | |
510 | + } | |
511 | + | |
512 | + //ミッション選択 | |
513 | + for(int i=0; i<TOTAL_MENUITEMS; i++){ | |
514 | + char name[32]; | |
515 | + if( GameInfoData.selectaddon == false ){ | |
516 | + GameParamInfo.GetOfficialMission(scrollitems + i, name, NULL, NULL, NULL); | |
517 | + } | |
518 | + else{ | |
519 | + strcpy(name, GameAddon.GetMissionName(scrollitems + i)); | |
520 | + } | |
521 | + | |
522 | + if( (MAINMENU_X < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+(signed)strlen(name)*20))&&(MAINMENU_Y+30 + i*30 < mainmenu_mouseY)&&(mainmenu_mouseY < MAINMENU_Y+30 + i*30 + 26) ){ | |
523 | + GameInfoData.selectmission_id = scrollitems + i; | |
524 | + GameState->PushMouseButton(); | |
525 | + } | |
526 | + } | |
527 | + } | |
528 | + | |
529 | + //スクロールバーの移動 | |
530 | + if( mainmenu_scrollbar_flag == true ){ | |
531 | + scrollbar_y += mainmenu_mouseY - y; | |
532 | + if( scrollbar_y < MAINMENU_Y+1 ){ scrollbar_y = MAINMENU_Y+1; } | |
533 | + if( scrollbar_y > MAINMENU_Y+MAINMENU_H-24 - (int)(scrollbar_height) ){ scrollbar_y = MAINMENU_Y+MAINMENU_H-24 - (int)(scrollbar_height); } | |
534 | + | |
535 | + scrollitems = (scrollbar_y - (MAINMENU_Y+1)) / (int)(scrollbar_scale); | |
536 | + if( scrollitems < 0 ){ | |
537 | + scrollitems = 0; | |
538 | + } | |
539 | + if( scrollitems > (totalmission - TOTAL_MENUITEMS) ){ | |
540 | + scrollitems = (totalmission - TOTAL_MENUITEMS); | |
541 | + } | |
542 | + } | |
543 | + else{ | |
544 | + scrollbar_y = MAINMENU_Y+1 + (int)(scrollbar_scale*scrollitems); | |
545 | + } | |
546 | + | |
547 | + //スクロールバーの情報などを反映 | |
548 | + if( GameInfoData.selectaddon == false ){ | |
549 | + mainmenu_scrollitems_official = scrollitems; | |
550 | + mainmenu_scrollbar_official_y = scrollbar_y; | |
551 | + } | |
552 | + else{ | |
553 | + mainmenu_scrollitems_addon = scrollitems; | |
554 | + mainmenu_scrollbar_addon_y = scrollbar_y; | |
555 | + } | |
556 | + | |
557 | + //標準ミッションとアドオンリストの切り替え | |
558 | + if( inputCtrl->CheckMouseButtonUpL() ){ | |
559 | + if( (MAINMENU_X < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+340))&&((MAINMENU_Y+MAINMENU_H-25) < mainmenu_mouseY)&&(mainmenu_mouseY < (MAINMENU_Y+MAINMENU_H-2)) ){ | |
560 | + if( GameInfoData.selectaddon == false ){ | |
561 | + if( GameAddon.GetTotaldatas() > 0 ){ | |
562 | + GameInfoData.selectaddon = true; | |
563 | + } | |
564 | + } | |
565 | + else{ | |
566 | + GameInfoData.selectaddon = false; | |
567 | + } | |
568 | + } | |
569 | + } | |
570 | +} | |
571 | + | |
572 | +void mainmenu::Process() | |
573 | +{ | |
574 | + //オブジェクトマネージャーを実行 | |
575 | + ObjMgr.Process(-1, camera_rx, camera_ry); | |
576 | + | |
577 | + //AIを実行 | |
578 | + for(int i=0; i<MAX_HUMAN; i++){ | |
579 | + HumanAI[i].Process(); | |
580 | + } | |
581 | + | |
582 | + //カメラ位置を計算 | |
583 | + human *myHuman = ObjMgr.GetPlayerHumanObject(); | |
584 | + myHuman->GetPosData(&camera_x, &camera_y, &camera_z, NULL); | |
585 | + camera_x -= 4.0f; | |
586 | + camera_y += 22.0f; | |
587 | + camera_z -= 12.0f; | |
588 | + camera_rx = (float)M_PI/180 * (45); | |
589 | + camera_ry = (float)M_PI/180 * (-25); | |
590 | + | |
591 | + framecnt += 1; | |
592 | +} | |
593 | + | |
594 | +void mainmenu::Render3D() | |
595 | +{ | |
596 | + //フォグとカメラを設定 | |
597 | + d3dg->SetFog(0); | |
598 | + d3dg->SetCamera(camera_x, camera_y, camera_z, camera_rx, camera_ry, VIEWANGLE_NORMAL); | |
599 | + | |
600 | + //Zバッファを初期化 | |
601 | + d3dg->ResetZbuffer(); | |
602 | + | |
603 | + //マップを描画 | |
604 | + d3dg->ResetWorldTransform(); | |
605 | + d3dg->DrawMapdata(false); | |
606 | + | |
607 | + //オブジェクトを描画 | |
608 | + ObjMgr.Render(camera_x, camera_y, camera_z, 0); | |
609 | +} | |
610 | + | |
611 | +void mainmenu::Render2D() | |
612 | +{ | |
613 | + int color, color2; | |
614 | + float effect; | |
615 | + | |
616 | + //スクロールバーの情報などを取得 | |
617 | + int scrollitems; | |
618 | + float scrollbar_height; | |
619 | + int scrollbar_y; | |
620 | + int totalmission; | |
621 | + if( GameInfoData.selectaddon == false ){ | |
622 | + scrollitems = mainmenu_scrollitems_official; | |
623 | + scrollbar_height = mainmenu_scrollbar_official_height; | |
624 | + scrollbar_y = mainmenu_scrollbar_official_y; | |
625 | + totalmission = TOTAL_OFFICIALMISSION; | |
626 | + } | |
627 | + else{ | |
628 | + scrollitems = mainmenu_scrollitems_addon; | |
629 | + scrollbar_height = mainmenu_scrollbar_addon_height; | |
630 | + scrollbar_y = mainmenu_scrollbar_addon_y; | |
631 | + totalmission = GameAddon.GetTotaldatas(); | |
632 | + } | |
633 | + | |
634 | + //ゲームのバージョン情報描画 | |
635 | + d3dg->Draw2DTextureFontText(522+1, 75+1, GAMEVERSION, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f), 18, 22); | |
636 | + d3dg->Draw2DTextureFontText(522, 75, GAMEVERSION, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 18, 22); | |
637 | + | |
638 | + //メニューエリア描画 | |
639 | + if( GameAddon.GetTotaldatas() > 0 ){ //addonがあれば | |
640 | + d3dg->Draw2DBox(MAINMENU_X-1, MAINMENU_Y, MAINMENU_X+360, MAINMENU_Y+MAINMENU_H+1, d3dg->GetColorCode(0.0f,0.0f,0.0f,0.5f)); | |
641 | + } | |
642 | + else{ | |
643 | + d3dg->Draw2DBox(MAINMENU_X-1, MAINMENU_Y, MAINMENU_X+360, MAINMENU_Y+MAINMENU_H-24, d3dg->GetColorCode(0.0f,0.0f,0.0f,0.5f)); | |
644 | + } | |
645 | + d3dg->Draw2DBox(MAINMENU_X+341, MAINMENU_Y+1, MAINMENU_X+360, MAINMENU_Y+MAINMENU_H-24, d3dg->GetColorCode(0.5f,0.5f,0.5f,0.5f)); | |
646 | + | |
647 | + //スクロールバー描画 | |
648 | + if( totalmission > TOTAL_MENUITEMS ){ | |
649 | + //色を設定 | |
650 | + if( mainmenu_scrollbar_flag == true ){ | |
651 | + color = d3dg->GetColorCode(0.6f,0.3f,0.25f,1.0f); | |
652 | + color2 = d3dg->GetColorCode(0.8f,0.3f,0.25f,1.0f); | |
653 | + } | |
654 | + else if( ((MAINMENU_X+341) < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+360))&&(scrollbar_y < mainmenu_mouseY)&&(mainmenu_mouseY < scrollbar_y + (int)scrollbar_height) ){ | |
655 | + color = d3dg->GetColorCode(0.4f,0.67f,0.57f,1.0f); | |
656 | + color2 = d3dg->GetColorCode(0.38f,0.77f,0.64f,1.0f); | |
657 | + } | |
658 | + else{ | |
659 | + color = d3dg->GetColorCode(0.6f,0.6f,0.25f,1.0f); | |
660 | + color2 = d3dg->GetColorCode(0.8f,0.8f,0.25f,1.0f); | |
661 | + } | |
662 | + | |
663 | + //描画 | |
664 | + d3dg->Draw2DBox(MAINMENU_X+341, scrollbar_y, MAINMENU_X+360, scrollbar_y + (int)scrollbar_height, color); | |
665 | + d3dg->Draw2DBox(MAINMENU_X+341+3, scrollbar_y +3, MAINMENU_X+360-3, scrollbar_y + (int)scrollbar_height -3, color2); | |
666 | + } | |
667 | + | |
668 | + //'< UP >'描画 | |
669 | + if( scrollitems > 0 ){ | |
670 | + d3dg->Draw2DTextureFontText(MAINMENU_X+1, MAINMENU_Y+1, "< UP >", d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f), 25, 26); | |
671 | + | |
672 | + //文字の色を設定 | |
673 | + if( (MAINMENU_X < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+340))&&(MAINMENU_Y < mainmenu_mouseY)&&(mainmenu_mouseY < MAINMENU_Y+30) ){ | |
674 | + color = d3dg->GetColorCode(0.0f,1.0f,1.0f,1.0f); | |
675 | + } | |
676 | + else{ | |
677 | + color = d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f); | |
678 | + } | |
679 | + | |
680 | + //文字を描画 | |
681 | + d3dg->Draw2DTextureFontText(MAINMENU_X, MAINMENU_Y, "< UP >", color, 25, 26); | |
682 | + } | |
683 | + else{ | |
684 | + d3dg->Draw2DTextureFontText(MAINMENU_X+1, MAINMENU_Y+1, "< UP >", d3dg->GetColorCode(0.6f,0.6f,0.6f,1.0f), 25, 26); | |
685 | + } | |
686 | + | |
687 | + //'< DOWN >'描画 | |
688 | + if( scrollitems < (totalmission - TOTAL_MENUITEMS) ){ | |
689 | + d3dg->Draw2DTextureFontText(MAINMENU_X+1, MAINMENU_Y+MAINMENU_H-55+1, "< DOWN >", d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f), 25, 26); | |
690 | + | |
691 | + //文字の色を設定 | |
692 | + if( (MAINMENU_X < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+340))&&((MAINMENU_Y+MAINMENU_H-55) < mainmenu_mouseY)&&(mainmenu_mouseY < (MAINMENU_Y+MAINMENU_H-55+30)) ){ | |
693 | + color = d3dg->GetColorCode(0.0f,1.0f,1.0f,1.0f); | |
694 | + } | |
695 | + else{ | |
696 | + color = d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f); | |
697 | + } | |
698 | + | |
699 | + //文字を描画 | |
700 | + d3dg->Draw2DTextureFontText(MAINMENU_X, MAINMENU_Y+MAINMENU_H-55, "< DOWN >", color, 25, 26); | |
701 | + } | |
702 | + else{ | |
703 | + d3dg->Draw2DTextureFontText(MAINMENU_X+1, MAINMENU_Y+MAINMENU_H-55+1, "< DOWN >", d3dg->GetColorCode(0.6f,0.6f,0.6f,1.0f), 25, 26); | |
704 | + } | |
705 | + | |
706 | + //標準ミッションとaddon切り替え | |
707 | + if( GameInfoData.selectaddon == false ){ | |
708 | + //addonがあれば | |
709 | + if( GameAddon.GetTotaldatas() > 0 ){ | |
710 | + //文字の色を設定 | |
711 | + if( (MAINMENU_X < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+340))&&((MAINMENU_Y+MAINMENU_H-25) < mainmenu_mouseY)&&(mainmenu_mouseY < (MAINMENU_Y+MAINMENU_H-2)) ){ | |
712 | + color = d3dg->GetColorCode(0.0f,1.0f,1.0f,1.0f); | |
713 | + } | |
714 | + else{ | |
715 | + color = d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f); | |
716 | + } | |
717 | + | |
718 | + //文字を描画 | |
719 | + d3dg->Draw2DTextureFontText(MAINMENU_X+1, MAINMENU_Y+MAINMENU_H-25+1, "ADD-ON MISSIONS >>", d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f), 17, 22); | |
720 | + d3dg->Draw2DTextureFontText(MAINMENU_X, MAINMENU_Y+MAINMENU_H-25, "ADD-ON MISSIONS >>", color, 17, 22); | |
721 | + } | |
722 | + } | |
723 | + else{ | |
724 | + //addonがあれば | |
725 | + //if( GameAddon.GetTotaldatas() > 0 ){ | |
726 | + //文字の色を設定 | |
727 | + if( (MAINMENU_X < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+340))&&((MAINMENU_Y+MAINMENU_H-25) < mainmenu_mouseY)&&(mainmenu_mouseY < (MAINMENU_Y+MAINMENU_H-2)) ){ | |
728 | + color = d3dg->GetColorCode(0.0f,1.0f,1.0f,1.0f); | |
729 | + } | |
730 | + else{ | |
731 | + color = d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f); | |
732 | + } | |
733 | + | |
734 | + //文字を描画 | |
735 | + d3dg->Draw2DTextureFontText(MAINMENU_X+1, MAINMENU_Y+MAINMENU_H-25+1, "<< STANDARD MISSIONS", d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f), 17, 22); | |
736 | + d3dg->Draw2DTextureFontText(MAINMENU_X, MAINMENU_Y+MAINMENU_H-25, "<< STANDARD MISSIONS", color, 17, 22); | |
737 | + //} | |
738 | + } | |
739 | + | |
740 | + //ミッション名を描画 | |
741 | + for(int i=0; i<TOTAL_MENUITEMS; i++){ | |
742 | + char name[32]; | |
743 | + strcpy(name, ""); | |
744 | + | |
745 | + //ミッション名を取得 | |
746 | + if( GameInfoData.selectaddon == false ){ | |
747 | + GameParamInfo.GetOfficialMission(scrollitems + i, name, NULL, NULL, NULL); | |
748 | + } | |
749 | + else{ | |
750 | + strcpy(name, GameAddon.GetMissionName(scrollitems + i)); | |
751 | + } | |
752 | + | |
753 | + //文字の色を設定 | |
754 | + if( (MAINMENU_X < mainmenu_mouseX)&&(mainmenu_mouseX < (MAINMENU_X+(signed)strlen(name)*20))&&(MAINMENU_Y+30 + i*30 < mainmenu_mouseY)&&(mainmenu_mouseY < MAINMENU_Y+30 + i*30 + 26) ){ | |
755 | + color = d3dg->GetColorCode(1.0f,0.6f,0.6f,1.0f); | |
756 | + } | |
757 | + else{ | |
758 | + color = d3dg->GetColorCode(0.6f,0.6f,1.0f,1.0f); | |
759 | + } | |
760 | + | |
761 | + //文字を描画 | |
762 | + d3dg->Draw2DTextureFontText(MAINMENU_X+1, MAINMENU_Y+30+1 + i*30, name, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f), 20, 26); | |
763 | + d3dg->Draw2DTextureFontText(MAINMENU_X, MAINMENU_Y+30 + i*30, name, color, 20, 26); | |
764 | + } | |
765 | + | |
766 | + //マウスカーソル描画(赤線) | |
767 | + d3dg->Draw2DBox(0, mainmenu_mouseY-1, SCREEN_WIDTH, mainmenu_mouseY+1, d3dg->GetColorCode(1.0f,0.0f,0.0f,0.5f)); | |
768 | + d3dg->Draw2DBox(mainmenu_mouseX-1, 0, mainmenu_mouseX+1, SCREEN_HEIGHT, d3dg->GetColorCode(1.0f,0.0f,0.0f,0.5f)); | |
769 | + d3dg->Draw2DLine(0, mainmenu_mouseY, SCREEN_WIDTH, mainmenu_mouseY, d3dg->GetColorCode(1.0f,0.0f,0.0f,1.0f)); | |
770 | + d3dg->Draw2DLine(mainmenu_mouseX, 0, mainmenu_mouseX, SCREEN_HEIGHT, d3dg->GetColorCode(1.0f,0.0f,0.0f,1.0f)); | |
771 | + | |
772 | + //ゲームのロゴマーク描画 | |
773 | + d3dg->Draw2DTexture(20, 25, gametitle, 480, 80, 1.0f); | |
774 | + | |
775 | + //ブラックアウト設定 | |
776 | + if( framecnt < (int)(2.0f*GAMEFPS) ){ | |
777 | + effect = GetEffectAlpha(framecnt, 1.0f, 2.0f, 0.0f, true); | |
778 | + } | |
779 | + else{ | |
780 | + effect = 0.0f; | |
781 | + } | |
782 | + d3dg->Draw2DBox(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, d3dg->GetColorCode(0.0f,0.0f,0.0f,effect)); | |
783 | +} | |
784 | + | |
785 | +void mainmenu::Destroy() | |
786 | +{ | |
787 | + //ブロックデータ解放 | |
788 | + d3dg->CleanupMapdata(); | |
789 | + | |
790 | + //オブジェクトマネージャー解放 | |
791 | + ObjMgr.Cleanup(); | |
792 | + | |
793 | + //背景空解放 | |
794 | + Resource.CleanupSkyModelTexture(); | |
795 | + | |
796 | + d3dg->CleanupTexture(gametitle); | |
797 | + | |
798 | + GameState->NextState(); | |
799 | +} | |
800 | + | |
801 | +//! @brief コンストラクタ | |
802 | +briefing::briefing() | |
803 | +{} | |
804 | + | |
805 | +//! @brief ディストラクタ | |
806 | +briefing::~briefing() | |
807 | +{} | |
808 | + | |
809 | +int briefing::Create() | |
810 | +{ | |
811 | + char path[MAX_PATH]; | |
812 | + char pdata[MAX_PATH]; | |
813 | + char PictureA[MAX_PATH]; | |
814 | + char PictureB[MAX_PATH]; | |
815 | + | |
816 | + //背景画像を取得 | |
817 | + gametitle = d3dg->LoadTexture("data\\title.dds", false, false); | |
818 | + | |
819 | + //mifファイルのファイルパス取得 | |
820 | + if( GameInfoData.selectaddon == false ){ | |
821 | + GameParamInfo.GetOfficialMission(GameInfoData.selectmission_id, NULL, NULL, path, pdata); | |
822 | + strcat(path, pdata); | |
823 | + strcat(path, ".txt"); | |
824 | + } | |
825 | + else{ | |
826 | + strcpy(path, "addon\\"); | |
827 | + strcat(path, GameAddon.GetFileName(GameInfoData.selectmission_id)); | |
828 | + } | |
829 | + | |
830 | + //mifファイルを読み込み | |
831 | + if( MIFdata.LoadFiledata(path) != 0 ){ | |
832 | + //briefing data open failed | |
833 | + return 1; | |
834 | + } | |
835 | + | |
836 | + //ブリーフィング画像のファイルパス取得 | |
837 | + MIFdata.GetPicturefilePath(PictureA, PictureB); | |
838 | + | |
839 | + //ブリーフィング画像読み込み | |
840 | + if( strcmp(PictureB, "!") == 0 ){ | |
841 | + TwoTexture = false; | |
842 | + TextureA = d3dg->LoadTexture(PictureA, true, false); | |
843 | + TextureB = -1; | |
844 | + } | |
845 | + else{ | |
846 | + TwoTexture = true; | |
847 | + TextureA = d3dg->LoadTexture(PictureA, true, false); | |
848 | + TextureB = d3dg->LoadTexture(PictureB, true, false); | |
849 | + } | |
850 | + | |
851 | + //マウスカーソルを中央へ移動 | |
852 | + inputCtrl->MoveMouseCenter(); | |
853 | + framecnt = 0; | |
854 | + | |
855 | + GameState->NextState(); | |
856 | + return 0; | |
857 | +} | |
858 | + | |
859 | +void briefing::Render2D() | |
860 | +{ | |
861 | + float effectA = GetEffectAlphaLoop(framecnt, 0.8f, 0.7f, true); | |
862 | + float effectB = GetEffectAlphaLoop(framecnt, 0.8f, 1.0f, true); | |
863 | + int effectB_sizeW = (int)( (float)(framecnt%((int)(GAMEFPS*1.0f))) * 0.2f + 18 ); | |
864 | + int effectB_sizeH = (int)( (float)(framecnt%((int)(GAMEFPS*1.0f))) * 1.0f + 26 ); | |
865 | + | |
866 | + //メモ:背景画像の描画は、自動的に行われる。 | |
867 | + | |
868 | + //固定文字描画 | |
869 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 60*4, 30, "BRIEFING", d3dg->GetColorCode(1.0f,1.0f,0.0f,effectA), 60, 42); | |
870 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH - 210 - effectB_sizeW*20/2, SCREEN_HEIGHT - 37 - effectB_sizeH/2, | |
871 | + "LEFT CLICK TO BEGIN", d3dg->GetColorCode(1.0f,1.0f,1.0f,effectB), effectB_sizeW, effectB_sizeH); | |
872 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH - 210 - 18*20/2, SCREEN_HEIGHT - 37 - 26/2, "LEFT CLICK TO BEGIN", d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 18, 26); | |
873 | + | |
874 | + //ブリーフィング画像描画 | |
875 | + if( TwoTexture == false ){ | |
876 | + d3dg->Draw2DBox(40, 180, 40+160, 180+150, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f)); | |
877 | + d3dg->Draw2DTexture(40, 180, TextureA, 160, 150, 1.0f); | |
878 | + } | |
879 | + else{ | |
880 | + d3dg->Draw2DBox(40, 130, 40+160, 130+150, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f)); | |
881 | + d3dg->Draw2DTexture(40, 130, TextureA, 160, 150, 1.0f); | |
882 | + | |
883 | + d3dg->Draw2DBox(40, 300, 40+160, 300+150, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f)); | |
884 | + d3dg->Draw2DTexture(40, 300, TextureB, 160, 150, 1.0f); | |
885 | + } | |
886 | + | |
887 | + //ミッション名を取得・描画 | |
888 | + char mname[64]; | |
889 | + if( MIFdata.GetFiletype() == false ){ | |
890 | + GameParamInfo.GetOfficialMission(GameInfoData.selectmission_id, NULL, mname, NULL, NULL); | |
891 | + } | |
892 | + else{ | |
893 | + strcpy(mname, MIFdata.GetMissionFullname()); | |
894 | + } | |
895 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - strlen(mname)*18/2, 90, mname, d3dg->GetColorCode(1.0f,0.5f,0.0f,1.0f), 18, 25); | |
896 | + | |
897 | + //ミッション説明を描画 | |
898 | + d3dg->Draw2DMSFontText(230, 180, MIFdata.GetBriefingText(), d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f)); | |
899 | +} | |
900 | + | |
901 | +void briefing::Destroy(){ | |
902 | + //ブリーフィング画像を開放 | |
903 | + d3dg->CleanupTexture(TextureA); | |
904 | + d3dg->CleanupTexture(TextureB); | |
905 | + | |
906 | + //背景画像を開放 | |
907 | + d3dg->CleanupTexture(gametitle); | |
908 | + | |
909 | + GameState->NextState(); | |
910 | +} | |
911 | + | |
912 | +//! @brief コンストラクタ | |
913 | +maingame::maingame() | |
914 | +{ | |
915 | + ShowInfo_Debugmode = false; | |
916 | + Camera_F2mode = 0; | |
917 | + Camera_HOMEmode = false; | |
918 | + time_input = 0; | |
919 | + time_process_object = 0; | |
920 | + time_process_ai = 0; | |
921 | + time_process_event = 0; | |
922 | + time_sound = 0; | |
923 | + time_render = 0; | |
924 | +} | |
925 | + | |
926 | +//! @brief ディストラクタ | |
927 | +maingame::~maingame() | |
928 | +{} | |
929 | + | |
930 | +int maingame::Create() | |
931 | +{ | |
932 | + MainGameInfo = GameInfoData; | |
933 | + char path[MAX_PATH]; | |
934 | + char bdata[MAX_PATH]; | |
935 | + char pdata[MAX_PATH]; | |
936 | + char pdata2[MAX_PATH]; | |
937 | + | |
938 | + //.bd1と.pd1のファイルパスを求める | |
939 | + if( MIFdata.GetFiletype() == false ){ | |
940 | + GameParamInfo.GetOfficialMission(MainGameInfo.selectmission_id, NULL, NULL, path, pdata2); | |
941 | + | |
942 | + strcpy(bdata, path); | |
943 | + strcat(bdata, "temp.bd1"); | |
944 | + strcpy(pdata, path); | |
945 | + strcat(pdata, pdata2); | |
946 | + strcat(pdata, ".pd1"); | |
947 | + } | |
948 | + else{ | |
949 | + MIFdata.GetDatafilePath(bdata, pdata); | |
950 | + | |
951 | + strcpy(path, bdata); | |
952 | + for(int i=strlen(path)-1; i>0; i--){ | |
953 | + if( path[i] == '\\' ){ | |
954 | + path[i+1] = 0x00; | |
955 | + break; | |
956 | + } | |
957 | + } | |
958 | + } | |
959 | + | |
960 | + //追加小物を読み込む | |
961 | + Resource.LoadAddSmallObject(MIFdata.GetAddSmallobjectModelPath(), MIFdata.GetAddSmallobjectTexturePath(), MIFdata.GetAddSmallobjectSoundPath()); | |
962 | + | |
963 | + //ブロックデータ読み込み | |
964 | + if( BlockData.LoadFiledata(bdata) ){ | |
965 | + //block data open failed | |
966 | + return 1; | |
967 | + } | |
968 | + BlockData.CalculationBlockdata(MIFdata.GetScreenFlag()); | |
969 | + d3dg->LoadMapdata(&BlockData, path); | |
970 | + CollD.InitCollision(&BlockData); | |
971 | + | |
972 | + //ポイントデータ読み込み | |
973 | + if( PointData.LoadFiledata(pdata) ){ | |
974 | + //point data open failed | |
975 | + return 1; | |
976 | + } | |
977 | + ObjMgr.LoadPointData(); | |
978 | + | |
979 | + //AI設定 | |
980 | + for(int i=0; i<MAX_HUMAN; i++){ | |
981 | + HumanAI[i].SetClass(&ObjMgr, i, &BlockData, &PointData, &GameParamInfo, &CollD, GameSound); | |
982 | + HumanAI[i].Init(); | |
983 | + } | |
984 | + | |
985 | + | |
986 | + //背景空読み込み | |
987 | + Resource.LoadSkyModelTexture(MIFdata.GetSkynumber()); | |
988 | + | |
989 | + //サウンド初期化 | |
990 | + GameSound->InitWorldSound(); | |
991 | + | |
992 | + //イベント初期化 | |
993 | + for(int i=0; i<TOTAL_EVENTLINE; i++){ | |
994 | + Event[i].SetClass(&PointData, &ObjMgr); | |
995 | + } | |
996 | + Event[0].Reset(TOTAL_EVENTENTRYPOINT_0); | |
997 | + Event[1].Reset(TOTAL_EVENTENTRYPOINT_1); | |
998 | + Event[2].Reset(TOTAL_EVENTENTRYPOINT_2); | |
999 | + | |
1000 | + //プレイヤーの向きを取得 | |
1001 | + ObjMgr.GetPlayerHumanObject()->GetRxRy(&mouse_rx, &mouse_ry); | |
1002 | + | |
1003 | + view_rx = 0.0f; | |
1004 | + view_ry = 0.0f; | |
1005 | + Camera_Debugmode = false; | |
1006 | + tag = false; | |
1007 | + radar = false; | |
1008 | + wireframe = false; | |
1009 | + CenterLine = false; | |
1010 | + Camera_F1mode = false; | |
1011 | + InvincibleID = -1; | |
1012 | + PlayerAI = false; | |
1013 | + AIstop = false; | |
1014 | + AINoFight = false; | |
1015 | + framecnt = 0; | |
1016 | + start_framecnt = 0; | |
1017 | + end_framecnt = 0; | |
1018 | + message_id = -1; | |
1019 | + message_cnt = 0; | |
1020 | + redflash_flag = false; | |
1021 | + MainGameInfo.missioncomplete = false; | |
1022 | + MainGameInfo.fire = 0; | |
1023 | + MainGameInfo.ontarget = 0; | |
1024 | + MainGameInfo.kill = 0; | |
1025 | + MainGameInfo.headshot = 0; | |
1026 | + | |
1027 | +#ifdef ENABLE_DEBUGCONSOLE | |
1028 | + Show_Console = false; | |
1029 | + | |
1030 | + //コンソール用初期化 | |
1031 | + InfoConsoleData = new ConsoleData [MAX_CONSOLELINES]; | |
1032 | + InputConsoleData = new ConsoleData; | |
1033 | + for(int i=0; i<MAX_CONSOLELINES; i++){ | |
1034 | + InfoConsoleData[i].color = d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f); | |
1035 | + InfoConsoleData[i].textdata[0] = NULL; | |
1036 | + } | |
1037 | + InputConsoleData->color = d3dg->GetColorCode(1.0f,1.0f,0.0f,1.0f); | |
1038 | + InputConsoleData->textdata[0] = NULL; | |
1039 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Game Debug Console."); | |
1040 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), " Command list >help"); | |
1041 | +#endif | |
1042 | + | |
1043 | + GameState->NextState(); | |
1044 | + return 0; | |
1045 | +} | |
1046 | + | |
1047 | +//! @brief 特定操作の入力をチェック | |
1048 | +bool maingame::CheckInputControl(int CheckKey, int mode) | |
1049 | +{ | |
1050 | + int KeyCode = OriginalkeycodeToDinputdef(GameConfig.GetKeycode(CheckKey)); | |
1051 | + if( KeyCode == -1 ){ | |
1052 | + if( mode == 0 ){ | |
1053 | + return inputCtrl->CheckMouseButtonNowL(); | |
1054 | + } | |
1055 | + if( mode == 1 ){ | |
1056 | + return inputCtrl->CheckMouseButtonDownL(); | |
1057 | + } | |
1058 | + //if( mode == 2 ){ | |
1059 | + return inputCtrl->CheckMouseButtonUpL(); | |
1060 | + //} | |
1061 | + } | |
1062 | + if( KeyCode == -2 ){ | |
1063 | + if( mode == 0 ){ | |
1064 | + return inputCtrl->CheckMouseButtonNowR(); | |
1065 | + } | |
1066 | + if( mode == 1 ){ | |
1067 | + return inputCtrl->CheckMouseButtonDownR(); | |
1068 | + } | |
1069 | + //if( mode == 2 ){ | |
1070 | + return inputCtrl->CheckMouseButtonUpR(); | |
1071 | + //} | |
1072 | + } | |
1073 | + if( KeyCode == -3 ){ | |
1074 | + int CodeL, CodeR; | |
1075 | + GetDoubleKeyCode(0, &CodeL, &CodeR); | |
1076 | + if( mode == 0 ){ | |
1077 | + if( inputCtrl->CheckKeyNow(CodeL) ){ | |
1078 | + return true; | |
1079 | + } | |
1080 | + return inputCtrl->CheckKeyNow(CodeR); | |
1081 | + } | |
1082 | + if( mode == 1 ){ | |
1083 | + if( inputCtrl->CheckKeyDown(CodeL) ){ | |
1084 | + return true; | |
1085 | + } | |
1086 | + return inputCtrl->CheckKeyDown(CodeR); | |
1087 | + } | |
1088 | + //if( mode == 2 ){ | |
1089 | + if( inputCtrl->CheckKeyUp(CodeL) ){ | |
1090 | + return true; | |
1091 | + } | |
1092 | + return inputCtrl->CheckKeyUp(CodeR); | |
1093 | + //} | |
1094 | + } | |
1095 | + if( KeyCode == -4 ){ | |
1096 | + int CodeL, CodeR; | |
1097 | + GetDoubleKeyCode(1, &CodeL, &CodeR); | |
1098 | + if( mode == 0 ){ | |
1099 | + if( inputCtrl->CheckKeyNow(CodeL) ){ | |
1100 | + return true; | |
1101 | + } | |
1102 | + return inputCtrl->CheckKeyNow(CodeR); | |
1103 | + } | |
1104 | + if( mode == 1 ){ | |
1105 | + if( inputCtrl->CheckKeyDown(CodeL) ){ | |
1106 | + return true; | |
1107 | + } | |
1108 | + return inputCtrl->CheckKeyDown(CodeR); | |
1109 | + } | |
1110 | + //if( mode == 2 ){ | |
1111 | + if( inputCtrl->CheckKeyUp(CodeL) ){ | |
1112 | + return true; | |
1113 | + } | |
1114 | + return inputCtrl->CheckKeyUp(CodeR); | |
1115 | + //} | |
1116 | + } | |
1117 | + | |
1118 | + if( mode == 0 ){ | |
1119 | + return inputCtrl->CheckKeyNow( OriginalkeycodeToDinputdef(GameConfig.GetKeycode(CheckKey)) ); | |
1120 | + } | |
1121 | + if( mode == 1 ){ | |
1122 | + return inputCtrl->CheckKeyDown( OriginalkeycodeToDinputdef(GameConfig.GetKeycode(CheckKey)) ); | |
1123 | + } | |
1124 | + //if( mode == 2 ){ | |
1125 | + return inputCtrl->CheckKeyUp( OriginalkeycodeToDinputdef(GameConfig.GetKeycode(CheckKey)) ); | |
1126 | + //} | |
1127 | +} | |
1128 | + | |
1129 | +void maingame::Input() | |
1130 | +{ | |
1131 | + time = GetTimeMS(); | |
1132 | + static unsigned int bullettime = 0; | |
1133 | + | |
1134 | + //プレイヤーのクラスを取得 | |
1135 | + human *myHuman = ObjMgr.GetPlayerHumanObject(); | |
1136 | + int PlayerID = ObjMgr.GetPlayerID(); | |
1137 | + | |
1138 | + //キー入力を取得 | |
1139 | + inputCtrl->GetInputState(true); | |
1140 | + inputCtrl->MoveMouseCenter(); | |
1141 | + | |
1142 | + //マウスの移動量取得 | |
1143 | + int x, y; | |
1144 | + float MouseSensitivity; | |
1145 | + inputCtrl->GetMouseMovement(&x, &y); | |
1146 | + | |
1147 | + //視点の移動量計算 | |
1148 | + float mang = 0.0f; | |
1149 | + if( myHuman->GetScopeMode() == 0 ){ mang = 0.01f; } | |
1150 | + if( myHuman->GetScopeMode() == 1 ){ mang = 0.0032f; } | |
1151 | + if( myHuman->GetScopeMode() == 2 ){ mang = 0.0060f; } | |
1152 | + MouseSensitivity = (float)M_PI/180 * mang * GameConfig.GetMouseSensitivity(); | |
1153 | + | |
1154 | + //マウス反転(オプション設定)が有効ならば、反転する。 | |
1155 | + if( GameConfig.GetInvertMouseFlag() == true ){ | |
1156 | + y *= -1; | |
1157 | + } | |
1158 | + | |
1159 | + if( Camera_Debugmode == false ){ //通常モードならば | |
1160 | + if( myHuman->GetHP() > 0 ){ | |
1161 | + //マウスによる向きを計算 | |
1162 | + mouse_rx += x * MouseSensitivity; | |
1163 | + mouse_ry -= y * MouseSensitivity; | |
1164 | + | |
1165 | + //キー操作による向きを計算 | |
1166 | + if( inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x00)) ){ mouse_ry += (float)M_PI/180 * 3; } // [↑] | |
1167 | + if( inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x01)) ){ mouse_ry -= (float)M_PI/180 * 3; } // [↓] | |
1168 | + if( inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x02)) ){ mouse_rx -= (float)M_PI/180 * 3; } // [←] | |
1169 | + if( inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x03)) ){ mouse_rx += (float)M_PI/180 * 3; } // [→] | |
1170 | + | |
1171 | + if( mouse_ry > (float)M_PI/18*7 ) mouse_ry = (float)M_PI/18*7; | |
1172 | + if( mouse_ry < (float)M_PI/18*7 *-1 ) mouse_ry = (float)M_PI/18*7 *-1; | |
1173 | + } | |
1174 | + } | |
1175 | + else{ //デバックモードならば | |
1176 | + //キー操作によりカメラ座標を計算 | |
1177 | + if( inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x00)) ){ camera_x += 2.0f; } // [↑] | |
1178 | + if( inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x01)) ){ camera_x -= 2.0f; } // [↓] | |
1179 | + if( inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x02)) ){ camera_z += 2.0f; } // [←] | |
1180 | + if( inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x03)) ){ camera_z -= 2.0f; } // [→] | |
1181 | + if( inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x48)) ){ camera_y += 2.0f; } //[NUM +] | |
1182 | + if( inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x49)) ){ camera_y -= 2.0f; } //[NUM -] | |
1183 | + | |
1184 | + //マウス移動をカメラの向きとして適用 | |
1185 | + //camera_rx -= x*0.0025f; | |
1186 | + //camera_ry -= y*0.0025f; | |
1187 | + camera_rx -= x * MouseSensitivity; | |
1188 | + camera_ry -= y * MouseSensitivity; | |
1189 | + if( camera_ry > (float)M_PI/18*7 ) camera_ry = (float)M_PI/18*7; | |
1190 | + if( camera_ry < (float)M_PI/18*7 *-1 ) camera_ry = (float)M_PI/18*7 *-1; | |
1191 | + } | |
1192 | + | |
1193 | + //ゲーム終了操作かチェック | |
1194 | + if( inputCtrl->CheckKeyDown(GetEscKeycode()) ){ | |
1195 | + GameState->PushBackSpaceKey(); | |
1196 | + } | |
1197 | + | |
1198 | + //カメラ表示モード変更操作かチェック | |
1199 | + if( inputCtrl->CheckKeyDown( GetFunctionKeycode(1) ) ){ | |
1200 | + if( Camera_F1mode == false ){ | |
1201 | + Camera_F1mode = true; | |
1202 | + view_rx = 0.0f; | |
1203 | + view_ry = (float)M_PI/8 * -1; | |
1204 | + } | |
1205 | + else{ | |
1206 | + Camera_F1mode = false; | |
1207 | + view_rx = 0.0f; | |
1208 | + view_ry = 0.0f; | |
1209 | + } | |
1210 | + } | |
1211 | + | |
1212 | + //画面のUI変更操作かチェック | |
1213 | + if( inputCtrl->CheckKeyDown( GetFunctionKeycode(2) ) ){ | |
1214 | + if( Camera_F2mode == 2 ){ | |
1215 | + Camera_F2mode = 0; | |
1216 | + } | |
1217 | + else{ | |
1218 | + Camera_F2mode += 1; | |
1219 | + } | |
1220 | + } | |
1221 | + | |
1222 | + //リセット操作かチェック | |
1223 | + if( inputCtrl->CheckKeyDown( GetFunctionKeycode(12) ) ){ | |
1224 | + GameState->PushF12Key(); | |
1225 | + } | |
1226 | + | |
1227 | +#ifdef ENABLE_DEBUGCONSOLE | |
1228 | + //デバック用コンソールの表示操作かチェック | |
1229 | + if( inputCtrl->CheckKeyDown( GetFunctionKeycode(11) ) ){ | |
1230 | + if( Show_Console == false ){ | |
1231 | + Show_Console = true; | |
1232 | + | |
1233 | + strcpy(InputConsoleData->textdata, CONSOLE_PROMPT); | |
1234 | + } | |
1235 | + else{ | |
1236 | + Show_Console = false; | |
1237 | + } | |
1238 | + } | |
1239 | + | |
1240 | + if( Show_Console == false ){ | |
1241 | +#endif | |
1242 | + | |
1243 | + if( PlayerAI == false ){ | |
1244 | + | |
1245 | + //前後左右の移動(走り)操作かチェック | |
1246 | + if( CheckInputControl(KEY_MOVEFORWARD, 0) ){ | |
1247 | + ObjMgr.MoveForward(PlayerID); | |
1248 | + } | |
1249 | + if( CheckInputControl(KEY_MOVEBACKWARD, 0) ){ | |
1250 | + ObjMgr.MoveBack(PlayerID); | |
1251 | + } | |
1252 | + if( CheckInputControl(KEY_MOVELEFT, 0) ){ | |
1253 | + ObjMgr.MoveLeft(PlayerID); | |
1254 | + } | |
1255 | + if( CheckInputControl(KEY_MOVERIGHT, 0) ){ | |
1256 | + ObjMgr.MoveRight(PlayerID); | |
1257 | + } | |
1258 | + | |
1259 | + //歩き操作かチェック | |
1260 | + if( CheckInputControl(KEY_WALK, 0) ){ | |
1261 | + ObjMgr.MoveWalk(PlayerID); | |
1262 | + } | |
1263 | + | |
1264 | + //ジャンプ操作かチェック | |
1265 | + if( CheckInputControl(KEY_JUMP, 1) ){ | |
1266 | + ObjMgr.MoveJump(PlayerID); | |
1267 | + } | |
1268 | + | |
1269 | + if( Camera_Debugmode == true ){ //デバックモードならば | |
1270 | + //発砲操作かチェック | |
1271 | + if( CheckInputControl(KEY_Shot, 0) ){ | |
1272 | + //前回の発射より、4フレーム分よりも時間が経っていれば | |
1273 | + if( bullettime + 4*((int)GAMEFPS) < GetTimeMS() ){ | |
1274 | + float x, y, z, rx, ry; | |
1275 | + x = camera_x; | |
1276 | + y = camera_y; | |
1277 | + z = camera_z; | |
1278 | + rx = camera_rx; | |
1279 | + ry = camera_ry; | |
1280 | + | |
1281 | + //未使用の弾オブジェクトを取得 | |
1282 | + bullet* newbullet = ObjMgr.GetNewBulletObject(); | |
1283 | + if( newbullet != NULL ){ | |
1284 | + //弾オブジェクトを設定 | |
1285 | + newbullet->SetPosData(x, y, z, rx, ry); | |
1286 | + newbullet->SetParamData(40, 5, 10, 1024, ObjMgr.GetPlayerID(), true); | |
1287 | + newbullet->SetDrawFlag(true); | |
1288 | + GameSound->ShotWeapon(x, y, z, 0, 1024, true); | |
1289 | + | |
1290 | + //スコアに加算 | |
1291 | + MainGameInfo.fire += 1; | |
1292 | + | |
1293 | + //発射時間を記憶(連射間隔判定用) | |
1294 | + bullettime = GetTimeMS(); | |
1295 | + } | |
1296 | + } | |
1297 | + } | |
1298 | + } | |
1299 | + else{ //デバックモードでなければ | |
1300 | + HumanParameter humandata; | |
1301 | + int id_param; | |
1302 | + bool zombie; | |
1303 | + int keymode; | |
1304 | + | |
1305 | + //ゾンビかどうか判定 | |
1306 | + myHuman->GetParamData(&id_param, NULL, NULL, NULL); | |
1307 | + GameParamInfo.GetHuman(id_param, &humandata); | |
1308 | + if( humandata.type == 2 ){ | |
1309 | + zombie = true; | |
1310 | + } | |
1311 | + else{ | |
1312 | + zombie = false; | |
1313 | + } | |
1314 | + | |
1315 | + //連射モードを取得 | |
1316 | + if( zombie == true ){ | |
1317 | + keymode = 1; | |
1318 | + } | |
1319 | + else if( myHuman->GetWeaponBlazingmode() == false ){ | |
1320 | + keymode = 1; | |
1321 | + } | |
1322 | + else{ | |
1323 | + keymode = 0; | |
1324 | + } | |
1325 | + | |
1326 | + //発砲操作かチェック | |
1327 | + if( CheckInputControl(KEY_Shot, keymode) ){ | |
1328 | + | |
1329 | + if( zombie == false ){ | |
1330 | + //弾の発射に成功すれば | |
1331 | + if( ObjMgr.ShotWeapon(PlayerID) == 1 ){ | |
1332 | + //スコアに加算 | |
1333 | + MainGameInfo.fire += 1; | |
1334 | + | |
1335 | + //プレイヤーの向きを取得 | |
1336 | + ObjMgr.GetPlayerHumanObject()->GetRxRy(&mouse_rx, &mouse_ry); | |
1337 | + } | |
1338 | + } | |
1339 | + else{ | |
1340 | + for(int i=0; i<MAX_HUMAN; i++){ | |
1341 | + human *EnemyHuman = ObjMgr.GeHumanObject(i); | |
1342 | + if( ObjMgr.CheckZombieAttack(myHuman, EnemyHuman) == true ){ | |
1343 | + ObjMgr.HitZombieAttack(EnemyHuman); | |
1344 | + } | |
1345 | + } | |
1346 | + } | |
1347 | + | |
1348 | + } | |
1349 | + } | |
1350 | + | |
1351 | + //リロード操作かチェック | |
1352 | + if( CheckInputControl(KEY_RELOAD, 1) ){ | |
1353 | + ObjMgr.ReloadWeapon(PlayerID); | |
1354 | + } | |
1355 | + | |
1356 | + //武器の切り替え操作かチェック | |
1357 | + if( CheckInputControl(KEY_SWITCHWEAPON, 1) ){ | |
1358 | + ObjMgr.ChangeWeapon(PlayerID, -1); | |
1359 | + } | |
1360 | + if( CheckInputControl(KEY_WEAPON1, 1) ){ | |
1361 | + ObjMgr.ChangeWeapon(PlayerID, 0); | |
1362 | + } | |
1363 | + if( CheckInputControl(KEY_WEAPON2, 1) ){ | |
1364 | + ObjMgr.ChangeWeapon(PlayerID, 1); | |
1365 | + } | |
1366 | + | |
1367 | + //武器の廃棄操作かチェック | |
1368 | + if( CheckInputControl(KEY_DROPWEAPON, 1) ){ | |
1369 | + ObjMgr.DumpWeapon(PlayerID); | |
1370 | + } | |
1371 | + | |
1372 | + //スコープ操作かチェック | |
1373 | + if( CheckInputControl(KEY_ZOOM, 1) ){ | |
1374 | + ObjMgr.ChangeScopeMode(PlayerID); | |
1375 | + } | |
1376 | + | |
1377 | + //連射モード変更操作かチェック | |
1378 | + if( CheckInputControl(KEY_ShotMODE, 1) ){ | |
1379 | + ObjMgr.ChangeShotMode(PlayerID); | |
1380 | + } | |
1381 | + | |
1382 | + //カメラ操作 | |
1383 | + if( Camera_F1mode == true ){ | |
1384 | + if( inputCtrl->CheckKeyNow( OriginalkeycodeToDinputdef(0x0C) ) ){ //NUM8 | |
1385 | + view_ry -= (float)M_PI/180 * 2; | |
1386 | + } | |
1387 | + if( inputCtrl->CheckKeyNow( OriginalkeycodeToDinputdef(0x09) ) ){ //NUM5 | |
1388 | + view_ry += (float)M_PI/180 * 2; | |
1389 | + } | |
1390 | + if( inputCtrl->CheckKeyNow( OriginalkeycodeToDinputdef(0x08) ) ){ //NUM4 | |
1391 | + view_rx -= (float)M_PI/180 * 2; | |
1392 | + } | |
1393 | + if( inputCtrl->CheckKeyNow( OriginalkeycodeToDinputdef(0x0A) ) ){ //NUM6 | |
1394 | + view_rx += (float)M_PI/180 * 2; | |
1395 | + } | |
1396 | + } | |
1397 | + | |
1398 | + //裏技・上昇の操作かチェック | |
1399 | + if( (inputCtrl->CheckKeyNow( GetFunctionKeycode(5) ))&&(inputCtrl->CheckKeyNow(OriginalkeycodeToDinputdef(0x0F))) ){ // F5 + [ENTER] | |
1400 | + Cmd_F5 = true; | |
1401 | + } | |
1402 | + else{ | |
1403 | + Cmd_F5 = false; | |
1404 | + } | |
1405 | + | |
1406 | + //裏技・弾追加の操作かチェック | |
1407 | + if( inputCtrl->CheckKeyNow( GetFunctionKeycode(6) ) ){ | |
1408 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x0F)) ){ // [ENTER] | |
1409 | + ObjMgr.CheatAddBullet(PlayerID); | |
1410 | + } | |
1411 | + } | |
1412 | + | |
1413 | + //裏技・武器変更の操作かチェック | |
1414 | + if( inputCtrl->CheckKeyNow( GetFunctionKeycode(7) ) ){ | |
1415 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x02)) ){ // [←] | |
1416 | + int id_param = myHuman->GetMainWeaponTypeNO(); | |
1417 | + | |
1418 | + //次の武器番号を計算 | |
1419 | + if( id_param >= TOTAL_PARAMETERINFO_WEAPON-1 ){ id_param = 0; } | |
1420 | + else{ id_param += 1; } | |
1421 | + | |
1422 | + ObjMgr.CheatNewWeapon(PlayerID, id_param); | |
1423 | + } | |
1424 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x03)) ){ // [→] | |
1425 | + int id_param = myHuman->GetMainWeaponTypeNO(); | |
1426 | + | |
1427 | + //次の武器番号を計算 | |
1428 | + if( id_param <= 0 ){ id_param = TOTAL_PARAMETERINFO_WEAPON-1; } | |
1429 | + else{ id_param -= 1; } | |
1430 | + | |
1431 | + ObjMgr.CheatNewWeapon(PlayerID, id_param); | |
1432 | + } | |
1433 | + } | |
1434 | + | |
1435 | + //裏技・人変更の操作かチェック | |
1436 | + if( inputCtrl->CheckKeyNow( GetFunctionKeycode(8) ) ){ | |
1437 | + int Player_HumanID; | |
1438 | + | |
1439 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x02)) ){ // [←] | |
1440 | + //現在のプレイヤー番号を取得 | |
1441 | + Player_HumanID = ObjMgr.GetPlayerID(); | |
1442 | + | |
1443 | + //次の人を計算 | |
1444 | + Player_HumanID += 1; | |
1445 | + if( Player_HumanID >= MAX_HUMAN ){ Player_HumanID = 0; } | |
1446 | + | |
1447 | + //対象プレイヤー番号を適用 | |
1448 | + ObjMgr.SetPlayerID(Player_HumanID); | |
1449 | + | |
1450 | + //プレイヤーの向きを取得 | |
1451 | + ObjMgr.GetPlayerHumanObject()->GetRxRy(&mouse_rx, &mouse_ry); | |
1452 | + } | |
1453 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x03)) ){ // [→] | |
1454 | + //現在のプレイヤー番号を取得 | |
1455 | + Player_HumanID = ObjMgr.GetPlayerID(); | |
1456 | + | |
1457 | + //次の人を計算 | |
1458 | + Player_HumanID -= 1; | |
1459 | + if( Player_HumanID < 0 ){ Player_HumanID = MAX_HUMAN-1; } | |
1460 | + | |
1461 | + //対象プレイヤー番号を適用 | |
1462 | + ObjMgr.SetPlayerID(Player_HumanID); | |
1463 | + | |
1464 | + //プレイヤーの向きを取得 | |
1465 | + ObjMgr.GetPlayerHumanObject()->GetRxRy(&mouse_rx, &mouse_ry); | |
1466 | + } | |
1467 | + } | |
1468 | + | |
1469 | + //裏技・人追加の操作かチェック | |
1470 | + if( inputCtrl->CheckKeyNow( GetFunctionKeycode(9) ) ){ | |
1471 | + if( (inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x00)))||(inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x01))) ){ // [↑]・[↓] | |
1472 | + float x, y, z, r; | |
1473 | + int param, dataid, team; | |
1474 | + int selectweapon; | |
1475 | + weapon *weapon[TOTAL_HAVEWEAPON]; | |
1476 | + int weapon_paramid[TOTAL_HAVEWEAPON]; | |
1477 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
1478 | + weapon[i] = NULL; | |
1479 | + weapon_paramid[i] = 0; | |
1480 | + } | |
1481 | + int id; | |
1482 | + | |
1483 | + //プレイヤーの座標や武器を取得 | |
1484 | + myHuman->GetPosData(&x, &y, &z, &r); | |
1485 | + myHuman->GetParamData(¶m, &dataid, NULL, &team); | |
1486 | + myHuman->GetWeapon(&selectweapon, weapon); | |
1487 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
1488 | + if( weapon[i] != NULL ){ | |
1489 | + weapon[i]->GetParamData(&weapon_paramid[i], NULL, NULL); | |
1490 | + } | |
1491 | + } | |
1492 | + | |
1493 | + //プレイヤーの目の前の座標を取得 | |
1494 | + x += cos(r*-1 + (float)M_PI/2)*10.0f; | |
1495 | + y += 5.0f; | |
1496 | + z += sin(r*-1 + (float)M_PI/2)*10.0f; | |
1497 | + | |
1498 | + //人を追加 | |
1499 | + id = ObjMgr.AddHumanIndex(x, y, z, r, param, team, weapon_paramid); | |
1500 | + if( id >= 0 ){ | |
1501 | + ObjMgr.ChangeWeapon(id, selectweapon); | |
1502 | + | |
1503 | + //AIを設定 | |
1504 | + HumanAI[id].Init(); | |
1505 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x00)) ){ // [↑] | |
1506 | + HumanAI[id].SetHoldTracking(dataid); | |
1507 | + } | |
1508 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x01)) ){ // [↓] | |
1509 | + HumanAI[id].SetHoldWait(x, z, r); | |
1510 | + } | |
1511 | + } | |
1512 | + } | |
1513 | + } | |
1514 | + | |
1515 | + //裏技・腕表示の操作かチェック | |
1516 | + if( inputCtrl->CheckKeyDown( GetHomeKeycode() ) ){ | |
1517 | + if( Camera_HOMEmode == false ){ | |
1518 | + Camera_HOMEmode = true; | |
1519 | + } | |
1520 | + else{ | |
1521 | + Camera_HOMEmode = false; | |
1522 | + } | |
1523 | + } | |
1524 | + } | |
1525 | + | |
1526 | +#ifdef ENABLE_DEBUGCONSOLE | |
1527 | + } | |
1528 | + if( Show_Console == true ){ | |
1529 | + InputConsole(); | |
1530 | + } | |
1531 | +#endif | |
1532 | + | |
1533 | + time_input = GetTimeMS() - time; | |
1534 | +} | |
1535 | + | |
1536 | +void maingame::Process() | |
1537 | +{ | |
1538 | + //プレイヤーのクラスを取得 | |
1539 | + human *myHuman = ObjMgr.GetPlayerHumanObject(); | |
1540 | + | |
1541 | + int ontarget, kill, headshot; | |
1542 | + | |
1543 | + //----------------------------------- | |
1544 | + | |
1545 | + time = GetTimeMS(); | |
1546 | + | |
1547 | + //武器の持ち方を取得 | |
1548 | + int weaponid; | |
1549 | + WeaponParameter data; | |
1550 | + weaponid = myHuman->GetMainWeaponTypeNO(); | |
1551 | + GameParamInfo.GetWeapon(weaponid, &data); | |
1552 | + | |
1553 | + //プレイヤー(オブジェクト)の向きを設定 | |
1554 | + if( (PlayerAI == false)&&(myHuman->GetHP() > 0) ){ | |
1555 | + myHuman->SetRxRy(mouse_rx, mouse_ry); | |
1556 | + } | |
1557 | + | |
1558 | + //オブジェクトマネージャーを実行 | |
1559 | + if( Cmd_F5 == true ){ | |
1560 | + ObjMgr.Process( ObjMgr.GetPlayerID() , camera_rx, camera_ry); | |
1561 | + } | |
1562 | + else{ | |
1563 | + ObjMgr.Process(-1, camera_rx, camera_ry); | |
1564 | + } | |
1565 | + | |
1566 | + //プレイヤーの戦歴を加算 | |
1567 | + ObjMgr.GetHumanShotInfo( ObjMgr.GetPlayerID(), &ontarget, &kill, &headshot); | |
1568 | + MainGameInfo.ontarget += ontarget; | |
1569 | + MainGameInfo.kill += kill; | |
1570 | + MainGameInfo.headshot += headshot; | |
1571 | + | |
1572 | + time_process_object = GetTimeMS() - time; | |
1573 | + | |
1574 | + //----------------------------------- | |
1575 | + | |
1576 | + time = GetTimeMS(); | |
1577 | + if( AIstop == false ){ | |
1578 | + int PlayerID = ObjMgr.GetPlayerID(); | |
1579 | + for(int i=0; i<MAX_HUMAN; i++){ | |
1580 | + if( (PlayerAI == false)&&(i == PlayerID) ){ continue; } | |
1581 | + //AIを実行 | |
1582 | + HumanAI[i].Process(); | |
1583 | + } | |
1584 | + } | |
1585 | + time_process_ai = GetTimeMS() - time; | |
1586 | + | |
1587 | + //----------------------------------- | |
1588 | + | |
1589 | + //ミッションが終了していなければ、 | |
1590 | + if( end_framecnt == 0 ){ | |
1591 | + int check = ObjMgr.CheckGameOverorComplete(); | |
1592 | + | |
1593 | + //ゲームクリアー判定 | |
1594 | + if( check == 1 ){ | |
1595 | + end_framecnt += 1; | |
1596 | + MainGameInfo.missioncomplete = true; | |
1597 | + } | |
1598 | + | |
1599 | + //ゲームオーバー判定 | |
1600 | + if( check == 2 ){ | |
1601 | + end_framecnt += 1; | |
1602 | + MainGameInfo.missioncomplete = false; | |
1603 | + } | |
1604 | + } | |
1605 | + | |
1606 | + //----------------------------------- | |
1607 | + | |
1608 | + time = GetTimeMS(); | |
1609 | + bool SetMessageID; | |
1610 | + if( end_framecnt == 0 ){ | |
1611 | + //イベント実行 | |
1612 | + for(int i=0; i<TOTAL_EVENTLINE; i++){ | |
1613 | + SetMessageID = false; | |
1614 | + Event[i].Execution(&end_framecnt, &MainGameInfo.missioncomplete, &message_id, &SetMessageID); | |
1615 | + | |
1616 | + //イベントメッセージが再セットされていたら、カウントを戻す。 | |
1617 | + if( SetMessageID == true ){ | |
1618 | + message_cnt = 0; | |
1619 | + } | |
1620 | + } | |
1621 | + } | |
1622 | + if( (message_id != -1)&&(message_cnt < (int)(TOTAL_EVENTENT_SHOWMESSEC*GAMEFPS)) ){ | |
1623 | + message_cnt += 1; | |
1624 | + } | |
1625 | + else{ | |
1626 | + message_id = -1; | |
1627 | + message_cnt = 0; | |
1628 | + } | |
1629 | + time_process_event = GetTimeMS() - time; | |
1630 | + | |
1631 | + //----------------------------------- | |
1632 | + | |
1633 | + float x, y, z; | |
1634 | + myHuman->GetPosData(&x, &y, &z, NULL); | |
1635 | + | |
1636 | + if( PlayerAI == true ){ | |
1637 | + //プレイヤーの向きを取得 | |
1638 | + ObjMgr.GetPlayerHumanObject()->GetRxRy(&mouse_rx, &mouse_ry); | |
1639 | + } | |
1640 | + | |
1641 | + //カメラワークを求める | |
1642 | + if( Camera_Debugmode == true ){ | |
1643 | + // | |
1644 | + } | |
1645 | + else if( myHuman->GetHP() <= 0 ){ | |
1646 | + float rx = (float)M_PI/180*end_framecnt; | |
1647 | + float ry = (float)M_PI/180*85*-1; | |
1648 | + float r = 25.0f; | |
1649 | + | |
1650 | + camera_x = x + cos(rx)*cos(ry)*r; | |
1651 | + camera_y = y - sin(ry)*r; | |
1652 | + camera_z = z + sin(rx)*cos(ry)*r; | |
1653 | + camera_rx = rx; | |
1654 | + camera_ry = ry; | |
1655 | + } | |
1656 | + else if( Camera_F1mode == true ){ | |
1657 | + float crx = view_rx + mouse_rx*-1 + (float)M_PI/2; | |
1658 | + float cry = view_ry + mouse_ry; | |
1659 | + float dist; | |
1660 | + if( CollD.CheckALLBlockIntersectRay(x, y + HUMAN_HEIGTH, z, cos(crx)*cos(cry)*-1, sin(cry*-1), sin(crx)*cos(cry)*-1, NULL, NULL, &dist, 13.0f) == true ){ | |
1661 | + dist -= 1.0f; | |
1662 | + } | |
1663 | + else{ | |
1664 | + dist = 13.0f; | |
1665 | + } | |
1666 | + camera_x = x - cos(crx)*cos(cry)*dist; | |
1667 | + camera_y = y + HUMAN_HEIGTH + sin(cry*-1)*dist; | |
1668 | + camera_z = z - sin(crx)*cos(cry)*dist; | |
1669 | + camera_rx = crx; | |
1670 | + camera_ry = cry; | |
1671 | + } | |
1672 | + else{ | |
1673 | + camera_x = x; | |
1674 | + camera_y = y + VIEW_HEIGHT; | |
1675 | + camera_z = z; | |
1676 | + camera_rx = view_rx + mouse_rx*-1 + (float)M_PI/2; | |
1677 | + camera_ry = view_ry + mouse_ry; | |
1678 | + } | |
1679 | + | |
1680 | + //ダメージを受けていれば、レッドフラッシュを描画する | |
1681 | + redflash_flag = myHuman->CheckHit(); | |
1682 | + | |
1683 | + //----------------------------------- | |
1684 | + | |
1685 | +#ifdef ENABLE_DEBUGCONSOLE | |
1686 | + //デバック用コンソールを表示しており、かつミッション終了のカウントが始まっていなければ〜 | |
1687 | + if( (Show_Console == true)&&(end_framecnt == 0) ){ | |
1688 | + //デバック用コンソールのメイン処理 | |
1689 | + ProcessConsole(); | |
1690 | + } | |
1691 | +#endif | |
1692 | + | |
1693 | + //----------------------------------- | |
1694 | + | |
1695 | + framecnt += 1; | |
1696 | + if( start_framecnt < (int)(1.0f*GAMEFPS) ){ //ミッション開始中なら | |
1697 | + start_framecnt += 1; | |
1698 | + } | |
1699 | + if( end_framecnt == 1 ){ //ミッション終了直後ならば | |
1700 | + MainGameInfo.framecnt = framecnt; | |
1701 | + GameInfoData = MainGameInfo; | |
1702 | + end_framecnt += 1; | |
1703 | + } | |
1704 | + else if( end_framecnt > 0 ){ //ミッション終了中ならば | |
1705 | + if( end_framecnt < (int)(5.0f*GAMEFPS) ){ | |
1706 | + end_framecnt += 1; | |
1707 | + } | |
1708 | + else{ | |
1709 | + GameState->PushMouseButton(); | |
1710 | + } | |
1711 | + } | |
1712 | +} | |
1713 | + | |
1714 | +void maingame::Sound() | |
1715 | +{ | |
1716 | + time = GetTimeMS(); | |
1717 | + | |
1718 | + //サウンドを再生 | |
1719 | + GameSound->PlayWorldSound(camera_x, camera_y, camera_z, camera_rx); | |
1720 | + | |
1721 | + time_sound = GetTimeMS() - time; | |
1722 | +} | |
1723 | + | |
1724 | +void maingame::Render3D() | |
1725 | +{ | |
1726 | + time = GetTimeMS(); | |
1727 | + | |
1728 | + | |
1729 | + int skymodel, skytexture; | |
1730 | + human *myHuman = ObjMgr.GetPlayerHumanObject(); | |
1731 | + | |
1732 | + //フォグとカメラを設定 | |
1733 | + d3dg->SetFog(MIFdata.GetSkynumber()); | |
1734 | + if( Camera_F1mode == false ){ | |
1735 | + int scopemode = myHuman->GetScopeMode(); | |
1736 | + float viewangle = 0.0f; | |
1737 | + | |
1738 | + //スコープによる視野角を決定 | |
1739 | + if( scopemode == 0 ){ viewangle = VIEWANGLE_NORMAL; } | |
1740 | + if( scopemode == 1 ){ viewangle = VIEWANGLE_SCOPE_1; } | |
1741 | + if( scopemode == 2 ){ viewangle = VIEWANGLE_SCOPE_2; } | |
1742 | + | |
1743 | + d3dg->SetCamera(camera_x, camera_y, camera_z, camera_rx, camera_ry, viewangle); | |
1744 | + } | |
1745 | + else{ | |
1746 | + d3dg->SetCamera(camera_x, camera_y, camera_z, camera_rx, camera_ry, VIEWANGLE_NORMAL); | |
1747 | + } | |
1748 | + | |
1749 | + //カメラ座標に背景空を描画 | |
1750 | + d3dg->SetWorldTransform(camera_x, camera_y, camera_z, 0.0f, 0.0f, 2.0f); | |
1751 | + Resource.GetSkyModelTexture(&skymodel, &skytexture); | |
1752 | + d3dg->RenderModel(skymodel, skytexture); | |
1753 | + | |
1754 | + //Zバッファを初期化 | |
1755 | + d3dg->ResetZbuffer(); | |
1756 | + | |
1757 | + if( CenterLine == true ){ | |
1758 | + //中心線描画(デバック用) | |
1759 | + d3dg->Centerline(); | |
1760 | + } | |
1761 | + | |
1762 | + //マップを描画 | |
1763 | + d3dg->ResetWorldTransform(); | |
1764 | + d3dg->DrawMapdata(wireframe); | |
1765 | + | |
1766 | + //プレイヤーの描画有無の決定 | |
1767 | + int DrawPlayer = 0; | |
1768 | + if( (Camera_F1mode == false)&&(Camera_Debugmode == false)&&(myHuman->GetHP() > 0) ){ | |
1769 | + if( Camera_HOMEmode == false ){ | |
1770 | + DrawPlayer = 1; | |
1771 | + } | |
1772 | + else{ | |
1773 | + DrawPlayer = 2; | |
1774 | + } | |
1775 | + } | |
1776 | + //オブジェクトを描画 | |
1777 | + ObjMgr.Render(camera_x, camera_y, camera_z, DrawPlayer); | |
1778 | +} | |
1779 | + | |
1780 | +void maingame::Render2D() | |
1781 | +{ | |
1782 | + char str[256]; | |
1783 | + unsigned char stru[256]; | |
1784 | + float fps = GetFps(10); | |
1785 | + float effect; | |
1786 | + | |
1787 | + human *myHuman = ObjMgr.GetPlayerHumanObject(); | |
1788 | + | |
1789 | + int selectweapon; | |
1790 | + weapon *weapon[TOTAL_HAVEWEAPON]; | |
1791 | + int weapon_paramid[TOTAL_HAVEWEAPON]; | |
1792 | + WeaponParameter weapon_paramdata; | |
1793 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
1794 | + weapon[i] = NULL; | |
1795 | + weapon_paramid[i] = 0; | |
1796 | + } | |
1797 | + int lnbs = 0; | |
1798 | + int nbs = 0; | |
1799 | + int reloadcnt = 0; | |
1800 | + int selectweaponcnt = 0; | |
1801 | + int weaponmodel, weapontexture; | |
1802 | + char weaponname[16]; | |
1803 | + int hp; | |
1804 | + int param_scopemode; | |
1805 | + int param_WeaponP; | |
1806 | + int ErrorRange; | |
1807 | + | |
1808 | + //各種設定やゲーム情報を取得 | |
1809 | + myHuman->GetWeapon(&selectweapon, weapon); | |
1810 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
1811 | + if( weapon[i] != NULL ){ | |
1812 | + if( selectweapon == i ){ | |
1813 | + weapon[i]->GetParamData(&weapon_paramid[i], &lnbs, &nbs); | |
1814 | + reloadcnt = weapon[i]->GetReloadCnt(); | |
1815 | + } | |
1816 | + else{ | |
1817 | + weapon[i]->GetParamData(&weapon_paramid[i], NULL, NULL); | |
1818 | + } | |
1819 | + } | |
1820 | + } | |
1821 | + selectweaponcnt = myHuman->GetChangeWeaponCnt(); | |
1822 | + GameParamInfo.GetWeapon(weapon_paramid[selectweapon], &weapon_paramdata); | |
1823 | + strcpy(weaponname, weapon_paramdata.name); | |
1824 | + hp = myHuman->GetHP(); | |
1825 | + param_scopemode = weapon_paramdata.scopemode; | |
1826 | + param_WeaponP = weapon_paramdata.WeaponP; | |
1827 | + ErrorRange = myHuman->GetGunsightErrorRange(); | |
1828 | + | |
1829 | + float human_x, human_y, human_z, human_rx; | |
1830 | + myHuman->GetPosData(&human_x, &human_y, &human_z, &human_rx); | |
1831 | + | |
1832 | + //レッドフラッシュ描画 | |
1833 | + if( redflash_flag == true ){ | |
1834 | + d3dg->Draw2DBox(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, d3dg->GetColorCode(1.0f,0.0f,0.0f,0.5f)); | |
1835 | + redflash_flag = false; | |
1836 | + } | |
1837 | + | |
1838 | + //スコープ表示 | |
1839 | + if( (Camera_F1mode == false)&&(myHuman->GetScopeMode() == 1) ){ | |
1840 | + d3dg->Draw2DTexture(0, 0, Resource.GetScopeTexture(), SCREEN_WIDTH, SCREEN_HEIGHT, 1.0f); | |
1841 | + d3dg->Draw2DLine(SCREEN_WIDTH/2-49, SCREEN_HEIGHT/2, SCREEN_WIDTH/2-4, SCREEN_HEIGHT/2, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
1842 | + d3dg->Draw2DLine(SCREEN_WIDTH/2+4, SCREEN_HEIGHT/2, SCREEN_WIDTH/2+49, SCREEN_HEIGHT/2, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
1843 | + d3dg->Draw2DLine(SCREEN_WIDTH/2, SCREEN_HEIGHT/2-49, SCREEN_WIDTH/2, SCREEN_HEIGHT/2-4, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
1844 | + d3dg->Draw2DLine(SCREEN_WIDTH/2, SCREEN_HEIGHT/2+4, SCREEN_WIDTH/2, SCREEN_HEIGHT/2+49, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
1845 | + d3dg->Draw2DBox(SCREEN_WIDTH/2-50, SCREEN_HEIGHT/2-1, SCREEN_WIDTH/20+50, SCREEN_HEIGHT/2+1, d3dg->GetColorCode(0.0f,0.0f,0.0f,0.5f)); | |
1846 | + d3dg->Draw2DBox(SCREEN_WIDTH/2-1, SCREEN_HEIGHT/2-50, SCREEN_WIDTH/2+1, SCREEN_HEIGHT/2+50, d3dg->GetColorCode(0.0f,0.0f,0.0f,0.5f)); | |
1847 | + } | |
1848 | + if( (Camera_F1mode == false)&&(myHuman->GetScopeMode() == 2) ){ | |
1849 | + d3dg->Draw2DTexture(0, 0, Resource.GetScopeTexture(), SCREEN_WIDTH, SCREEN_HEIGHT, 1.0f); | |
1850 | + d3dg->Draw2DLine(0, SCREEN_HEIGHT/2, SCREEN_WIDTH, SCREEN_HEIGHT/2, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
1851 | + d3dg->Draw2DLine(SCREEN_WIDTH/2, 0, SCREEN_WIDTH/2, SCREEN_HEIGHT, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
1852 | + d3dg->Draw2DBox(0, SCREEN_HEIGHT/2-1, SCREEN_WIDTH, SCREEN_HEIGHT/2+1, d3dg->GetColorCode(0.0f,0.0f,0.0f,0.5f)); | |
1853 | + d3dg->Draw2DBox(SCREEN_WIDTH/2-1, 0, SCREEN_WIDTH/2+1, SCREEN_HEIGHT, d3dg->GetColorCode(0.0f,0.0f,0.0f,0.5f)); | |
1854 | + } | |
1855 | + | |
1856 | + //目隠し表示 | |
1857 | + if( (Camera_Debugmode == false)&&(hp > 0) ){ | |
1858 | + | |
1859 | + int scopemode = myHuman->GetScopeMode(); | |
1860 | + float addang; | |
1861 | + float adddist = 1.2f; | |
1862 | + | |
1863 | + //スコープによる視野角を決定 | |
1864 | + if( scopemode == 0 ){ addang = VIEWANGLE_NORMAL / 4; } | |
1865 | + if( scopemode == 1 ){ addang = VIEWANGLE_SCOPE_1 / 4; } | |
1866 | + if( scopemode == 2 ){ addang = VIEWANGLE_SCOPE_2 / 4; } | |
1867 | + | |
1868 | + //上 | |
1869 | + if( CollD.CheckALLBlockInside(camera_x + cos(camera_rx)*cos(camera_ry + addang) * adddist, camera_y + sin(camera_ry + addang) * adddist, camera_z + sin(camera_rx)*cos(camera_ry + addang) * adddist) == true ){ | |
1870 | + d3dg->Draw2DBox(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT/2, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
1871 | + } | |
1872 | + | |
1873 | + //下 | |
1874 | + if( CollD.CheckALLBlockInside(camera_x + cos(camera_rx)*cos(camera_ry - addang) * adddist, camera_y + sin(camera_ry - addang) * adddist, camera_z + sin(camera_rx)*cos(camera_ry - addang) * adddist) == true ){ | |
1875 | + d3dg->Draw2DBox(0, SCREEN_HEIGHT/2, SCREEN_WIDTH, SCREEN_HEIGHT, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
1876 | + } | |
1877 | + | |
1878 | + //左 | |
1879 | + if( CollD.CheckALLBlockInside(camera_x + cos(camera_rx + addang)*cos(camera_ry) * adddist, camera_y + sin(camera_ry) * adddist, camera_z + sin(camera_rx + addang)*cos(camera_ry) * adddist) == true ){ | |
1880 | + d3dg->Draw2DBox(0, 0, SCREEN_WIDTH/2, SCREEN_HEIGHT, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
1881 | + } | |
1882 | + | |
1883 | + //右 | |
1884 | + if( CollD.CheckALLBlockInside(camera_x + cos(camera_rx - addang)*cos(camera_ry) * adddist, camera_y + sin(camera_ry) * adddist, camera_z + sin(camera_rx - addang)*cos(camera_ry) * adddist) == true ){ | |
1885 | + d3dg->Draw2DBox(SCREEN_WIDTH/2, 0, SCREEN_WIDTH, SCREEN_HEIGHT, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f)); | |
1886 | + } | |
1887 | + } | |
1888 | + | |
1889 | + //デバック用・ゲーム情報の表示 | |
1890 | + if( (ShowInfo_Debugmode == true)||(Camera_Debugmode == true) ){ | |
1891 | + //システムフォントによる表示 見やすい・重い | |
1892 | + /* | |
1893 | + sprintf(str, "OpenXOPS テスト\ncamera x:%.2f y:%.2f z:%.2f rx:%.2f ry:%.2f\n" | |
1894 | + "human[%d]:x:%.2f y:%.2f z:%.2f rx:%.2f\n" | |
1895 | + "I:%02dms PO:%02dms PA:%02dms PE:%02dms R:%02dms", | |
1896 | + camera_x, camera_y, camera_z, camera_rx, camera_ry, | |
1897 | + ObjMgr.GetPlayerID(), human_x, human_y, human_z, human_rx, | |
1898 | + time_input, time_process_object, time_process_ai, time_process_event, time_render); | |
1899 | + d3dg->Draw2DMSFontText(10+1, 10+1, str, d3dg->GetColorCode(0.1f,0.1f,0.1f,1.0f)); | |
1900 | + d3dg->Draw2DMSFontText(10, 10, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f)); | |
1901 | + */ | |
1902 | + | |
1903 | + //テクスチャフォントによる表示 軽い・見にくい | |
1904 | + sprintf(str, "frame:%d time %02d:%02d", framecnt, framecnt/(int)GAMEFPS/60, framecnt/(int)GAMEFPS%60); | |
1905 | + d3dg->Draw2DTextureFontText(10+1, 10+1, str, d3dg->GetColorCode(0.1f,0.1f,0.1f,1.0f), 10, 14); | |
1906 | + d3dg->Draw2DTextureFontText(10, 10, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 10, 14); | |
1907 | + sprintf(str, "camera x:%.2f y:%.2f z:%.2f rx:%.2f ry:%.2f", camera_x, camera_y, camera_z, camera_rx, camera_ry); | |
1908 | + d3dg->Draw2DTextureFontText(10+1, 30+1, str, d3dg->GetColorCode(0.1f,0.1f,0.1f,1.0f), 10, 14); | |
1909 | + d3dg->Draw2DTextureFontText(10, 30, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 10, 14); | |
1910 | + sprintf(str, "human[%d] x:%.2f y:%.2f z:%.2f rx:%.2f HP:%d", ObjMgr.GetPlayerID(), human_x, human_y, human_z, human_rx, hp); | |
1911 | + d3dg->Draw2DTextureFontText(10+1, 50+1, str, d3dg->GetColorCode(0.1f,0.1f,0.1f,1.0f), 10, 14); | |
1912 | + d3dg->Draw2DTextureFontText(10, 50, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 10, 14); | |
1913 | + sprintf(str, "Input:%02dms Object:%02dms AI:%02dms Event:%02dms Sound:%02dms", time_input, time_process_object, time_process_ai, time_process_event, time_sound); | |
1914 | + d3dg->Draw2DTextureFontText(10+1, 70+1, str, d3dg->GetColorCode(0.1f,0.1f,0.1f,1.0f), 10, 14); | |
1915 | + d3dg->Draw2DTextureFontText(10, 70, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 10, 14); | |
1916 | + sprintf(str, "Render:%02dms", time_render); | |
1917 | + d3dg->Draw2DTextureFontText(10+1, 90+1, str, d3dg->GetColorCode(0.1f,0.1f,0.1f,1.0f), 10, 14); | |
1918 | + d3dg->Draw2DTextureFontText(10, 90, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 10, 14); | |
1919 | + } | |
1920 | + | |
1921 | + //ゲーム実行速度の表示 | |
1922 | + if( 1 ){ | |
1923 | + sprintf(str, "fps:%.2f", fps); | |
1924 | + } | |
1925 | + else{ | |
1926 | + int speed = (int)(fps / (1000.0f/GAMEFRAMEMS) * 100); | |
1927 | + sprintf(str, "PROCESSING SPEED %d%%", speed); | |
1928 | + } | |
1929 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH - strlen(str)*14 - 14 +1, 10+1, str, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f), 14, 18); | |
1930 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH - strlen(str)*14 - 14, 10, str, d3dg->GetColorCode(1.0f,0.5f,0.0f,1.0f), 14, 18); | |
1931 | + | |
1932 | + //HUD表示・モードA | |
1933 | + if( Camera_F2mode == 0 ){ | |
1934 | + //左下エリア描画 | |
1935 | + //"ウエエエエエエオ" | |
1936 | + stru[0] = 0xB3; stru[1] = 0xB4; stru[2] = 0xB4; stru[3] = 0xB4; stru[4] = 0xB4; | |
1937 | + stru[5] = 0xB4; stru[6] = 0xB4; stru[7] = 0xB5; stru[8] = 0x00; | |
1938 | + d3dg->Draw2DTextureFontText(15, SCREEN_HEIGHT - 105, (char*)stru, d3dg->GetColorCode(1.0f,1.0f,1.0f,0.5f), 32, 32); | |
1939 | + //"テトトトトトトナ" | |
1940 | + for(int i=0; stru[i] != 0x00; i++){ stru[i] += 0x10; } | |
1941 | + d3dg->Draw2DTextureFontText(15, SCREEN_HEIGHT - 105 +32, (char*)stru, d3dg->GetColorCode(1.0f,1.0f,1.0f,0.5f), 32, 32); | |
1942 | + //"ウエエカキキキクケ" | |
1943 | + stru[0] = 0xB3; stru[1] = 0xB4; stru[2] = 0xB4; stru[3] = 0xB6; stru[4] = 0xB7; | |
1944 | + stru[5] = 0xB7; stru[6] = 0xB7; stru[7] = 0xB8; stru[8] = 0xB9; stru[9] = 0x00; | |
1945 | + d3dg->Draw2DTextureFontText(15, SCREEN_HEIGHT - 55, (char*)stru, d3dg->GetColorCode(1.0f,1.0f,1.0f,0.5f), 32, 32); | |
1946 | + //"テトトニヌヌヌネノ" | |
1947 | + for(int i=0; stru[i] != 0x00; i++){ stru[i] += 0x10; } | |
1948 | + d3dg->Draw2DTextureFontText(15, SCREEN_HEIGHT - 55 +32, (char*)stru, d3dg->GetColorCode(1.0f,1.0f,1.0f,0.5f), 32, 32); | |
1949 | + | |
1950 | + //右下エリア用文字コード設定 | |
1951 | + stru[0] = 0xB0;//'ー'; | |
1952 | + for(int i=1; i<HUDA_WEAPON_SIZEW-1; i++){ | |
1953 | + stru[i] = 0xB1;//'ア'; | |
1954 | + } | |
1955 | + stru[HUDA_WEAPON_SIZEW-1] = 0xB2;//'イ'; | |
1956 | + stru[HUDA_WEAPON_SIZEW] = 0x00; | |
1957 | + | |
1958 | + //右下エリア描画 | |
1959 | + d3dg->Draw2DTextureFontText(HUDA_WEAPON_POSX, HUDA_WEAPON_POSY, (char*)stru, d3dg->GetColorCode(1.0f,1.0f,1.0f,0.5f), 32, 32); | |
1960 | + for(int i=0; i<HUDA_WEAPON_SIZEW; i++){ stru[i] += 0x10; } | |
1961 | + for(int i=1; i<HUDA_WEAPON_SIZEH-1; i++){ | |
1962 | + d3dg->Draw2DTextureFontText(HUDA_WEAPON_POSX, HUDA_WEAPON_POSY + 32*i, (char*)stru, d3dg->GetColorCode(1.0f,1.0f,1.0f,0.5f), 32, 32); | |
1963 | + } | |
1964 | + for(int i=0; i<HUDA_WEAPON_SIZEW; i++){ stru[i] += 0x10; } | |
1965 | + d3dg->Draw2DTextureFontText(HUDA_WEAPON_POSX, HUDA_WEAPON_POSY + 32*(HUDA_WEAPON_SIZEH-1), (char*)stru, d3dg->GetColorCode(1.0f,1.0f,1.0f,0.5f), 32, 32); | |
1966 | + | |
1967 | + //武器の弾数表示 | |
1968 | + sprintf((char*)stru, "A%d B%d", lnbs, (nbs - lnbs)); | |
1969 | + for(int i=0; i<(int)strlen((char*)stru); i++){ | |
1970 | + if( stru[i] == 'A' ){ stru[i] = 0xBB; } //'サ' | |
1971 | + if( stru[i] == 'B' ){ stru[i] = 0xBA; } //'コ' | |
1972 | + } | |
1973 | + d3dg->Draw2DTextureFontText(25, SCREEN_HEIGHT - 96, (char*)stru, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 23, 24); | |
1974 | + | |
1975 | + //HPによる色の決定 | |
1976 | + int statecolor; | |
1977 | + if( hp >= 100 ){ | |
1978 | + statecolor = d3dg->GetColorCode(0.0f,1.0f,0.0f,1.0f); | |
1979 | + } | |
1980 | + else if( hp >= 50 ){ | |
1981 | + statecolor = d3dg->GetColorCode(1.0f/50*(100-hp),1.0f,0.0f,1.0f); | |
1982 | + } | |
1983 | + else if( hp > 0 ){ | |
1984 | + statecolor = d3dg->GetColorCode(1.0f,1.0f/50*hp,0.0f,1.0f); | |
1985 | + } | |
1986 | + else{ | |
1987 | + statecolor = d3dg->GetColorCode(1.0f,0.0f,0.0f,1.0f); | |
1988 | + } | |
1989 | + | |
1990 | + //HP表示 | |
1991 | + if( hp >= 80 ){ | |
1992 | + d3dg->Draw2DTextureFontText(23, SCREEN_HEIGHT - 45, "STATE", statecolor, 18, 24); | |
1993 | + d3dg->Draw2DTextureFontText(155, SCREEN_HEIGHT - 45, "FINE", statecolor, 18, 24); | |
1994 | + } | |
1995 | + else if( hp >= 40 ){ | |
1996 | + d3dg->Draw2DTextureFontText(23, SCREEN_HEIGHT - 45, "STATE", statecolor, 18, 24); | |
1997 | + d3dg->Draw2DTextureFontText(135, SCREEN_HEIGHT - 45, "CAUTION", statecolor, 18, 24); | |
1998 | + } | |
1999 | + else if( hp > 0 ){ | |
2000 | + d3dg->Draw2DTextureFontText(23, SCREEN_HEIGHT - 45, "STATE", statecolor, 18, 24); | |
2001 | + d3dg->Draw2DTextureFontText(140, SCREEN_HEIGHT - 45, "DANGER", statecolor, 18, 24); | |
2002 | + } | |
2003 | + else{ | |
2004 | + d3dg->Draw2DTextureFontText(23, SCREEN_HEIGHT - 45, "STATE", statecolor, 18, 24); | |
2005 | + d3dg->Draw2DTextureFontText(155, SCREEN_HEIGHT - 45, "DEAD", statecolor, 18, 24); | |
2006 | + } | |
2007 | + | |
2008 | + //武器名表示 | |
2009 | + d3dg->Draw2DTextureFontText(HUDA_WEAPON_POSX + 9, HUDA_WEAPON_POSY + 4, weaponname, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 16, 20); | |
2010 | + } | |
2011 | + | |
2012 | + //HUD表示・モードB | |
2013 | + if( Camera_F2mode == 1 ){ | |
2014 | + //画面周りの線 | |
2015 | + d3dg->Draw2DLine(0, 0, SCREEN_WIDTH-1, 0, d3dg->GetColorCode(0.0f,1.0f,0.0f,1.0f)); | |
2016 | + d3dg->Draw2DLine(SCREEN_WIDTH-1, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1, d3dg->GetColorCode(0.0f,1.0f,0.0f,1.0f)); | |
2017 | + d3dg->Draw2DLine(0, 0, 0, SCREEN_HEIGHT-1, d3dg->GetColorCode(0.0f,1.0f,0.0f,1.0f)); | |
2018 | + d3dg->Draw2DLine(0, SCREEN_HEIGHT-1, SCREEN_WIDTH-1, SCREEN_HEIGHT-1, d3dg->GetColorCode(0.0f,1.0f,0.0f,1.0f)); | |
2019 | + | |
2020 | + //武器名表示 | |
2021 | + d3dg->Draw2DBox(8, SCREEN_HEIGHT - 32, 227, SCREEN_HEIGHT - 7, d3dg->GetColorCode(0.0f,0.0f,0.0f,0.3f)); | |
2022 | + d3dg->Draw2DTextureFontText(10, SCREEN_HEIGHT - 30, weaponname, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 16, 20); | |
2023 | + } | |
2024 | + | |
2025 | + //レーダー描画 | |
2026 | + if( radar == true ){ | |
2027 | + RenderRadar(); | |
2028 | + } | |
2029 | + | |
2030 | + //イベントメッセージ表示 | |
2031 | + if( (message_id != -1)&&(message_cnt < (int)(TOTAL_EVENTENT_SHOWMESSEC*GAMEFPS)) ){ | |
2032 | + char messtr[MAX_POINTMESSAGEBYTE]; | |
2033 | + PointData.GetMessageText(messtr, message_id); | |
2034 | + float effectA = 1.0f; | |
2035 | + if( message_cnt < (int)(0.2f*GAMEFPS) ){ effectA = GetEffectAlpha(message_cnt, 1.0f, 0.2f, 0.0f, false); } | |
2036 | + if( (int)((TOTAL_EVENTENT_SHOWMESSEC-0.2f)*GAMEFPS) < message_cnt ){ effectA = GetEffectAlpha(message_cnt, 1.0f, 0.2f, (TOTAL_EVENTENT_SHOWMESSEC - 0.2f), true); } | |
2037 | + d3dg->Draw2DMSFontTextCenter(0 +1, SCREEN_HEIGHT - 140 +1, SCREEN_WIDTH, 140, messtr, d3dg->GetColorCode(0.1f,0.1f,0.1f,effectA)); | |
2038 | + d3dg->Draw2DMSFontTextCenter(0, SCREEN_HEIGHT - 140, SCREEN_WIDTH, 140, messtr, d3dg->GetColorCode(1.0f,1.0f,1.0f,effectA)); | |
2039 | + } | |
2040 | + | |
2041 | + //リロード表示 | |
2042 | + if( reloadcnt > 0 ){ | |
2043 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 145 +3, SCREEN_HEIGHT - 180+3, "RELOADING", d3dg->GetColorCode(0.2f,0.2f,0.2f,1.0f), 32, 34); | |
2044 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 145, SCREEN_HEIGHT - 180, "RELOADING", d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 32, 34); | |
2045 | + } | |
2046 | + | |
2047 | + //武器切り替え表示 | |
2048 | + if( selectweaponcnt > 0 ){ | |
2049 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 130 +3, SCREEN_HEIGHT - 180+3, "CHANGING", d3dg->GetColorCode(0.2f,0.2f,0.2f,1.0f), 32, 34); | |
2050 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 130, SCREEN_HEIGHT - 180, "CHANGING", d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 32, 34); | |
2051 | + } | |
2052 | + | |
2053 | + //照準表示 | |
2054 | + if( (Camera_F1mode == false)&&(param_WeaponP != 2) ){ | |
2055 | + if( (weapon[selectweapon] != NULL)&&(myHuman->GetScopeMode() == 0)&&(param_scopemode != 2) ){ | |
2056 | + if( (end_framecnt == 0)||(GameInfoData.missioncomplete == true) ){ | |
2057 | + if( GameConfig.GetAnotherGunsightFlag() ){ //オプション型 | |
2058 | + //照準の透明度 | |
2059 | + float alpha = 1.0f - (float)ErrorRange/40.0f; | |
2060 | + if( alpha < 0.0f ){ alpha = 0.0f; } | |
2061 | + | |
2062 | + d3dg->Draw2DLine(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, SCREEN_WIDTH/2, SCREEN_HEIGHT/2+4, d3dg->GetColorCode(1.0f,0.0f,0.0f,0.5f)); | |
2063 | + d3dg->Draw2DLine(SCREEN_WIDTH/2-15, SCREEN_HEIGHT/2+15, SCREEN_WIDTH/2-19, SCREEN_HEIGHT/2+19, d3dg->GetColorCode(1.0f,0.0f,0.0f,0.5f)); | |
2064 | + d3dg->Draw2DLine(SCREEN_WIDTH/2+15, SCREEN_HEIGHT/2+15, SCREEN_WIDTH/2+19, SCREEN_HEIGHT/2+19, d3dg->GetColorCode(1.0f,0.0f,0.0f,0.5f)); | |
2065 | + d3dg->Draw2DLine(SCREEN_WIDTH/2-4, SCREEN_HEIGHT/2+4, SCREEN_WIDTH/2+4, SCREEN_HEIGHT/2+4, d3dg->GetColorCode(1.0f,0.0f,0.0f,1.0f)); | |
2066 | + | |
2067 | + d3dg->Draw2DLine(SCREEN_WIDTH/2-4 - ErrorRange, SCREEN_HEIGHT/2-4 - ErrorRange/2, SCREEN_WIDTH/2-4 - ErrorRange, SCREEN_HEIGHT/2+4 + ErrorRange/2, d3dg->GetColorCode(1.0f,0.0f,0.0f,alpha)); | |
2068 | + d3dg->Draw2DLine(SCREEN_WIDTH/2+4 + ErrorRange, SCREEN_HEIGHT/2-4 - ErrorRange/2, SCREEN_WIDTH/2+4 + ErrorRange, SCREEN_HEIGHT/2+4 + ErrorRange/2, d3dg->GetColorCode(1.0f,0.0f,0.0f,alpha)); | |
2069 | + } | |
2070 | + else{ //標準型 | |
2071 | + d3dg->Draw2DLine(SCREEN_WIDTH/2-13, SCREEN_HEIGHT/2, SCREEN_WIDTH/2-3, SCREEN_HEIGHT/2, d3dg->GetColorCode(1.0f,0.0f,0.0f,1.0f)); | |
2072 | + d3dg->Draw2DLine(SCREEN_WIDTH/2+13, SCREEN_HEIGHT/2, SCREEN_WIDTH/2+3, SCREEN_HEIGHT/2, d3dg->GetColorCode(1.0f,0.0f,0.0f,1.0f)); | |
2073 | + d3dg->Draw2DLine(SCREEN_WIDTH/2, SCREEN_HEIGHT/2-13, SCREEN_WIDTH/2, SCREEN_HEIGHT/2-3, d3dg->GetColorCode(1.0f,0.0f,0.0f,1.0f)); | |
2074 | + d3dg->Draw2DLine(SCREEN_WIDTH/2, SCREEN_HEIGHT/2+13, SCREEN_WIDTH/2, SCREEN_HEIGHT/2+3, d3dg->GetColorCode(1.0f,0.0f,0.0f,1.0f)); | |
2075 | + | |
2076 | + stru[0] = 0xBD; stru[1] = 0x00; //"ス" | |
2077 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 16 - ErrorRange, SCREEN_HEIGHT/2 - 16, (char*)stru, d3dg->GetColorCode(1.0f,0.0f,0.0f,0.5f), 32, 32); | |
2078 | + stru[0] = 0xBE; stru[1] = 0x00; //"セ" | |
2079 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 16 + ErrorRange, SCREEN_HEIGHT/2 - 16, (char*)stru, d3dg->GetColorCode(1.0f,0.0f,0.0f,0.5f), 32, 32); | |
2080 | + } | |
2081 | + } | |
2082 | + } | |
2083 | + } | |
2084 | + | |
2085 | + if( tag == true ){ | |
2086 | + int color; | |
2087 | + if( ObjMgr.GetObjectInfoTag(camera_x, camera_y, camera_z, camera_rx, camera_ry, &color, str) == true ){ | |
2088 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - strlen(str)*14/2 + 1, SCREEN_HEIGHT/2 + 30 +1 , str, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f), 14, 18); | |
2089 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - strlen(str)*14/2, SCREEN_HEIGHT/2 + 30, str, color, 14, 18); | |
2090 | + } | |
2091 | + } | |
2092 | + | |
2093 | + | |
2094 | + //----------------------------------- | |
2095 | + | |
2096 | + //Zバッファを初期化 | |
2097 | + d3dg->ResetZbuffer(); | |
2098 | + | |
2099 | + | |
2100 | + //HUD表示・モードA | |
2101 | + if( Camera_F2mode == 0 ){ | |
2102 | + int notselectweapon = selectweapon + 1; | |
2103 | + if( notselectweapon == TOTAL_HAVEWEAPON ){ notselectweapon = 0; } | |
2104 | + | |
2105 | + //(3D描画)カメラ座標を暫定設定 | |
2106 | + d3dg->SetCamera(camera_x, camera_y, camera_z, camera_rx, camera_ry, VIEWANGLE_NORMAL); | |
2107 | + | |
2108 | + //(3D描画)所持している武器モデルの描画・メイン武器 | |
2109 | + GameParamInfo.GetWeapon(weapon_paramid[selectweapon], &weapon_paramdata); | |
2110 | + Resource.GetWeaponModelTexture(weapon_paramid[selectweapon], &weaponmodel, &weapontexture); | |
2111 | + d3dg->SetWorldTransformPlayerWeapon(true, camera_x, camera_y, camera_z, camera_rx, camera_ry, (float)M_PI/180*framecnt*2, weapon_paramdata.size); | |
2112 | + d3dg->RenderModel(weaponmodel, weapontexture); | |
2113 | + | |
2114 | + //(3D描画)所持している武器モデルの描画・サブ武器 | |
2115 | + GameParamInfo.GetWeapon(weapon_paramid[notselectweapon], &weapon_paramdata); | |
2116 | + Resource.GetWeaponModelTexture(weapon_paramid[notselectweapon], &weaponmodel, &weapontexture); | |
2117 | + d3dg->SetWorldTransformPlayerWeapon(false, camera_x, camera_y, camera_z, camera_rx, camera_ry, 0.0f, weapon_paramdata.size); | |
2118 | + d3dg->RenderModel(weaponmodel, weapontexture); | |
2119 | + } | |
2120 | + | |
2121 | + //----------------------------------- | |
2122 | + | |
2123 | +#ifdef ENABLE_DEBUGCONSOLE | |
2124 | + if( Show_Console == true ){ | |
2125 | + if( ScreenShot == false ){ | |
2126 | + RenderConsole(); | |
2127 | + } | |
2128 | + } | |
2129 | +#endif | |
2130 | + | |
2131 | + //----------------------------------- | |
2132 | + | |
2133 | + | |
2134 | + //スタート時と終了時のブラックアウト設定 | |
2135 | + if( start_framecnt < (int)(1.0f*GAMEFPS) ){ | |
2136 | + effect = GetEffectAlpha(start_framecnt, 1.0f, 1.0f, 0.0f, true); | |
2137 | + } | |
2138 | + else if( end_framecnt > 0 ){ | |
2139 | + effect = GetEffectAlpha(end_framecnt, 1.0f, 4.0f, 0.0f, false); | |
2140 | + } | |
2141 | + else{ | |
2142 | + effect = 0.0f; | |
2143 | + } | |
2144 | + d3dg->Draw2DBox(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, d3dg->GetColorCode(0.0f,0.0f,0.0f,effect)); | |
2145 | + | |
2146 | + //終了時の文字表示 | |
2147 | + if( end_framecnt > 0 ){ | |
2148 | + if( end_framecnt < (int)(1.0f*GAMEFPS) ){ | |
2149 | + effect = GetEffectAlpha(end_framecnt, 1.0f, 1.0f, 0.0f, false); | |
2150 | + } | |
2151 | + else if( end_framecnt > (int)(4.0f*GAMEFPS) ){ | |
2152 | + effect = GetEffectAlpha(end_framecnt, 1.0f, 1.0f, 4.0f, true); | |
2153 | + } | |
2154 | + else{ | |
2155 | + effect = 1.0f; | |
2156 | + } | |
2157 | + | |
2158 | + if( GameInfoData.missioncomplete == true ){ | |
2159 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 252, SCREEN_HEIGHT/2 + 10, "objective complete", d3dg->GetColorCode(1.0f,0.5f,0.0f,effect), 28, 32); | |
2160 | + } | |
2161 | + else{ | |
2162 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 210, SCREEN_HEIGHT/2 + 10, "mission failure", d3dg->GetColorCode(1.0f,0.0f,0.0f,effect), 28, 32); | |
2163 | + } | |
2164 | + } | |
2165 | + | |
2166 | + | |
2167 | + time_render = GetTimeMS() - time; | |
2168 | +} | |
2169 | + | |
2170 | +//! @brief レーダーに表示する座標に変換 | |
2171 | +//! @param in_x 空間 X座標 | |
2172 | +//! @param in_y 空間 Y座標 | |
2173 | +//! @param in_z 空間 Z座標 | |
2174 | +//! @param RadarPosX レーダーの描画 X座標(左上基準) | |
2175 | +//! @param RadarPosY レーダーの描画 Y座標(左上基準) | |
2176 | +//! @param RadarSize レーダーの描画サイズ | |
2177 | +//! @param RadarWorldR レーダーにポイントする距離 | |
2178 | +//! @param out_x 2D X座標 を受け取るポインタ | |
2179 | +//! @param out_y 2D X座標 を受け取るポインタ | |
2180 | +//! @param local_y ローカル Y座標 を受け取るポインタ(NULL可) | |
2181 | +//! @param check 計算の省略 | |
2182 | +//! @return 成功:true 失敗:false | |
2183 | +//! @attention checkフラグを有効にすると、レーダーから外れることが明らかになった時点で計算を終了し、falseを返します。 | |
2184 | +bool maingame::GetRadarPos(float in_x, float in_y, float in_z, int RadarPosX, int RadarPosY, int RadarSize, float RadarWorldR, int *out_x, int *out_y, float *local_y, bool check) | |
2185 | +{ | |
2186 | + bool outf = false; | |
2187 | + float x, y, z, r, rx; | |
2188 | + float x2, z2, r2, rx2; | |
2189 | + | |
2190 | + //カメラとの距離を計算 | |
2191 | + x = in_x - camera_x; | |
2192 | + y = in_y - camera_y; | |
2193 | + z = in_z - camera_z; | |
2194 | + | |
2195 | + //近ければ処理する | |
2196 | + if( (check == false) || ((abs(x) < RadarWorldR*2)&&(abs(z) < RadarWorldR*2)&&(abs(y) < 80.0f)) ){ | |
2197 | + //角度を距離を計算 | |
2198 | + rx = atan2(z, x); | |
2199 | + r = sqrt(x*x + z*z); | |
2200 | + | |
2201 | + //カメラ基準の座標を再計算 | |
2202 | + rx2 = (rx - camera_rx)*-1 - (float)M_PI/2; | |
2203 | + x2 = cos(rx2) * r; | |
2204 | + z2 = sin(rx2) * r; | |
2205 | + | |
2206 | + //収まるか判定 | |
2207 | + if( (check == false) || ((abs(x2) < RadarWorldR)&&(abs(z2) < RadarWorldR)) ){ | |
2208 | + //描画座標を計算 | |
2209 | + r2 = r / RadarWorldR * (RadarSize/2); | |
2210 | + *out_x = (int)(RadarPosX+RadarSize/2 + cos(rx2) * r2); | |
2211 | + *out_y = (int)(RadarPosY+RadarSize/2 + sin(rx2) * r2); | |
2212 | + if( local_y != NULL ){ *local_y = y; } | |
2213 | + outf = true; | |
2214 | + } | |
2215 | + } | |
2216 | + | |
2217 | + return outf; | |
2218 | +} | |
2219 | + | |
2220 | +//! @brief 簡易レーダー表示 | |
2221 | +void maingame::RenderRadar() | |
2222 | +{ | |
2223 | + int RadarPosX = 10; //レーダーの描画 X座標(左上基準) | |
2224 | + int RadarPosY = 130; //レーダーの描画 Y座標(左上基準) | |
2225 | + int RadarSize = 200; //レーダーの描画サイズ | |
2226 | + float RadarWorldR = 300.0f; //レーダーにポイントする距離 | |
2227 | + | |
2228 | + float ecr = DISTANCE_CHECKPOINT / RadarWorldR * (RadarSize/2); | |
2229 | + | |
2230 | + //下地と囲い | |
2231 | + d3dg->Draw2DBox(RadarPosX, RadarPosY, RadarPosX+RadarSize, RadarPosY+RadarSize, d3dg->GetColorCode(0.0f,0.0f,0.0f,0.6f)); | |
2232 | + d3dg->Draw2DLine(RadarPosX, RadarPosY, RadarPosX+RadarSize, RadarPosY, d3dg->GetColorCode(0.0f,0.8f,0.0f,1.0f)); | |
2233 | + d3dg->Draw2DLine(RadarPosX+RadarSize, RadarPosY, RadarPosX+RadarSize, RadarPosY+RadarSize, d3dg->GetColorCode(0.0f,0.8f,0.0f,1.0f)); | |
2234 | + d3dg->Draw2DLine(RadarPosX+RadarSize, RadarPosY+RadarSize, RadarPosX, RadarPosY+RadarSize, d3dg->GetColorCode(0.0f,0.8f,0.0f,1.0f)); | |
2235 | + d3dg->Draw2DLine(RadarPosX, RadarPosY+RadarSize, RadarPosX, RadarPosY, d3dg->GetColorCode(0.0f,0.8f,0.0f,1.0f)); | |
2236 | + | |
2237 | + //マップを描画 | |
2238 | + int bs = BlockData.GetTotaldatas(); | |
2239 | + for(int i=0; i< bs; i++){ | |
2240 | + blockdata bdata; | |
2241 | + float x_min, y_min, z_min, x_max, y_max, z_max; | |
2242 | + int vid[4]; | |
2243 | + int bvx[4], bvy[4]; | |
2244 | + | |
2245 | + //ブロックのデータを取得 | |
2246 | + BlockData.Getdata(&bdata, i); | |
2247 | + | |
2248 | + //表示候補のブロックを検出(荒削り) | |
2249 | + CollD.GetBlockPosMINMAX(bdata, &x_min, &y_min, &z_min, &x_max, &y_max, &z_max); | |
2250 | + if( CollideBoxAABB(x_min, y_min, z_min, x_max, y_max, z_max, camera_x-RadarWorldR*2, camera_y-1.0f, camera_z-RadarWorldR*2, camera_x+RadarWorldR*2, camera_y+1.0f, camera_z+RadarWorldR*2) == true ){ | |
2251 | + | |
2252 | + //各面ごとに処理する | |
2253 | + for(int j=0; j<6; j++){ | |
2254 | + //登れない斜面か判定 ※地面や階段などの傾斜を除外する | |
2255 | + float angle = acos(bdata.material[j].vy); | |
2256 | + if( (HUMAN_MAPCOLLISION_SLOPEANGLE < angle)&&(angle < (float)M_PI/18*12) ){ | |
2257 | + | |
2258 | + //ブロック頂点データの関連付けを取得 | |
2259 | + blockdataface(j, &(vid[0]), NULL); | |
2260 | + | |
2261 | + //4頂点を計算 | |
2262 | + for(int k=0; k<4; k++){ | |
2263 | + GetRadarPos(bdata.x[ vid[k] ], bdata.y[ vid[k] ], bdata.z[ vid[k] ], RadarPosX, RadarPosY, RadarSize, RadarWorldR, &(bvx[k]), &(bvy[k]), NULL, false); | |
2264 | + } | |
2265 | + | |
2266 | + int line_x1, line_y1, line_x2, line_y2; | |
2267 | + | |
2268 | + //レーダーの四角形に収まるように描画する | |
2269 | + if( Get2DLineInBox(bvx[0], bvy[0], bvx[1], bvy[1], RadarPosX, RadarPosY, RadarPosX+RadarSize, RadarPosY+RadarSize, &line_x1, &line_y1, &line_x2, &line_y2) == true ){ | |
2270 | + d3dg->Draw2DLine(line_x1, line_y1, line_x2, line_y2, d3dg->GetColorCode(0.8f,0.8f,0.8f,1.0f)); | |
2271 | + } | |
2272 | + if( Get2DLineInBox(bvx[1], bvy[1], bvx[2], bvy[2], RadarPosX, RadarPosY, RadarPosX+RadarSize, RadarPosY+RadarSize, &line_x1, &line_y1, &line_x2, &line_y2) == true ){ | |
2273 | + d3dg->Draw2DLine(line_x1, line_y1, line_x2, line_y2, d3dg->GetColorCode(0.8f,0.8f,0.8f,1.0f)); | |
2274 | + } | |
2275 | + if( Get2DLineInBox(bvx[2], bvy[2], bvx[3], bvy[3], RadarPosX, RadarPosY, RadarPosX+RadarSize, RadarPosY+RadarSize, &line_x1, &line_y1, &line_x2, &line_y2) == true ){ | |
2276 | + d3dg->Draw2DLine(line_x1, line_y1, line_x2, line_y2, d3dg->GetColorCode(0.8f,0.8f,0.8f,1.0f)); | |
2277 | + } | |
2278 | + if( Get2DLineInBox(bvx[3], bvy[3], bvx[0], bvy[0], RadarPosX, RadarPosY, RadarPosX+RadarSize, RadarPosY+RadarSize, &line_x1, &line_y1, &line_x2, &line_y2) == true ){ | |
2279 | + d3dg->Draw2DLine(line_x1, line_y1, line_x2, line_y2, d3dg->GetColorCode(0.8f,0.8f,0.8f,1.0f)); | |
2280 | + } | |
2281 | + } | |
2282 | + } | |
2283 | + } | |
2284 | + } | |
2285 | + | |
2286 | + //イベントの到着ポイントを描画 | |
2287 | + for(int i=0; i<TOTAL_EVENTLINE; i++){ | |
2288 | + signed char p4 = Event[i].GetNextP4(); | |
2289 | + pointdata data; | |
2290 | + if( PointData.SearchPointdata(&data, 0x08, 0, 0, 0, p4, 0) != 0 ){ | |
2291 | + float y; | |
2292 | + int x_2d, y_2d; | |
2293 | + float alpha; | |
2294 | + |