X operations(XOPS)に非常に近いFPSゲームを制作・リメイクし、成果物をオープンソースとして公開することを目的としたプロジェクトです。
修订版 | 45 (tree) |
---|---|
时间 | 2015-02-20 01:15:15 |
作者 | xops-mikan |
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 | + | |
2295 | + if( (data.p1 == 13)||(data.p1 == 16) ){ | |
2296 | + data.y += VIEW_HEIGHT; | |
2297 | + | |
2298 | + if( GetRadarPos(data.x, data.y, data.z, RadarPosX, RadarPosY, RadarSize, RadarWorldR, &x_2d, &y_2d, &y, true) == true ){ | |
2299 | + //高さによる透明度 | |
2300 | + if( (abs(y) < 40.0f) ){ | |
2301 | + alpha = 1.0f; | |
2302 | + } | |
2303 | + else{ | |
2304 | + alpha = 0.5f; | |
2305 | + } | |
2306 | + | |
2307 | + //マーカー描画 | |
2308 | + d3dg->Draw2DCycle(x_2d, y_2d, (int)ecr, d3dg->GetColorCode(1.0f,0.5f,0.0f,alpha)); | |
2309 | + } | |
2310 | + } | |
2311 | + } | |
2312 | + } | |
2313 | + | |
2314 | + //プレイヤーの情報を取得 | |
2315 | + int PlayerID = ObjMgr.GetPlayerID(); | |
2316 | + int myteamid; | |
2317 | + ObjMgr.GeHumanObject(PlayerID)->GetParamData(NULL, NULL, NULL, &myteamid); | |
2318 | + | |
2319 | + //人を描画 | |
2320 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2321 | + human* thuman; | |
2322 | + float tx, ty, tz; | |
2323 | + int tteamid; | |
2324 | + float y; | |
2325 | + int x_2d, y_2d; | |
2326 | + float alpha; | |
2327 | + int color; | |
2328 | + | |
2329 | + //人のオブジェクトを取得 | |
2330 | + thuman = ObjMgr.GeHumanObject(i); | |
2331 | + | |
2332 | + //使われていない人や死体は無視する | |
2333 | + if( thuman->GetDrawFlag() == false ){ continue; } | |
2334 | + if( thuman->GetDeadFlag() == true ){ continue; } | |
2335 | + | |
2336 | + //人の情報を取得 | |
2337 | + thuman->GetPosData(&tx, &ty, &tz, NULL); | |
2338 | + thuman->GetParamData(NULL, NULL, NULL, &tteamid); | |
2339 | + ty += VIEW_HEIGHT; | |
2340 | + | |
2341 | + if( GetRadarPos(tx, ty, tz, RadarPosX, RadarPosY, RadarSize, RadarWorldR, &x_2d, &y_2d, &y, true) == true ){ | |
2342 | + //高さによる透明度 | |
2343 | + if( (abs(y) < 40.0f) ){ | |
2344 | + alpha = 1.0f; | |
2345 | + } | |
2346 | + else{ | |
2347 | + alpha = 0.5f; | |
2348 | + } | |
2349 | + | |
2350 | + //マーカーの色を決定 | |
2351 | + if( PlayerID == i ){ color = d3dg->GetColorCode(1.0f,1.0f,0.0f,alpha); } //プレイヤー自身 | |
2352 | + else if( tteamid == myteamid ){ color = d3dg->GetColorCode(0.0f,0.5f,1.0f,alpha); } //味方 | |
2353 | + else{ color = d3dg->GetColorCode(1.0f,0.0f,0.5f,alpha); } //敵 | |
2354 | + | |
2355 | + //マーカー描画 | |
2356 | + d3dg->Draw2DBox(x_2d-3, y_2d-3, x_2d+3, y_2d+3, color); | |
2357 | + } | |
2358 | + } | |
2359 | +} | |
2360 | + | |
2361 | +#ifdef ENABLE_DEBUGCONSOLE | |
2362 | + | |
2363 | +//! @brief デバック用コンソールに新たな文字列を追加 | |
2364 | +//! @param color 文字の色 | |
2365 | +//! @param str 追加する文字列のポインタ | |
2366 | +//! @attention 新しい文字列は常に下から追加されます。 | |
2367 | +//! @attention 表示可能行数(定数:MAX_CONSOLELINES)を上回る場合、最初の行(1行目)を削除し1行ずつずらした上で、一番下の行に追加します。 | |
2368 | +void maingame::AddInfoConsole(int color, char *str) | |
2369 | +{ | |
2370 | + for(int i=0; i<MAX_CONSOLELINES; i++){ | |
2371 | + if( InfoConsoleData[i].textdata[0] == NULL ){ | |
2372 | + InfoConsoleData[i].color = color; | |
2373 | + strcpy(InfoConsoleData[i].textdata, str); | |
2374 | + return; | |
2375 | + } | |
2376 | + } | |
2377 | + | |
2378 | + for(int i=1; i<MAX_CONSOLELINES; i++){ | |
2379 | + memcpy(&(InfoConsoleData[i-1]), &(InfoConsoleData[i]), sizeof(ConsoleData)); | |
2380 | + } | |
2381 | + InfoConsoleData[MAX_CONSOLELINES-1].color = color; | |
2382 | + strcpy(InfoConsoleData[MAX_CONSOLELINES-1].textdata, str); | |
2383 | +} | |
2384 | + | |
2385 | +//! @brief 入力用コンソールに文字を一文字追加 | |
2386 | +//! @param inchar 追加する文字 | |
2387 | +void maingame::ConsoleInputText(char inchar) | |
2388 | +{ | |
2389 | + for(int i=0; i<MAX_CONSOLELEN; i++){ | |
2390 | + if( InputConsoleData->textdata[i] == NULL ){ | |
2391 | + InputConsoleData->textdata[i] = inchar; | |
2392 | + InputConsoleData->textdata[i+1] = NULL; | |
2393 | + return; | |
2394 | + } | |
2395 | + } | |
2396 | +} | |
2397 | + | |
2398 | +//! @brief 入力用コンソールの文字を一文字削除 | |
2399 | +void maingame::ConsoleDeleteText() | |
2400 | +{ | |
2401 | + int s = strlen(InputConsoleData->textdata); | |
2402 | + if( s == (int)strlen(CONSOLE_PROMPT) ){ return; } | |
2403 | + InputConsoleData->textdata[ s-1 ] = NULL; | |
2404 | +} | |
2405 | + | |
2406 | +//! @brief コマンドの判定および引数(整数値)を取得 | |
2407 | +//! @param cmd 判定するコマンド文字のポインタ | |
2408 | +//! @param num 与えられた引数を受け取るポインタ | |
2409 | +//! @return 取得:true 判定外:false | |
2410 | +bool maingame::GetCommandNum(char *cmd, int *num) | |
2411 | +{ | |
2412 | + char str[MAX_CONSOLELEN]; | |
2413 | + | |
2414 | + //コマンド名を調べる | |
2415 | + strcpy(str, NewCommand); | |
2416 | + str[ strlen(cmd) ] = NULL; | |
2417 | + if( strcmp(str, cmd) != 0 ){ return false; } | |
2418 | + | |
2419 | + //「コマンド名_X」分の文字数に達しているかどうか | |
2420 | + if( strlen(cmd)+2 > strlen(NewCommand) ){ return false; } | |
2421 | + | |
2422 | + //与えられた数字を調べる | |
2423 | + *num = atoi(&(NewCommand[ strlen(cmd)+1 ])); | |
2424 | + return true; | |
2425 | +} | |
2426 | + | |
2427 | +//! @brief デバック用コンソールの入力処理 | |
2428 | +void maingame::InputConsole() | |
2429 | +{ | |
2430 | + NewCommand[0] = NULL; | |
2431 | + | |
2432 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x0F)) ){ // [ENTER] | |
2433 | + //何か入力されていれば〜 | |
2434 | + if( strcmp(InputConsoleData->textdata, CONSOLE_PROMPT) != 0 ){ | |
2435 | + //コンソールに追加し、未処理コマンドとして登録 | |
2436 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), InputConsoleData->textdata); | |
2437 | + strcpy(NewCommand, &(InputConsoleData->textdata[strlen(CONSOLE_PROMPT)])); | |
2438 | + } | |
2439 | + | |
2440 | + //入力エリアを初期化 | |
2441 | + strcpy(InputConsoleData->textdata, CONSOLE_PROMPT); | |
2442 | + } | |
2443 | + else{ | |
2444 | + //数字 | |
2445 | + for(char key=0x16; key<=0x1F; key++){ | |
2446 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(key)) ){ | |
2447 | + ConsoleInputText(key + 0x1A); | |
2448 | + } | |
2449 | + } | |
2450 | + for(char key=0x04; key<=0x0D; key++){ | |
2451 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(key)) ){ | |
2452 | + ConsoleInputText(key + 0x2C); | |
2453 | + } | |
2454 | + } | |
2455 | + | |
2456 | + //アルファベット小文字 | |
2457 | + for(char key=0x20; key<=0x39; key++){ | |
2458 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(key)) ){ | |
2459 | + ConsoleInputText(key + 0x41); | |
2460 | + } | |
2461 | + } | |
2462 | + | |
2463 | + //スペース | |
2464 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x11)) ){ // [SPACE] | |
2465 | + ConsoleInputText(' '); | |
2466 | + } | |
2467 | + | |
2468 | + //一文字削除 | |
2469 | + if( inputCtrl->CheckKeyDown(OriginalkeycodeToDinputdef(0x0E)) ){ // [BACK] | |
2470 | + ConsoleDeleteText(); | |
2471 | + } | |
2472 | + } | |
2473 | +} | |
2474 | + | |
2475 | +//! @brief デバック用コンソールのメイン処理 | |
2476 | +void maingame::ProcessConsole() | |
2477 | +{ | |
2478 | + char str[MAX_CONSOLELEN]; | |
2479 | + int id; | |
2480 | + | |
2481 | + //コマンドリスト | |
2482 | + if( strcmp(NewCommand, "help") == 0 ){ | |
2483 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "help human result event"); | |
2484 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "ver"); | |
2485 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "info view center map"); | |
2486 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "tag radar"); | |
2487 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "revive treat <NUM> nodamage <NUM>"); | |
2488 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "kill <NUM> break <NUM> newobj <NUM>"); | |
2489 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "bot nofight caution stop"); | |
2490 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "ss clear"); | |
2491 | + } | |
2492 | + | |
2493 | + //人の統計情報 | |
2494 | + if( strcmp(NewCommand, "human") == 0 ){ | |
2495 | + int alivemyfriend = 0; | |
2496 | + int myfriend = 0; | |
2497 | + int aliveenemy = 0; | |
2498 | + int enemy = 0; | |
2499 | + int myteamid; | |
2500 | + | |
2501 | + //プレイヤーのチーム番号を取得 | |
2502 | + ObjMgr.GetPlayerHumanObject()->GetParamData(NULL, NULL, NULL, &myteamid); | |
2503 | + | |
2504 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2505 | + int teamid; | |
2506 | + bool deadflag; | |
2507 | + human *thuman = ObjMgr.GeHumanObject(i); | |
2508 | + if( thuman->GetDrawFlag() == true ){ | |
2509 | + //死亡状態とチーム番号を取得 | |
2510 | + deadflag = thuman->GetDeadFlag(); | |
2511 | + thuman->GetParamData(NULL, NULL, NULL, &teamid); | |
2512 | + | |
2513 | + //カウント | |
2514 | + if( teamid == myteamid ){ | |
2515 | + myfriend += 1; | |
2516 | + if( deadflag == false ){ alivemyfriend += 1; } | |
2517 | + } | |
2518 | + else{ | |
2519 | + enemy += 1; | |
2520 | + if( deadflag == false ){ aliveenemy += 1; } | |
2521 | + } | |
2522 | + } | |
2523 | + } | |
2524 | + | |
2525 | + sprintf(str, "Friend:%d/%d Enemy:%d/%d Total:%d/%d", | |
2526 | + alivemyfriend, myfriend, aliveenemy, enemy, alivemyfriend + aliveenemy, myfriend + enemy); | |
2527 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2528 | + } | |
2529 | + | |
2530 | + //暫定リザルト表示 | |
2531 | + if( strcmp(NewCommand, "result") == 0 ){ | |
2532 | + float rate; | |
2533 | + if( MainGameInfo.fire == 0 ){ | |
2534 | + rate = 0.0f; | |
2535 | + } | |
2536 | + else{ | |
2537 | + rate = (float)MainGameInfo.ontarget / MainGameInfo.fire * 100; | |
2538 | + } | |
2539 | + | |
2540 | + sprintf(str, "Time %02d:%02d / Fired %d / On target %d", framecnt/(int)GAMEFPS/60, framecnt/(int)GAMEFPS%60, MainGameInfo.fire, MainGameInfo.ontarget); | |
2541 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2542 | + sprintf(str, "AR rate %.1f%% / Kill %d / HS %d", rate, MainGameInfo.kill, MainGameInfo.headshot); | |
2543 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2544 | + } | |
2545 | + | |
2546 | + //イベントタスク表示 | |
2547 | + if( strcmp(NewCommand, "event") == 0 ){ | |
2548 | + for(int i=0; i<TOTAL_EVENTLINE; i++){ | |
2549 | + signed char p4 = Event[i].GetNextP4(); | |
2550 | + pointdata data; | |
2551 | + if( PointData.SearchPointdata(&data, 0x08, 0, 0, 0, p4, 0) == 0 ){ | |
2552 | + sprintf(str, "Event %d No task.", i); | |
2553 | + } | |
2554 | + else{ | |
2555 | + sprintf(str, "Event %d [%d][%d][%d][%d]", i, data.p1, data.p2, data.p3, data.p4); | |
2556 | + } | |
2557 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2558 | + } | |
2559 | + } | |
2560 | + | |
2561 | + //デバック用文字の表示 | |
2562 | + if( strcmp(NewCommand, "info") == 0 ){ | |
2563 | + if( ShowInfo_Debugmode == false ){ | |
2564 | + ShowInfo_Debugmode = true; | |
2565 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Show Debug information."); | |
2566 | + } | |
2567 | + else{ | |
2568 | + ShowInfo_Debugmode = false; | |
2569 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Hide Debug information."); | |
2570 | + } | |
2571 | + } | |
2572 | + | |
2573 | + //フリーカメラ切り替え | |
2574 | + if( strcmp(NewCommand, "view") == 0 ){ | |
2575 | + if( Camera_Debugmode == false ){ | |
2576 | + Camera_Debugmode = true; | |
2577 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Change FreeView mode."); | |
2578 | + } | |
2579 | + else{ | |
2580 | + Camera_Debugmode = false; | |
2581 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Change PlayerView mode."); | |
2582 | + } | |
2583 | + | |
2584 | + //デバックモード開始時のカメラ設定 | |
2585 | + if( Camera_Debugmode == true ){ | |
2586 | + camera_x = 100.0f; | |
2587 | + camera_y = 100.0f; | |
2588 | + camera_z = -100.0f; | |
2589 | + camera_rx = (float)M_PI/180*135; | |
2590 | + camera_ry = (float)M_PI/180*(-40); | |
2591 | + } | |
2592 | + } | |
2593 | + | |
2594 | + //3Dの中心線表示 | |
2595 | + if( strcmp(NewCommand, "center") == 0 ){ | |
2596 | + if( CenterLine == false ){ | |
2597 | + CenterLine = true; | |
2598 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Show World center position."); | |
2599 | + } | |
2600 | + else{ | |
2601 | + CenterLine = false; | |
2602 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Hide World center position."); | |
2603 | + } | |
2604 | + } | |
2605 | + | |
2606 | + //マップをワイヤーフレーム化 | |
2607 | + if( strcmp(NewCommand, "map") == 0 ){ | |
2608 | + if( wireframe == false ){ | |
2609 | + wireframe = true; | |
2610 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Draw map on the Wire frame."); | |
2611 | + } | |
2612 | + else{ | |
2613 | + wireframe = false; | |
2614 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Draw map on the Normal."); | |
2615 | + } | |
2616 | + } | |
2617 | + | |
2618 | + //オブジェクトのタグを表示 | |
2619 | + if( strcmp(NewCommand, "tag") == 0 ){ | |
2620 | + if( tag == false ){ | |
2621 | + tag = true; | |
2622 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Show object information."); | |
2623 | + } | |
2624 | + else{ | |
2625 | + tag = false; | |
2626 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Hide object information."); | |
2627 | + } | |
2628 | + } | |
2629 | + | |
2630 | + if( strcmp(NewCommand, "radar") == 0 ){ | |
2631 | + if( radar == false ){ | |
2632 | + radar = true; | |
2633 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Show Radar."); | |
2634 | + } | |
2635 | + else{ | |
2636 | + radar = false; | |
2637 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Hide Radar."); | |
2638 | + } | |
2639 | + } | |
2640 | + | |
2641 | + //全ての死者を蘇生する | |
2642 | + if( strcmp(NewCommand, "revive") == 0 ){ | |
2643 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2644 | + ObjMgr.HumanResuscitation(i); | |
2645 | + } | |
2646 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "All human has resuscitation."); | |
2647 | + } | |
2648 | + | |
2649 | + //回復する | |
2650 | + if( GetCommandNum("treat", &id) == true ){ | |
2651 | + if( (0 <= id)&&(id < MAX_HUMAN) ){ | |
2652 | + int param, hp; | |
2653 | + HumanParameter data; | |
2654 | + human *thuman = ObjMgr.GeHumanObject(id); | |
2655 | + | |
2656 | + //初期時のHPを取得 | |
2657 | + thuman->GetParamData(¶m, NULL, NULL, NULL); | |
2658 | + GameParamInfo.GetHuman(param, &data); | |
2659 | + hp = data.hp; | |
2660 | + | |
2661 | + //回復 | |
2662 | + if( thuman->SetHP(hp) == true ){ | |
2663 | + sprintf(str, "Set the HP:%d to Human[%d].", data.hp, id); | |
2664 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2665 | + } | |
2666 | + } | |
2667 | + } | |
2668 | + | |
2669 | + //無敵化 | |
2670 | + if( GetCommandNum("nodamage", &id) == true ){ | |
2671 | + if( (0 <= id)&&(id < MAX_HUMAN) ){ | |
2672 | + if( InvincibleID == id ){ | |
2673 | + //同じ番号が指定されたらなら、無効化 | |
2674 | + InvincibleID = -1; | |
2675 | + ObjMgr.GeHumanObject(id)->SetInvincibleFlag(false); | |
2676 | + sprintf(str, "Not invincible Human[%d].", id); | |
2677 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2678 | + } | |
2679 | + else{ | |
2680 | + //既に誰かが指定されていたら、既に指定されている人を無効化 | |
2681 | + if( InvincibleID != -1 ){ | |
2682 | + ObjMgr.GeHumanObject(InvincibleID)->SetInvincibleFlag(false); | |
2683 | + sprintf(str, "Not invincible Human[%d].", InvincibleID); | |
2684 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2685 | + } | |
2686 | + | |
2687 | + //新たに無敵状態の人を指定 | |
2688 | + InvincibleID = id; | |
2689 | + ObjMgr.GeHumanObject(id)->SetInvincibleFlag(true); | |
2690 | + sprintf(str, "Invincible Human[%d].", id); | |
2691 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2692 | + } | |
2693 | + } | |
2694 | + } | |
2695 | + | |
2696 | + //殺害 | |
2697 | + if( GetCommandNum("kill", &id) == true ){ | |
2698 | + if( (0 <= id)&&(id < MAX_HUMAN) ){ | |
2699 | + human *thuman = ObjMgr.GeHumanObject(id); | |
2700 | + if( thuman->GetDrawFlag() == true ){ | |
2701 | + if( thuman->SetHP(0) == true ){ | |
2702 | + sprintf(str, "Killed Human[%d].", id); | |
2703 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2704 | + } | |
2705 | + } | |
2706 | + } | |
2707 | + } | |
2708 | + | |
2709 | + //小物を破壊 | |
2710 | + if( GetCommandNum("break", &id) == true ){ | |
2711 | + if( (0 <= id)&&(id < MAX_SMALLOBJECT) ){ | |
2712 | + smallobject *tsmallobject = ObjMgr.GetSmallObject(id); | |
2713 | + if( tsmallobject->GetDrawFlag() == true ){ | |
2714 | + tsmallobject->Destruction(); | |
2715 | + sprintf(str, "Broke SmallObject[%d].", id); | |
2716 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2717 | + } | |
2718 | + } | |
2719 | + } | |
2720 | + | |
2721 | + //小物を新規配置 | |
2722 | + if( GetCommandNum("newobj", &id) == true ){ | |
2723 | + if( (0 <= id)&&(id < TOTAL_PARAMETERINFO_SMALLOBJECT) ){ | |
2724 | + int dataid = ObjMgr.AddSmallObjectIndex(camera_x + cos(camera_rx)*20.0f, camera_y, camera_z + sin(camera_rx)*20.0f, camera_rx*-1, id, true); | |
2725 | + if( dataid != -1 ){ | |
2726 | + sprintf(str, "Add SmallObject[%d].", dataid); | |
2727 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2728 | + } | |
2729 | + } | |
2730 | + } | |
2731 | + | |
2732 | + //プレイヤー操作をAI化 | |
2733 | + if( strcmp(NewCommand, "bot") == 0 ){ | |
2734 | + if( PlayerAI == false ){ | |
2735 | + PlayerAI = true; | |
2736 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Player is AI control. (bot)"); | |
2737 | + } | |
2738 | + else{ | |
2739 | + PlayerAI = false; | |
2740 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Player is User control."); | |
2741 | + } | |
2742 | + } | |
2743 | + | |
2744 | + //AIを非戦闘化させる | |
2745 | + if( strcmp(NewCommand, "nofight") == 0 ){ | |
2746 | + if( AINoFight == false ){ | |
2747 | + AINoFight = true; | |
2748 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2749 | + HumanAI[i].SetNoFightFlag(true); | |
2750 | + } | |
2751 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "AI had no Fight."); | |
2752 | + } | |
2753 | + else{ | |
2754 | + AINoFight = false; | |
2755 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2756 | + HumanAI[i].SetNoFightFlag(false); | |
2757 | + } | |
2758 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "AI had Fight."); | |
2759 | + } | |
2760 | + } | |
2761 | + | |
2762 | + //AIを警戒させる | |
2763 | + if( strcmp(NewCommand, "caution") == 0 ){ | |
2764 | + for(int i=0; i<MAX_HUMAN; i++){ | |
2765 | + HumanAI[i].SetCautionMode(); | |
2766 | + } | |
2767 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Set cautious AI."); | |
2768 | + } | |
2769 | + | |
2770 | + //AIの処理を停止 | |
2771 | + if( strcmp(NewCommand, "stop") == 0 ){ | |
2772 | + if( AIstop == false ){ | |
2773 | + AIstop = true; | |
2774 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Stopped AI control."); | |
2775 | + } | |
2776 | + else{ | |
2777 | + AIstop = false; | |
2778 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Started AI control."); | |
2779 | + } | |
2780 | + } | |
2781 | + | |
2782 | + /* | |
2783 | + //ミッション達成 | |
2784 | + if( strcmp(NewCommand, "comp") == 0 ){ | |
2785 | + end_framecnt += 1; | |
2786 | + MainGameInfo.missioncomplete = true; | |
2787 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Mission complete."); | |
2788 | + } | |
2789 | + | |
2790 | + //ミッション失敗 | |
2791 | + if( strcmp(NewCommand, "fail") == 0 ){ | |
2792 | + end_framecnt += 1; | |
2793 | + MainGameInfo.missioncomplete = false; | |
2794 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "Mission fail."); | |
2795 | + } | |
2796 | + */ | |
2797 | + | |
2798 | + //バージョン情報取得 | |
2799 | + if( strcmp(NewCommand, "ver") == 0 ){ | |
2800 | + sprintf(str, "%s Version:%s", GAMENAME, GAMEVERSION); | |
2801 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2802 | + } | |
2803 | + | |
2804 | + //スクリーンショットを撮影 | |
2805 | + // ※コンソール画面を削除するため、撮影を1フレーム遅らせる。 | |
2806 | + if( ScreenShot == true ){ | |
2807 | + char fname[256]; | |
2808 | + | |
2809 | + //ファイル名を決定 | |
2810 | + GetTimeName(fname); | |
2811 | + strcat(fname, ".bmp"); | |
2812 | + | |
2813 | + //撮影・保存 | |
2814 | + if( d3dg->SaveScreenShot(fname) == true ){ | |
2815 | + sprintf(str, "Saved Screenshot (File:%s)", fname); | |
2816 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), str); | |
2817 | + } | |
2818 | + else{ | |
2819 | + AddInfoConsole(d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), "[Error] Save failed."); | |
2820 | + } | |
2821 | + } | |
2822 | + if( strcmp(NewCommand, "ss") == 0 ){ | |
2823 | + ScreenShot = true; | |
2824 | + } | |
2825 | + else{ | |
2826 | + ScreenShot = false; | |
2827 | + } | |
2828 | + | |
2829 | + //コンソールをクリア | |
2830 | + if( strcmp(NewCommand, "clear") == 0 ){ | |
2831 | + for(int i=0; i<MAX_CONSOLELINES; i++){ | |
2832 | + InfoConsoleData[i].color = d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f); | |
2833 | + InfoConsoleData[i].textdata[0] = NULL; | |
2834 | + } | |
2835 | + } | |
2836 | +} | |
2837 | + | |
2838 | +//! @brief デバック用コンソールの描画処理 | |
2839 | +void maingame::RenderConsole() | |
2840 | +{ | |
2841 | + //下地 | |
2842 | + d3dg->Draw2DBox(0, 0, SCREEN_WIDTH, (MAX_CONSOLELINES+1)*18 + 5 + 5, d3dg->GetColorCode(0.0f,0.0f,0.0f,0.75f)); | |
2843 | + | |
2844 | + //表示中の文字 | |
2845 | + for(int i=0; i<MAX_CONSOLELINES; i++){ | |
2846 | + if( InfoConsoleData[i].textdata[0] != NULL ){ | |
2847 | + d3dg->Draw2DTextureFontText(5+1, i*18+5+1, InfoConsoleData[i].textdata, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f), 14, 17); | |
2848 | + d3dg->Draw2DTextureFontText(5, i*18+5, InfoConsoleData[i].textdata, InfoConsoleData[i].color, 14, 17); | |
2849 | + } | |
2850 | + } | |
2851 | + | |
2852 | + //入力中の文字 | |
2853 | + int cnt; | |
2854 | + for(cnt=0; cnt<MAX_CONSOLELINES; cnt++){ | |
2855 | + if( InfoConsoleData[cnt].textdata[0] == NULL ){ break; } | |
2856 | + } | |
2857 | + d3dg->Draw2DTextureFontText(5+1, cnt*18+5+1, InputConsoleData->textdata, d3dg->GetColorCode(0.0f,0.0f,0.0f,1.0f), 14, 17); | |
2858 | + d3dg->Draw2DTextureFontText(5, cnt*18+5, InputConsoleData->textdata, InputConsoleData->color, 14, 17); | |
2859 | +} | |
2860 | + | |
2861 | +#endif | |
2862 | + | |
2863 | +void maingame::Destroy() | |
2864 | +{ | |
2865 | + //ブロックデータ解放 | |
2866 | + d3dg->CleanupMapdata(); | |
2867 | + | |
2868 | + //オブジェクトマネージャー解放 | |
2869 | + ObjMgr.Cleanup(); | |
2870 | + | |
2871 | + //背景空解放 | |
2872 | + Resource.CleanupSkyModelTexture(); | |
2873 | + | |
2874 | +#ifdef ENABLE_DEBUGCONSOLE | |
2875 | + //コンソール用データを解放 | |
2876 | + if( InfoConsoleData != NULL ){ delete [] InfoConsoleData; } | |
2877 | + if( InputConsoleData != NULL ){ delete InputConsoleData; } | |
2878 | +#endif | |
2879 | + | |
2880 | + GameState->NextState(); | |
2881 | +} | |
2882 | + | |
2883 | +//! @brief コンストラクタ | |
2884 | +result::result() | |
2885 | +{} | |
2886 | + | |
2887 | +//! @brief ディストラクタ | |
2888 | +result::~result() | |
2889 | +{} | |
2890 | + | |
2891 | +//! @brief リザルト画面の2D描画部分 | |
2892 | +void result::Render2D() | |
2893 | +{ | |
2894 | + char mname[64]; | |
2895 | + char str[32]; | |
2896 | + float effectA = GetEffectAlphaLoop(framecnt, 1.0f, 0.8f, true); | |
2897 | + float rate; | |
2898 | + if( GameInfoData.fire == 0 ){ | |
2899 | + rate = 0.0f; | |
2900 | + } | |
2901 | + else{ | |
2902 | + rate = (float)GameInfoData.ontarget / GameInfoData.fire * 100; | |
2903 | + } | |
2904 | + | |
2905 | + //メモ:背景画像の描画は、自動的に行われる。 | |
2906 | + | |
2907 | + //固定文字描画 | |
2908 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 50*3, 40, "RESULT", d3dg->GetColorCode(1.0f,0.0f,1.0f,effectA), 50, 42); | |
2909 | + | |
2910 | + //ミッション名を取得し描画 | |
2911 | + if( MIFdata.GetFiletype() == false ){ | |
2912 | + GameParamInfo.GetOfficialMission(GameInfoData.selectmission_id, NULL, mname, NULL, NULL); | |
2913 | + } | |
2914 | + else{ | |
2915 | + strcpy(mname, MIFdata.GetMissionFullname()); | |
2916 | + } | |
2917 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - strlen(mname)*18/2, 100, mname, d3dg->GetColorCode(0.5f,0.5f,1.0f,1.0f), 18, 25); | |
2918 | + | |
2919 | + //ミッションクリアーの有無 | |
2920 | + if( GameInfoData.missioncomplete == true ){ | |
2921 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 216, 150, "mission successful", d3dg->GetColorCode(0.0f,1.0f,0.0f,1.0f), 24, 32); | |
2922 | + } | |
2923 | + else{ | |
2924 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2 - 180, 150, "mission failure", d3dg->GetColorCode(1.0f,0.0f,0.0f,1.0f), 24, 32); | |
2925 | + } | |
2926 | + | |
2927 | + //結果表示 | |
2928 | + sprintf(str, "Time %dmin %dsec", GameInfoData.framecnt/(int)GAMEFPS/60, GameInfoData.framecnt/(int)GAMEFPS%60); | |
2929 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2-strlen(str)*20/2, 210, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 20, 32); | |
2930 | + sprintf(str, "Rounds fired %d", GameInfoData.fire); | |
2931 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2-strlen(str)*20/2, 260, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 20, 32); | |
2932 | + sprintf(str, "Rounds on target %d", GameInfoData.ontarget); | |
2933 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2-strlen(str)*20/2, 310, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 20, 32); | |
2934 | + sprintf(str, "Accuracy rate %.1f%%", rate); | |
2935 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2-strlen(str)*20/2, 360, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 20, 32); | |
2936 | + sprintf(str, "Kill %d / HeadShot %d", GameInfoData.kill, GameInfoData.headshot); | |
2937 | + d3dg->Draw2DTextureFontText(SCREEN_WIDTH/2-strlen(str)*20/2, 410, str, d3dg->GetColorCode(1.0f,1.0f,1.0f,1.0f), 20, 32); | |
2938 | +} | |
2939 | + | |
2940 | +//! @brief screen派生クラスの初期化(クラスの設定) | |
2941 | +void InitScreen(opening *Opening, mainmenu *MainMenu, briefing *Briefing, maingame *MainGame, result *Result) | |
2942 | +{ | |
2943 | + Opening->SetClass(&GameState, &d3dg, &inputCtrl, &GameSound); | |
2944 | + MainMenu->SetClass(&GameState, &d3dg, &inputCtrl, &GameSound); | |
2945 | + Briefing->SetClass(&GameState, &d3dg, &inputCtrl); | |
2946 | + MainGame->SetClass(&GameState, &d3dg, &inputCtrl, &GameSound); | |
2947 | + Result->SetClass(&GameState, &d3dg, &inputCtrl); | |
2948 | +} | |
2949 | + | |
2950 | +//! @brief screen派生クラスの実行 | |
2951 | +void ProcessScreen(HWND hWnd, opening *Opening, mainmenu *MainMenu, briefing *Briefing, maingame *MainGame, result *Result, unsigned int framecnt) | |
2952 | +{ | |
2953 | + int error; | |
2954 | + | |
2955 | + switch(GameState.GetState()){ | |
2956 | + //オープニング初期化 | |
2957 | + case STATE_CREATE_OPENING: | |
2958 | + error = Opening->Create(); | |
2959 | + if( error == 1 ){ | |
2960 | + MessageBox(hWnd, "block data open failed", "error", MB_OK); | |
2961 | + PostMessage(hWnd, WM_CLOSE, 0L, 0L); | |
2962 | + } | |
2963 | + if( error == 2 ){ | |
2964 | + MessageBox(hWnd, "point data open failed", "error", MB_OK); | |
2965 | + PostMessage(hWnd, WM_CLOSE, 0L, 0L); | |
2966 | + } | |
2967 | + break; | |
2968 | + | |
2969 | + //オープニング実行 | |
2970 | + case STATE_NOW_OPENING: | |
2971 | + Opening->Input(); | |
2972 | + Opening->Process(); | |
2973 | + Opening->Sound(); | |
2974 | + if( (GameConfig.GetFrameskipFlag() == false)||(framecnt%2 == 0) ){ | |
2975 | + if( Opening->RenderMain() == true ){ | |
2976 | + ResetGame(hWnd); | |
2977 | + } | |
2978 | + } | |
2979 | + break; | |
2980 | + | |
2981 | + //オープニング廃棄 | |
2982 | + case STATE_DESTROY_OPENING: | |
2983 | + Opening->Destroy(); | |
2984 | + break; | |
2985 | + | |
2986 | + //メニュー初期化 | |
2987 | + case STATE_CREATE_MENU: | |
2988 | + error = MainMenu->Create(); | |
2989 | + if( error == 1 ){ | |
2990 | + MessageBox(hWnd, "block data open failed", "error", MB_OK); | |
2991 | + PostMessage(hWnd, WM_CLOSE, 0L, 0L); | |
2992 | + } | |
2993 | + if( error == 2 ){ | |
2994 | + MessageBox(hWnd, "point data open failed", "error", MB_OK); | |
2995 | + PostMessage(hWnd, WM_CLOSE, 0L, 0L); | |
2996 | + } | |
2997 | + break; | |
2998 | + | |
2999 | + //メニュー実行 | |
3000 | + case STATE_NOW_MENU: | |
3001 | + MainMenu->Input(); | |
3002 | + MainMenu->Process(); | |
3003 | + MainMenu->Sound(); | |
3004 | + if( (GameConfig.GetFrameskipFlag() == false)||(framecnt%2 == 0) ){ | |
3005 | + if( MainMenu->RenderMain() == true ){ | |
3006 | + ResetGame(hWnd); | |
3007 | + } | |
3008 | + } | |
3009 | + break; | |
3010 | + | |
3011 | + //メニュー廃棄 | |
3012 | + case STATE_DESTROY_MENU: | |
3013 | + MainMenu->Destroy(); | |
3014 | + break; | |
3015 | + | |
3016 | + //ブリーフィング初期化 | |
3017 | + case STATE_CREATE_BRIEFING: | |
3018 | + error = Briefing->Create(); | |
3019 | + if( error == 1 ){ | |
3020 | + MessageBox(hWnd, "briefing data open failed", "error", MB_OK); | |
3021 | + PostMessage(hWnd, WM_CLOSE, 0L, 0L); | |
3022 | + } | |
3023 | + break; | |
3024 | + | |
3025 | + //ブリーフィング実行 | |
3026 | + case STATE_NOW_BRIEFING: | |
3027 | + Briefing->Input(); | |
3028 | + Briefing->Process(); | |
3029 | + if( (GameConfig.GetFrameskipFlag() == false)||(framecnt%2 == 0) ){ | |
3030 | + if( Briefing->RenderMain() == true ){ | |
3031 | + ResetGame(hWnd); | |
3032 | + } | |
3033 | + } | |
3034 | + break; | |
3035 | + | |
3036 | + //ブリーフィング廃棄 | |
3037 | + case STATE_DESTROY_BRIEFING: | |
3038 | + Briefing->Destroy(); | |
3039 | + break; | |
3040 | + | |
3041 | + //メインゲーム初期化 | |
3042 | + case STATE_CREATE_MAINGAME: | |
3043 | + error = MainGame->Create(); | |
3044 | + if( error == 1 ){ | |
3045 | + MessageBox(hWnd, "block data open failed", "error", MB_OK); | |
3046 | + PostMessage(hWnd, WM_CLOSE, 0L, 0L); | |
3047 | + } | |
3048 | + if( error == 2 ){ | |
3049 | + MessageBox(hWnd, "point data open failed", "error", MB_OK); | |
3050 | + PostMessage(hWnd, WM_CLOSE, 0L, 0L); | |
3051 | + } | |
3052 | + break; | |
3053 | + | |
3054 | + //メインゲーム実行 | |
3055 | + case STATE_NOW_MAINGAME: | |
3056 | + MainGame->Input(); | |
3057 | + MainGame->Process(); | |
3058 | + MainGame->Sound(); | |
3059 | + if( (GameConfig.GetFrameskipFlag() == false)||(framecnt%2 == 0) ){ | |
3060 | + if( MainGame->RenderMain() == true ){ | |
3061 | + ResetGame(hWnd); | |
3062 | + } | |
3063 | + } | |
3064 | + break; | |
3065 | + | |
3066 | + //メインゲーム廃棄 | |
3067 | + case STATE_DESTROY_MAINGAME: | |
3068 | + MainGame->Destroy(); | |
3069 | + break; | |
3070 | + | |
3071 | + //リザルト初期化 | |
3072 | + case STATE_CREATE_RESULT: | |
3073 | + error = Result->Create(); | |
3074 | + break; | |
3075 | + | |
3076 | + //リザルト実行 | |
3077 | + case STATE_NOW_RESULT: | |
3078 | + Result->Input(); | |
3079 | + Result->Process(); | |
3080 | + if( (GameConfig.GetFrameskipFlag() == false)||(framecnt%2 == 0) ){ | |
3081 | + if( Result->RenderMain() == true ){ | |
3082 | + ResetGame(hWnd); | |
3083 | + } | |
3084 | + } | |
3085 | + break; | |
3086 | + | |
3087 | + //リザルト廃棄 | |
3088 | + case STATE_DESTROY_RESULT: | |
3089 | + Result->Destroy(); | |
3090 | + break; | |
3091 | + | |
3092 | + //ゲーム終了 | |
3093 | + case STATE_EXIT: | |
3094 | + PostMessage(hWnd, WM_CLOSE, 0L, 0L); | |
3095 | + break; | |
3096 | + | |
3097 | + default: | |
3098 | + break; | |
3099 | + } | |
3100 | +} | |
\ No newline at end of file |
@@ -0,0 +1,1163 @@ | ||
1 | +//! @file collision.cpp | |
2 | +//! @brief Collisionクラスの定義 | |
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 "collision.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +Collision::Collision() | |
36 | +{ | |
37 | + blockdata = NULL; | |
38 | + bmin_x = new float[MAX_BLOCKS]; | |
39 | + bmin_y = new float[MAX_BLOCKS]; | |
40 | + bmin_z = new float[MAX_BLOCKS]; | |
41 | + bmax_x = new float[MAX_BLOCKS]; | |
42 | + bmax_y = new float[MAX_BLOCKS]; | |
43 | + bmax_z = new float[MAX_BLOCKS]; | |
44 | + BoardBlock = new bool[MAX_BLOCKS]; | |
45 | + bdata_worldgroup = new int[MAX_BLOCKS]; | |
46 | + for(int i=0; i<MAX_BLOCKS; i++){ | |
47 | + bmin_x[i] = 0.0f; | |
48 | + bmin_y[i] = 0.0f; | |
49 | + bmin_z[i] = 0.0f; | |
50 | + bmax_x[i] = 0.0f; | |
51 | + bmax_y[i] = 0.0f; | |
52 | + bmax_z[i] = 0.0f; | |
53 | + BoardBlock[i] = false; | |
54 | + bdata_worldgroup[i] = 0; | |
55 | + } | |
56 | +} | |
57 | + | |
58 | +//! @brief ディストラクタ | |
59 | +Collision::~Collision() | |
60 | +{ | |
61 | + if( bmin_x != NULL ){ delete [] bmin_x; } | |
62 | + if( bmin_y != NULL ){ delete [] bmin_y; } | |
63 | + if( bmin_z != NULL ){ delete [] bmin_z; } | |
64 | + if( bmax_x != NULL ){ delete [] bmax_x; } | |
65 | + if( bmax_y != NULL ){ delete [] bmax_y; } | |
66 | + if( bmax_z != NULL ){ delete [] bmax_z; } | |
67 | + if( BoardBlock != NULL ){ delete [] BoardBlock; } | |
68 | + if( bdata_worldgroup != NULL ){ delete [] bdata_worldgroup; } | |
69 | +} | |
70 | + | |
71 | +//! @brief ブロックデータを取り込む | |
72 | +//! @param in_blockdata ブロックデータ | |
73 | +int Collision::InitCollision(BlockDataInterface* in_blockdata) | |
74 | +{ | |
75 | + int bs; | |
76 | + struct blockdata data; | |
77 | + int vID[4]; | |
78 | + float g0, g1, costheta; | |
79 | + D3DXVECTOR3 dv1, dv2, dv3; | |
80 | + | |
81 | + if( in_blockdata == NULL ){ return 1; } | |
82 | + blockdata = in_blockdata; | |
83 | + | |
84 | + bs = blockdata->GetTotaldatas(); | |
85 | + | |
86 | + for(int i=0; i<bs; i++){ | |
87 | + BoardBlock[i] = false; | |
88 | + } | |
89 | + | |
90 | + //判定用平面作成 | |
91 | + for(int i=0; i<bs; i++){ | |
92 | + blockdata->Getdata(&data, i); | |
93 | + for(int j=0; j<6; j++){ | |
94 | + blockdataface(j, &vID[0], NULL); | |
95 | + | |
96 | + dv1 = D3DXVECTOR3( data.x[ vID[1] ], data.y[ vID[1] ], data.z[ vID[1] ] ); | |
97 | + dv2 = D3DXVECTOR3( data.x[ vID[2] ], data.y[ vID[2] ], data.z[ vID[2] ] ); | |
98 | + dv3 = D3DXVECTOR3( data.x[ vID[0] ], data.y[ vID[0] ], data.z[ vID[0] ] ); | |
99 | + D3DXPlaneFromPoints(&bdata_plane[i][j][0], &dv1, &dv2, &dv3); | |
100 | + dv1 = D3DXVECTOR3( data.x[ vID[0] ], data.y[ vID[0] ], data.z[ vID[0] ] ); | |
101 | + dv2 = D3DXVECTOR3( data.x[ vID[2] ], data.y[ vID[2] ], data.z[ vID[2] ] ); | |
102 | + dv3 = D3DXVECTOR3( data.x[ vID[3] ], data.y[ vID[3] ], data.z[ vID[3] ] ); | |
103 | + D3DXPlaneFromPoints(&bdata_plane[i][j][1], &dv1, &dv2, &dv3); | |
104 | + | |
105 | + //2つの三角形が持つ法線のなす角を求める | |
106 | + g0 = sqrt(bdata_plane[i][j][0].a * bdata_plane[i][j][0].a + bdata_plane[i][j][0].b * bdata_plane[i][j][0].b + bdata_plane[i][j][0].c * bdata_plane[i][j][0].c); | |
107 | + g1 = sqrt(bdata_plane[i][j][1].a * bdata_plane[i][j][1].a + bdata_plane[i][j][1].b * bdata_plane[i][j][1].b + bdata_plane[i][j][1].c * bdata_plane[i][j][1].c); | |
108 | + costheta = (bdata_plane[i][j][0].a * bdata_plane[i][j][1].a + bdata_plane[i][j][0].b * bdata_plane[i][j][1].b + bdata_plane[i][j][0].c * bdata_plane[i][j][1].c) / (g0 * g1); | |
109 | + | |
110 | + //1つの面で法線が90度以上違う(=異常)なら〜 | |
111 | + if( acos(costheta) > (float)M_PI/2 ){ | |
112 | + //違う三角形で作る | |
113 | + dv1 = D3DXVECTOR3( data.x[ vID[2] ], data.y[ vID[2] ], data.z[ vID[2] ] ); | |
114 | + dv2 = D3DXVECTOR3( data.x[ vID[3] ], data.y[ vID[3] ], data.z[ vID[3] ] ); | |
115 | + dv3 = D3DXVECTOR3( data.x[ vID[1] ], data.y[ vID[1] ], data.z[ vID[1] ] ); | |
116 | + D3DXPlaneFromPoints(&bdata_plane[i][j][0], &dv1, &dv2, &dv3); | |
117 | + dv1 = D3DXVECTOR3( data.x[ vID[1] ], data.y[ vID[1] ], data.z[ vID[1] ] ); | |
118 | + dv2 = D3DXVECTOR3( data.x[ vID[3] ], data.y[ vID[3] ], data.z[ vID[3] ] ); | |
119 | + dv3 = D3DXVECTOR3( data.x[ vID[0] ], data.y[ vID[0] ], data.z[ vID[0] ] ); | |
120 | + D3DXPlaneFromPoints(&bdata_plane[i][j][1], &dv1, &dv2, &dv3); | |
121 | + } | |
122 | + } | |
123 | + } | |
124 | + | |
125 | + //板状のブロックを検出 | |
126 | + for(int i=0; i<bs; i++){ | |
127 | + blockdata->Getdata(&data, i); | |
128 | + | |
129 | + BoardBlock[i] = false; | |
130 | + | |
131 | + for(int j=0; j<8; j++){ | |
132 | + for(int k=j+1; k<8; k++){ | |
133 | + //一ヵ所でも頂点が同じなら、板状になっていると判定。 | |
134 | + if( (data.x[j] == data.x[k])&&(data.y[j] == data.y[k])&&(data.z[j] == data.z[k]) ){ | |
135 | + BoardBlock[i] = true; | |
136 | + } | |
137 | + } | |
138 | + } | |
139 | + } | |
140 | + | |
141 | + | |
142 | + //ブロックAABB作成 | |
143 | + for(int i=0; i<bs; i++){ | |
144 | + blockdata->Getdata(&data, i); | |
145 | + GetBlockPosMINMAX(data, &bmin_x[i], &bmin_y[i], &bmin_z[i], &bmax_x[i], &bmax_y[i], &bmax_z[i]); | |
146 | + } | |
147 | + | |
148 | + //ブロックの空間分割グループを計算 | |
149 | + for(int i=0; i<bs; i++){ | |
150 | + ///* | |
151 | + blockdata->Getdata(&data, i); | |
152 | + | |
153 | + bdata_worldgroup[i] = GetWorldGroup(bmin_x[i], bmin_z[i]); | |
154 | + if( GetWorldGroup(bmax_x[i], bmax_z[i]) != bdata_worldgroup[i] ){ | |
155 | + bdata_worldgroup[i] = 0; | |
156 | + } | |
157 | + //*/ | |
158 | + //bdata_worldgroup[i] = 0; | |
159 | + } | |
160 | + | |
161 | + return 0; | |
162 | +} | |
163 | + | |
164 | +//! @brief ブロックの座標最大値・最小値を返す | |
165 | +//! @param data ブロックデータの構造体 | |
166 | +//! @param *min_x 最小 X座標を返すポインタ | |
167 | +//! @param *min_y 最小 Y座標を返すポインタ | |
168 | +//! @param *min_z 最小 Z座標を返すポインタ | |
169 | +//! @param *max_x 最大 X座標を返すポインタ | |
170 | +//! @param *max_y 最大 Y座標を返すポインタ | |
171 | +//! @param *max_z 最大 Z座標を返すポインタ | |
172 | +void Collision::GetBlockPosMINMAX(struct blockdata data, float *min_x, float *min_y, float *min_z, float *max_x, float *max_y, float *max_z) | |
173 | +{ | |
174 | + *min_x = data.x[0]; | |
175 | + *min_y = data.y[0]; | |
176 | + *min_z = data.z[0]; | |
177 | + *max_x = data.x[0]; | |
178 | + *max_y = data.y[0]; | |
179 | + *max_z = data.z[0]; | |
180 | + for(int i=1; i<8; i++){ | |
181 | + if( *min_x > data.x[i] ){ *min_x = data.x[i]; } | |
182 | + if( *min_y > data.y[i] ){ *min_y = data.y[i]; } | |
183 | + if( *min_z > data.z[i] ){ *min_z = data.z[i]; } | |
184 | + | |
185 | + if( *max_x < data.x[i] ){ *max_x = data.x[i]; } | |
186 | + if( *max_y < data.y[i] ){ *max_y = data.y[i]; } | |
187 | + if( *max_z < data.z[i] ){ *max_z = data.z[i]; } | |
188 | + } | |
189 | +} | |
190 | + | |
191 | +//! @brief 空間分割のグループを算出 | |
192 | +//! @param x X座標 | |
193 | +//! @param z Z座標 | |
194 | +//! @return グループ番号 | |
195 | +//! @attention 「グループ番号」の概念は別途ドキュメントを参照 | |
196 | +int Collision::GetWorldGroup(float x, float z) | |
197 | +{ | |
198 | + if( (x > 0)&&(z > 0) ){ return 1; } | |
199 | + if( (x < 0)&&(z > 0) ){ return 2; } | |
200 | + if( (x < 0)&&(z < 0) ){ return 3; } | |
201 | + if( (x > 0)&&(z < 0) ){ return 4; } | |
202 | + return 0; | |
203 | +} | |
204 | + | |
205 | +//! @brief ブロックに埋まっていないか調べる | |
206 | +//! @param blockid 判定するブロック番号 | |
207 | +//! @param x X座標 | |
208 | +//! @param y X座標 | |
209 | +//! @param z X座標 | |
210 | +//! @param worldgroup 空間のグループを利用して計算省略を試みる(true:有効・計算省略 false:無効・完全検索) | |
211 | +//! @param *planeid 表にある面番号(NULL可) | |
212 | +//! @return 埋っている:true 埋っていない:false | |
213 | +//! @warning *planeid が返す表面(0〜5)は、複数の面が該当する場合でも、最初に見つけた1面のみ返します。 | |
214 | +bool Collision::CheckBlockInside(int blockid, float x, float y, float z, bool worldgroup, int *planeid) | |
215 | +{ | |
216 | + D3DXVECTOR3 dv; | |
217 | + | |
218 | + if( blockdata == NULL ){ return false; } | |
219 | + if( (blockid < 0)||(blockdata->GetTotaldatas() <= blockid) ){ return false; } | |
220 | + | |
221 | + //板状のブロックは計算外 | |
222 | + if( BoardBlock[blockid] == true ){ return false; } | |
223 | + | |
224 | + | |
225 | + //判定の荒削り | |
226 | + if( worldgroup == true ){ | |
227 | + | |
228 | + //空間分割 | |
229 | + if( bdata_worldgroup[blockid] != 0 ){ | |
230 | + //観測点の空間のグループを取得 | |
231 | + int worldgroup = GetWorldGroup(x, z); | |
232 | + | |
233 | + if( worldgroup != 0 ){ | |
234 | + //空間のグループが違えば計算外 | |
235 | + if( bdata_worldgroup[blockid] != worldgroup ){ | |
236 | + return false; | |
237 | + } | |
238 | + } | |
239 | + } | |
240 | + | |
241 | + //範囲で検索 | |
242 | + if( (x < bmin_x[blockid])||(bmax_x[blockid] < x) ){ return false; } | |
243 | + if( (y < bmin_y[blockid])||(bmax_y[blockid] < y) ){ return false; } | |
244 | + if( (z < bmin_z[blockid])||(bmax_z[blockid] < z) ){ return false; } | |
245 | + } | |
246 | + | |
247 | + | |
248 | + //6面から見て全て裏面かどうか | |
249 | + for(int i=0; i<6; i++){ | |
250 | + dv = D3DXVECTOR3( x, y, z ); | |
251 | + if( (D3DXPlaneDotCoord(&bdata_plane[blockid][i][0], &dv) > 0)||(D3DXPlaneDotCoord(&bdata_plane[blockid][i][1], &dv) > 0) ){ | |
252 | + if( planeid != NULL ){ *planeid = i; } | |
253 | + return false; //表面ならば終了 | |
254 | + } | |
255 | + } | |
256 | + | |
257 | + return true; | |
258 | +} | |
259 | + | |
260 | +//! @brief 全てのブロックに埋まっていないか調べる | |
261 | +//! @param x X座標 | |
262 | +//! @param y X座標 | |
263 | +//! @param z X座標 | |
264 | +//! @return 埋っている:true 埋っていない:false | |
265 | +bool Collision::CheckALLBlockInside(float x, float y, float z) | |
266 | +{ | |
267 | + if( blockdata == NULL ){ return false; } | |
268 | + | |
269 | + int bs = blockdata->GetTotaldatas(); | |
270 | + | |
271 | + for(int i=0; i<bs; i++){ | |
272 | + if( CheckBlockInside(i, x, y, z, true, NULL) == true ){ return true; } | |
273 | + } | |
274 | + | |
275 | + return false; | |
276 | +} | |
277 | + | |
278 | +//! @brief ブロックとレイ(光線)のあたり判定 | |
279 | +//! @param blockid 判定するブロック番号 | |
280 | +//! @param RayPos_x レイの位置(始点)を指定する X座標 | |
281 | +//! @param RayPos_y レイの位置(始点)を指定する Y座標 | |
282 | +//! @param RayPos_z レイの位置(始点)を指定する Z座標 | |
283 | +//! @param RayDir_x レイのベクトルを指定する X成分 | |
284 | +//! @param RayDir_y レイのベクトルを指定する Y成分 | |
285 | +//! @param RayDir_z レイのベクトルを指定する Z成分 | |
286 | +//! @param face 当たったブロックの面番号(0〜5)を受け取るポインタ (NULL可) | |
287 | +//! @param Dist 当たったブロックとの距離を受け取るポインタ | |
288 | +//! @param maxDist 判定を行う最大距離 (0.0 未満で無効・無限) | |
289 | +//! @return 当たっている:true 当たっていない:false | |
290 | +//! @warning RayPos(始点)と RayDir(ベクトル)を間違えないこと。 | |
291 | +//! @warning 判定を行う最大距離を指定しないと、パフォーマンスが大幅に低下します。 | |
292 | +//! @attention レイの始点から裏側になるブロックの面は無視されます。厚さをゼロに変形させた板状のブロックも無視します。 | |
293 | +//! @attention また、レイが複数のブロックに当たる場合は、レイの始点から一番近い判定を返します。 | |
294 | +bool Collision::CheckBlockIntersectRay(int blockid, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, int *face, float *Dist, float maxDist) | |
295 | +{ | |
296 | + if( blockdata == NULL ){ return false; } | |
297 | + | |
298 | + struct blockdata data; | |
299 | + int vID[4]; | |
300 | + float pDist; | |
301 | + float min_pDist = FLT_MAX; | |
302 | + int min_blockface = -1; | |
303 | + float rmin_x = 0.0f; | |
304 | + float rmin_y = 0.0f; | |
305 | + float rmin_z = 0.0f; | |
306 | + float rmax_x = 0.0f; | |
307 | + float rmax_y = 0.0f; | |
308 | + float rmax_z = 0.0f; | |
309 | + int worldgroupA = 0; | |
310 | + int worldgroupB = 0; | |
311 | + | |
312 | + //板状のブロックは計算外 | |
313 | + if( BoardBlock[blockid] == true ){ | |
314 | + if( face != NULL ){ *face = 0; } | |
315 | + *Dist = 0.0f; | |
316 | + return false; | |
317 | + } | |
318 | + | |
319 | + if( maxDist > 0.0f ){ | |
320 | + //レイのAABBを作る | |
321 | + rmin_x = RayPos_x + RayDir_x * maxDist; | |
322 | + rmin_y = RayPos_y + RayDir_y * maxDist; | |
323 | + rmin_z = RayPos_z + RayDir_z * maxDist; | |
324 | + rmax_x = rmin_x; | |
325 | + rmax_y = rmin_y; | |
326 | + rmax_z = rmin_z; | |
327 | + if( rmin_x > RayPos_x ){ rmin_x = RayPos_x; } | |
328 | + if( rmin_y > RayPos_y ){ rmin_y = RayPos_y; } | |
329 | + if( rmin_z > RayPos_z ){ rmin_z = RayPos_z; } | |
330 | + if( rmax_x < RayPos_x ){ rmax_x = RayPos_x; } | |
331 | + if( rmax_y < RayPos_y ){ rmax_y = RayPos_y; } | |
332 | + if( rmax_z < RayPos_z ){ rmax_z = RayPos_z; } | |
333 | + } | |
334 | + | |
335 | + D3DXVECTOR3 pRayPos(RayPos_x, RayPos_y, RayPos_z); | |
336 | + D3DXVECTOR3 pRayDir(RayDir_x, RayDir_y, RayDir_z); | |
337 | + | |
338 | + if( maxDist > 0.0f ){ | |
339 | + //始点と終点の空間グループを取得 | |
340 | + worldgroupA = GetWorldGroup(RayPos_x, RayPos_z); | |
341 | + worldgroupB = GetWorldGroup(RayPos_x + RayDir_x * maxDist, RayPos_z + RayDir_z * maxDist); | |
342 | + } | |
343 | + | |
344 | + blockdata->Getdata(&data, blockid); | |
345 | + | |
346 | + if( maxDist > 0.0f ){ | |
347 | + if( bdata_worldgroup[blockid] != 0 ){ | |
348 | + //始点と終点が、空間のグループから出ていなければ | |
349 | + if( (worldgroupA != 0)&&(worldgroupA == worldgroupB) ){ | |
350 | + | |
351 | + //空間のグループが違えば計算外 | |
352 | + if( bdata_worldgroup[blockid] == worldgroupA ){ //worldgroupA == worldgroupB | |
353 | + //境界ボックス同士で判定 | |
354 | + if( CollideBoxAABB(bmin_x[blockid], bmin_y[blockid], bmin_z[blockid], bmax_x[blockid], bmax_y[blockid], bmax_z[blockid], rmin_x, rmin_y, rmin_z, rmax_x, rmax_y, rmax_z) == false ){ | |
355 | + //当たってなければ、このブロックは調べない。 | |
356 | + if( face != NULL ){ *face = 0; } | |
357 | + *Dist = 0.0f; | |
358 | + return false; | |
359 | + } | |
360 | + } | |
361 | + } | |
362 | + } | |
363 | + } | |
364 | + | |
365 | + //境界ボックスとレイで判定 | |
366 | + if( CollideAABBRay(bmin_x[blockid], bmin_y[blockid], bmin_z[blockid], bmax_x[blockid], bmax_y[blockid], bmax_z[blockid], RayPos_x, RayPos_y, RayPos_z, RayDir_x, RayDir_y, RayDir_z, NULL, -1.0f) == false ){ | |
367 | + //当たってなければ、このブロックは調べない。 | |
368 | + if( face != NULL ){ *face = 0; } | |
369 | + *Dist = 0.0f; | |
370 | + return false; | |
371 | + } | |
372 | + | |
373 | + //各ポリゴン単位で判定 | |
374 | + for(int i=0; i<6; i++){ | |
375 | + blockdataface(i, vID, NULL); | |
376 | + if( (D3DXPlaneDotCoord(&bdata_plane[blockid][i][0], &pRayPos) >= 0)||(D3DXPlaneDotCoord(&bdata_plane[blockid][i][1], &pRayPos) >= 0) ){ | |
377 | + D3DXVECTOR3 dv11, dv12, dv13; | |
378 | + D3DXVECTOR3 dv21, dv22, dv23; | |
379 | + | |
380 | + dv11 = D3DXVECTOR3( data.x[vID[0]], data.y[vID[0]], data.z[vID[0]]); | |
381 | + dv12 = D3DXVECTOR3( data.x[vID[1]], data.y[vID[1]], data.z[vID[1]]); | |
382 | + dv13 = D3DXVECTOR3( data.x[vID[2]], data.y[vID[2]], data.z[vID[2]]); | |
383 | + | |
384 | + dv21 = D3DXVECTOR3( data.x[vID[2]], data.y[vID[2]], data.z[vID[2]]); | |
385 | + dv22 = D3DXVECTOR3( data.x[vID[3]], data.y[vID[3]], data.z[vID[3]]); | |
386 | + dv23 = D3DXVECTOR3( data.x[vID[0]], data.y[vID[0]], data.z[vID[0]]); | |
387 | + | |
388 | + if( (D3DXIntersectTri(&dv11, &dv12, &dv13, &pRayPos, &pRayDir, NULL, NULL, &pDist) == TRUE)|| | |
389 | + (D3DXIntersectTri(&dv21, &dv22, &dv23, &pRayPos, &pRayDir, NULL, NULL, &pDist) == TRUE) | |
390 | + ){ | |
391 | + if( min_pDist > pDist ){ | |
392 | + min_pDist = pDist; | |
393 | + min_blockface = i; | |
394 | + } | |
395 | + } | |
396 | + } | |
397 | + } | |
398 | + | |
399 | + //見つからなければ、ポインタに適当な数字を入れて返す。 | |
400 | + if( min_blockface == -1 ){ | |
401 | + if( face != NULL ){ *face = 0; } | |
402 | + *Dist = 0.0f; | |
403 | + return false; | |
404 | + } | |
405 | + | |
406 | + //計算結果を入れて返す | |
407 | + if( face != NULL ){ *face = min_blockface; } | |
408 | + *Dist = min_pDist; | |
409 | + return true; | |
410 | +} | |
411 | + | |
412 | +//! @brief 全てのブロックとレイ(光線)のあたり判定 | |
413 | +//! @param RayPos_x レイの位置(始点)を指定する X座標 | |
414 | +//! @param RayPos_y レイの位置(始点)を指定する Y座標 | |
415 | +//! @param RayPos_z レイの位置(始点)を指定する Z座標 | |
416 | +//! @param RayDir_x レイのベクトルを指定する X成分 | |
417 | +//! @param RayDir_y レイのベクトルを指定する Y成分 | |
418 | +//! @param RayDir_z レイのベクトルを指定する Z成分 | |
419 | +//! @param id 当たったブロックのIDを受け取るポインタ (NULL可) | |
420 | +//! @param face 当たったブロックの面番号(0〜5)を受け取るポインタ (NULL可) | |
421 | +//! @param Dist 当たったブロックとの距離を受け取るポインタ | |
422 | +//! @param maxDist 判定を行う最大距離 (0.0 未満で無効・無限) | |
423 | +//! @return 当たっている:true 当たっていない:false | |
424 | +//! @warning RayPos(始点)と RayDir(ベクトル)を間違えないこと。 | |
425 | +//! @warning 判定を行う最大距離を指定しないと、パフォーマンスが大幅に低下します。 | |
426 | +//! @warning 使い方は CheckALLBlockIntersectDummyRay()関数 と類似していますが、同関数より高精度で低速です。 | |
427 | +//! @attention レイの始点から裏側になるブロックの面は無視されます。厚さをゼロに変形させた板状のブロックも無視します。 | |
428 | +//! @attention また、レイが複数のブロックに当たる場合は、<b>レイの始点から一番近い判定</b>を返します。 | |
429 | +bool Collision::CheckALLBlockIntersectRay(float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, int *id, int *face, float *Dist, float maxDist) | |
430 | +{ | |
431 | + if( blockdata == NULL ){ return false; } | |
432 | + | |
433 | + int bs = blockdata->GetTotaldatas(); | |
434 | + struct blockdata data; | |
435 | + int vID[4]; | |
436 | + float pDist; | |
437 | + float min_pDist = FLT_MAX; | |
438 | + int min_blockid = -1; | |
439 | + int min_blockface = -1; | |
440 | + float rmin_x = 0.0f; | |
441 | + float rmin_y = 0.0f; | |
442 | + float rmin_z = 0.0f; | |
443 | + float rmax_x = 0.0f; | |
444 | + float rmax_y = 0.0f; | |
445 | + float rmax_z = 0.0f; | |
446 | + int worldgroupA = 0; | |
447 | + int worldgroupB = 0; | |
448 | + | |
449 | + if( maxDist > 0.0f ){ | |
450 | + //レイのAABBを作る | |
451 | + rmin_x = RayPos_x + RayDir_x * maxDist; | |
452 | + rmin_y = RayPos_y + RayDir_y * maxDist; | |
453 | + rmin_z = RayPos_z + RayDir_z * maxDist; | |
454 | + rmax_x = rmin_x; | |
455 | + rmax_y = rmin_y; | |
456 | + rmax_z = rmin_z; | |
457 | + if( rmin_x > RayPos_x ){ rmin_x = RayPos_x; } | |
458 | + if( rmin_y > RayPos_y ){ rmin_y = RayPos_y; } | |
459 | + if( rmin_z > RayPos_z ){ rmin_z = RayPos_z; } | |
460 | + if( rmax_x < RayPos_x ){ rmax_x = RayPos_x; } | |
461 | + if( rmax_y < RayPos_y ){ rmax_y = RayPos_y; } | |
462 | + if( rmax_z < RayPos_z ){ rmax_z = RayPos_z; } | |
463 | + } | |
464 | + | |
465 | + D3DXVECTOR3 pRayPos(RayPos_x, RayPos_y, RayPos_z); | |
466 | + D3DXVECTOR3 pRayDir(RayDir_x, RayDir_y, RayDir_z); | |
467 | + | |
468 | + if( maxDist > 0.0f ){ | |
469 | + //始点と終点の空間グループを取得 | |
470 | + worldgroupA = GetWorldGroup(RayPos_x, RayPos_z); | |
471 | + worldgroupB = GetWorldGroup(RayPos_x + RayDir_x * maxDist, RayPos_z + RayDir_z * maxDist); | |
472 | + } | |
473 | + | |
474 | + for(int i=0; i<bs; i++){ | |
475 | + //板状のブロックは計算外 | |
476 | + if( BoardBlock[i] == true ){ continue; } | |
477 | + | |
478 | + blockdata->Getdata(&data, i); | |
479 | + | |
480 | + if( maxDist > 0.0f ){ | |
481 | + if( bdata_worldgroup[i] != 0 ){ | |
482 | + //始点と終点が、空間のグループから出ていなければ | |
483 | + if( (worldgroupA != 0)&&(worldgroupA == worldgroupB) ){ | |
484 | + | |
485 | + //空間のグループが違えば計算外 | |
486 | + if( bdata_worldgroup[i] == worldgroupA ){ //worldgroupA == worldgroupB | |
487 | + | |
488 | + //境界ボックス同士で判定 | |
489 | + if( CollideBoxAABB(bmin_x[i], bmin_y[i], bmin_z[i], bmax_x[i], bmax_y[i], bmax_z[i], rmin_x, rmin_y, rmin_z, rmax_x, rmax_y, rmax_z) == false ){ | |
490 | + continue; //当たってなければ、このブロックは調べない。 | |
491 | + } | |
492 | + | |
493 | + } | |
494 | + } | |
495 | + } | |
496 | + } | |
497 | + | |
498 | + //境界ボックスとレイで判定 | |
499 | + if( CollideAABBRay(bmin_x[i], bmin_y[i], bmin_z[i], bmax_x[i], bmax_y[i], bmax_z[i], RayPos_x, RayPos_y, RayPos_z, RayDir_x, RayDir_y, RayDir_z, NULL, -1.0f) == false ){ | |
500 | + continue; //当たってなければ、このブロックは調べない。 | |
501 | + } | |
502 | + | |
503 | + //各ポリゴン単位で判定 | |
504 | + for(int j=0; j<6; j++){ | |
505 | + blockdataface(j, vID, NULL); | |
506 | + if( (D3DXPlaneDotCoord(&bdata_plane[i][j][0], &pRayPos) >= 0)||(D3DXPlaneDotCoord(&bdata_plane[i][j][1], &pRayPos) >= 0) ){ | |
507 | + D3DXVECTOR3 dv11, dv12, dv13; | |
508 | + D3DXVECTOR3 dv21, dv22, dv23; | |
509 | + | |
510 | + dv11 = D3DXVECTOR3( data.x[vID[0]], data.y[vID[0]], data.z[vID[0]]); | |
511 | + dv12 = D3DXVECTOR3( data.x[vID[1]], data.y[vID[1]], data.z[vID[1]]); | |
512 | + dv13 = D3DXVECTOR3( data.x[vID[2]], data.y[vID[2]], data.z[vID[2]]); | |
513 | + | |
514 | + dv21 = D3DXVECTOR3( data.x[vID[2]], data.y[vID[2]], data.z[vID[2]]); | |
515 | + dv22 = D3DXVECTOR3( data.x[vID[3]], data.y[vID[3]], data.z[vID[3]]); | |
516 | + dv23 = D3DXVECTOR3( data.x[vID[0]], data.y[vID[0]], data.z[vID[0]]); | |
517 | + | |
518 | + if( (D3DXIntersectTri(&dv11, &dv12, &dv13, &pRayPos, &pRayDir, NULL, NULL, &pDist) == TRUE)|| | |
519 | + (D3DXIntersectTri(&dv21, &dv22, &dv23, &pRayPos, &pRayDir, NULL, NULL, &pDist) == TRUE) | |
520 | + ){ | |
521 | + if( min_pDist > pDist ){ | |
522 | + min_pDist = pDist; | |
523 | + min_blockid = i; | |
524 | + min_blockface = j; | |
525 | + } | |
526 | + } | |
527 | + } | |
528 | + } | |
529 | + } | |
530 | + | |
531 | + //見つけた距離が最大距離を超えていれば、判定を無効に。 | |
532 | + if( maxDist >= 0.0f ){ | |
533 | + if( min_pDist > maxDist ){ | |
534 | + min_blockid = -1; | |
535 | + } | |
536 | + } | |
537 | + | |
538 | + //見つからなければ、ポインタに適当な数字を入れて返す。 | |
539 | + if( min_blockid == -1 ){ | |
540 | + if( id != NULL ){ *id = 0; } | |
541 | + if( face != NULL ){ *face = 0; } | |
542 | + *Dist = 0.0f; | |
543 | + return false; | |
544 | + } | |
545 | + | |
546 | + //計算結果を入れて返す | |
547 | + if( id != NULL ){ *id = min_blockid; } | |
548 | + if( face != NULL ){ *face = min_blockface; } | |
549 | + *Dist = min_pDist; | |
550 | + return true; | |
551 | +} | |
552 | + | |
553 | +//! @brief 全てのブロックと衝突しているか判定 | |
554 | +//! @param RayPos_x 始点 X座標 | |
555 | +//! @param RayPos_y 始点 Y座標 | |
556 | +//! @param RayPos_z 始点 Z座標 | |
557 | +//! @param RayDir_x ベクトル X成分 | |
558 | +//! @param RayDir_y ベクトル Y成分 | |
559 | +//! @param RayDir_z ベクトル Z成分 | |
560 | +//! @param id 当たったブロックのIDを受け取るポインタ (NULL可) | |
561 | +//! @param face 当たったブロックの面番号(0〜5)を受け取るポインタ (NULL可) | |
562 | +//! @param Dist ダミー変数のポインタ(常に 0.0f を返す) | |
563 | +//! @param maxDist 判定を行う最大距離 (0.0 未満指定 不可) | |
564 | +//! @return 当たっている:true 当たっていない:false | |
565 | +//! @warning 始点と ベクトルを間違えないこと。 | |
566 | +//! @warning 使い方は CheckALLBlockIntersectRay()関数 と類似していますが、同関数より高速で低精度です。 | |
567 | +//! @attention レイの始点から裏側になるブロックの面は無視されます。厚さをゼロに変形させた板状のブロックも無視します。 | |
568 | +//! @attention また、レイが複数のブロックに当たる場合は、<b>一番最初に発見した判定</b>を返します。 | |
569 | +bool Collision::CheckALLBlockIntersectDummyRay(float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, int *id, int *face, float *Dist, float maxDist) | |
570 | +{ | |
571 | + if( blockdata == NULL ){ return false; } | |
572 | + if( maxDist <= 0.0f ){ return false; } | |
573 | + | |
574 | + float RayPos2_x = RayPos_x + RayDir_x * maxDist/2; | |
575 | + float RayPos2_y = RayPos_y + RayDir_y * maxDist/2; | |
576 | + float RayPos2_z = RayPos_z + RayDir_z * maxDist/2; | |
577 | + float RayPos3_x = RayPos_x + RayDir_x * maxDist; | |
578 | + float RayPos3_y = RayPos_y + RayDir_y * maxDist; | |
579 | + float RayPos3_z = RayPos_z + RayDir_z * maxDist; | |
580 | + | |
581 | + if( (id == NULL)&&(face == NULL) ){ | |
582 | + for(int i=0; i<MAX_BLOCKS; i++){ | |
583 | + //終了時点 | |
584 | + if( CheckBlockInside(i, RayPos3_x, RayPos3_y, RayPos3_z, true, NULL) == true ){ | |
585 | + *Dist = 0.0f; | |
586 | + return true; | |
587 | + } | |
588 | + | |
589 | + //中間時点 | |
590 | + if( CheckBlockInside(i, RayPos2_x, RayPos2_y, RayPos2_z, true, NULL) == true ){ | |
591 | + *Dist = 0.0f; | |
592 | + return true; | |
593 | + } | |
594 | + } | |
595 | + | |
596 | + *Dist = 0.0f; | |
597 | + return false; | |
598 | + } | |
599 | + | |
600 | + for(int i=0; i<MAX_BLOCKS; i++){ | |
601 | + int surface; | |
602 | + | |
603 | + //開始地点 | |
604 | + CheckBlockInside(i, RayPos_x, RayPos_y, RayPos_z, false, &surface); | |
605 | + | |
606 | + //終了時点 | |
607 | + if( CheckBlockInside(i, RayPos3_x, RayPos3_y, RayPos3_z, true, &surface) == true ){ | |
608 | + if( id != NULL ){ *id = i; } | |
609 | + if( face != NULL ){ *face = surface; } | |
610 | + *Dist = 0.0f; | |
611 | + return true; | |
612 | + } | |
613 | + | |
614 | + //中間時点 | |
615 | + if( CheckBlockInside(i, RayPos2_x, RayPos2_y, RayPos2_z, true, &surface) == true ){ | |
616 | + if( id != NULL ){ *id = i; } | |
617 | + if( face != NULL ){ *face = surface; } | |
618 | + *Dist = 0.0f; | |
619 | + return true; | |
620 | + } | |
621 | + } | |
622 | + | |
623 | + if( id != NULL ){ *id = 0; } | |
624 | + if( face != NULL ){ *face = 0; } | |
625 | + *Dist = 0.0f; | |
626 | + return false; | |
627 | +} | |
628 | + | |
629 | +//! @brief ブロックに沿って移動するベクトルを求める | |
630 | +void Collision::ScratchVector(BlockDataInterface* in_blockdata, int id, int face, float in_vx, float in_vy, float in_vz, float *out_vx, float *out_vy, float *out_vz) | |
631 | +{ | |
632 | + struct blockdata bdata; | |
633 | + in_blockdata->Getdata(&bdata, id); | |
634 | + | |
635 | + D3DXVECTOR3 out; | |
636 | + D3DXVECTOR3 front(in_vx, in_vy, in_vz); | |
637 | + D3DXVECTOR3 normal(bdata.material[face].vx, bdata.material[face].vy, bdata.material[face].vz); | |
638 | + | |
639 | + //D3DXVec3Normalize(&out, &(front - D3DXVec3Dot(&front, &normal) * normal)); | |
640 | + out = (front - D3DXVec3Dot(&front, &normal) * normal); | |
641 | + | |
642 | + *out_vx = out.x; | |
643 | + *out_vy = out.y; | |
644 | + *out_vz = out.z; | |
645 | +} | |
646 | + | |
647 | +//! @brief ブロックに反射するベクトルを求める | |
648 | +void Collision::ReflectVector(BlockDataInterface* in_blockdata, int id, int face, float in_vx, float in_vy, float in_vz, float *out_vx, float *out_vy, float *out_vz) | |
649 | +{ | |
650 | + struct blockdata bdata; | |
651 | + in_blockdata->Getdata(&bdata, id); | |
652 | + | |
653 | + D3DXVECTOR3 out; | |
654 | + D3DXVECTOR3 front(in_vx, in_vy, in_vz); | |
655 | + D3DXVECTOR3 normal(bdata.material[face].vx, bdata.material[face].vy, bdata.material[face].vz); | |
656 | + | |
657 | + //D3DXVec3Normalize(&out, &(front - 2.0f * D3DXVec3Dot(&front, &normal) * normal)); | |
658 | + out = (front - 2.0f * D3DXVec3Dot(&front, &normal) * normal); | |
659 | + | |
660 | + *out_vx = out.x; | |
661 | + *out_vy = out.y; | |
662 | + *out_vz = out.z; | |
663 | +} | |
664 | + | |
665 | + | |
666 | +//! @brief AABBによるあたり判定 | |
667 | +//! @param box1_min_x 物体Aの最少 X座標 | |
668 | +//! @param box1_min_y 物体Aの最少 Y座標 | |
669 | +//! @param box1_min_z 物体Aの最少 Z座標 | |
670 | +//! @param box1_max_x 物体Aの最大 X座標 | |
671 | +//! @param box1_max_y 物体Aの最大 Y座標 | |
672 | +//! @param box1_max_z 物体Aの最大 Z座標 | |
673 | +//! @param box2_min_x 物体Bの最少 X座標 | |
674 | +//! @param box2_min_y 物体Bの最少 Y座標 | |
675 | +//! @param box2_min_z 物体Bの最少 Z座標 | |
676 | +//! @param box2_max_x 物体Bの最大 X座標 | |
677 | +//! @param box2_max_y 物体Bの最大 Y座標 | |
678 | +//! @param box2_max_z 物体Bの最大 Z座標 | |
679 | +//! @return 当たっている:true 当たっていない:false | |
680 | +//! @attention エラーがある場合「当たっていない:false」が返されます。 | |
681 | +bool CollideBoxAABB(float box1_min_x, float box1_min_y, float box1_min_z, float box1_max_x, float box1_max_y, float box1_max_z, float box2_min_x, float box2_min_y, float box2_min_z, float box2_max_x, float box2_max_y, float box2_max_z) | |
682 | +{ | |
683 | + //エラー対策 | |
684 | + if( box1_min_x > box1_max_x ){ return false; } | |
685 | + if( box1_min_y > box1_max_y ){ return false; } | |
686 | + if( box1_min_z > box1_max_z ){ return false; } | |
687 | + if( box2_min_x > box2_max_x ){ return false; } | |
688 | + if( box2_min_y > box2_max_y ){ return false; } | |
689 | + if( box2_min_z > box2_max_z ){ return false; } | |
690 | + | |
691 | + if( | |
692 | + (box1_min_x < box2_max_x)&&(box1_max_x > box2_min_x)&& | |
693 | + (box1_min_y < box2_max_y)&&(box1_max_y > box2_min_y)&& | |
694 | + (box1_min_z < box2_max_z)&&(box1_max_z > box2_min_z) | |
695 | + ){ | |
696 | + return true; | |
697 | + } | |
698 | + | |
699 | + return false; | |
700 | +} | |
701 | + | |
702 | +//! @brief 円柱同士の当たり判定 | |
703 | +//! @param c1_x 円柱1 底辺のx座標 | |
704 | +//! @param c1_y 円柱1 底辺のy座標 | |
705 | +//! @param c1_z 円柱1 底辺のz座標 | |
706 | +//! @param c1_r 円柱1 の半径 | |
707 | +//! @param c1_h 円柱1 の高さ | |
708 | +//! @param c2_x 円柱2 底辺のx座標 | |
709 | +//! @param c2_y 円柱2 底辺のy座標 | |
710 | +//! @param c2_z 円柱2 底辺のz座標 | |
711 | +//! @param c2_r 円柱2 の半径 | |
712 | +//! @param c2_h 円柱2 の高さ | |
713 | +//! @param *angle 円柱1からみた接触角度を受け取るポインタ(NULL可) | |
714 | +//! @param *length 円柱1からみた接触距離を受け取るポインタ(NULL可) | |
715 | +//! @return 当たっている:true 当たっていない:false | |
716 | +bool CollideCylinder(float c1_x, float c1_y, float c1_z, float c1_r, float c1_h, float c2_x, float c2_y, float c2_z, float c2_r, float c2_h, float *angle, float *length) | |
717 | +{ | |
718 | + //先にお手軽な高さで判定 | |
719 | + if( (c1_y < c2_y + c2_h)&&(c1_y + c1_h > c2_y) ){ | |
720 | + | |
721 | + //距離で判定 | |
722 | + float x = c1_x - c2_x; | |
723 | + float z = c1_z - c2_z; | |
724 | + float caser = x*x + z*z; | |
725 | + float minr = (c1_r+c2_r) * (c1_r+c2_r); | |
726 | + if( caser < minr ){ | |
727 | + if( angle != NULL ){ *angle = atan2(z, x); } | |
728 | + if( length != NULL ){ *length = sqrt(minr) - sqrt(caser); } | |
729 | + return true; | |
730 | + } | |
731 | + } | |
732 | + | |
733 | + return false; | |
734 | +} | |
735 | + | |
736 | +//! @brief 球体とレイ(光線)のあたり判定 | |
737 | +//! @param s_x 球体のx座標 | |
738 | +//! @param s_y 球体のy座標 | |
739 | +//! @param s_z 球体のz座標 | |
740 | +//! @param s_r 球体の半径 | |
741 | +//! @param RayPos_x レイの位置(始点)を指定する X座標 | |
742 | +//! @param RayPos_y レイの位置(始点)を指定する Y座標 | |
743 | +//! @param RayPos_z レイの位置(始点)を指定する Z座標 | |
744 | +//! @param RayDir_x レイのベクトルを指定する X成分 | |
745 | +//! @param RayDir_y レイのベクトルを指定する Y成分 | |
746 | +//! @param RayDir_z レイのベクトルを指定する Z成分 | |
747 | +//! @param Dist 当たった球体との距離を受け取るポインタ | |
748 | +//! @param maxDist 判定を行う最大距離 (0.0 未満で無効・無限) | |
749 | +//! @return 当たっている:true 当たっていない:false | |
750 | +//! @warning RayPos(始点)と RayDir(ベクトル)を間違えないこと。 | |
751 | +//! @warning 判定を行う最大距離を指定しないと、パフォーマンスが大幅に低下します。 | |
752 | +bool CollideSphereRay(float s_x, float s_y, float s_z, float s_r, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float *Dist, float maxDist) | |
753 | +{ | |
754 | + if( maxDist > 0.0f ){ | |
755 | + float pmin_x, pmin_y, pmin_z, pmax_x, pmax_y, pmax_z; | |
756 | + | |
757 | + //レイのAABBを作る | |
758 | + pmin_x = RayPos_x + RayDir_x * maxDist; | |
759 | + pmin_y = RayPos_y + RayDir_y * maxDist; | |
760 | + pmin_z = RayPos_z + RayDir_z * maxDist; | |
761 | + pmax_x = pmin_x; | |
762 | + pmax_y = pmin_y; | |
763 | + pmax_z = pmin_z; | |
764 | + if( pmin_x > RayPos_x ){ pmin_x = RayPos_x; } | |
765 | + if( pmin_y > RayPos_y ){ pmin_y = RayPos_y; } | |
766 | + if( pmin_z > RayPos_z ){ pmin_z = RayPos_z; } | |
767 | + if( pmax_x < RayPos_x ){ pmax_x = RayPos_x; } | |
768 | + if( pmax_y < RayPos_y ){ pmax_y = RayPos_y; } | |
769 | + if( pmax_z < RayPos_z ){ pmax_z = RayPos_z; } | |
770 | + | |
771 | + //境界ボックス同士で判定 | |
772 | + if( CollideBoxAABB(s_x - s_r, s_y - s_r, s_z - s_r, s_x + s_r, s_y + s_r, s_z + s_r, pmin_x, pmin_y, pmin_z, pmax_x, pmax_y, pmax_z) == FALSE ){ | |
773 | + return false; | |
774 | + } | |
775 | + } | |
776 | + | |
777 | + D3DXVECTOR3 pCenter(s_x, s_y, s_z); | |
778 | + D3DXVECTOR3 pRayPos(RayPos_x, RayPos_y, RayPos_z); | |
779 | + D3DXVECTOR3 pRayDir(RayDir_x, RayDir_y, RayDir_z); | |
780 | + | |
781 | + //球体とレイの判定 | |
782 | + if( D3DXSphereBoundProbe(&pCenter, s_r, &pRayPos, &pRayDir) == TRUE ){ | |
783 | + if( Dist != NULL ){ | |
784 | + if( maxDist < 0.0f ){ maxDist = s_r * 2; } | |
785 | + | |
786 | + //点とレイ始点の距離 | |
787 | + float x, y, z, d; | |
788 | + x = s_x - RayPos_x; | |
789 | + y = s_y - RayPos_y; | |
790 | + z = s_z - RayPos_z; | |
791 | + d = sqrt(x*x + y*y + z*z); | |
792 | + | |
793 | + //レイ始点が半径より近い(=めり込んでいる) | |
794 | + if( d < s_r ){ | |
795 | + *Dist = 0.0f; | |
796 | + return true; | |
797 | + } | |
798 | + | |
799 | + //点(球体の中心)とレイの最短距離を求める | |
800 | + float MinDist, RayDist, RDist; | |
801 | + //点とレイの最短距離 | |
802 | + MinDist = DistancePosRay(s_x, s_y, s_z, RayPos_x, RayPos_y, RayPos_z, RayDir_x, RayDir_y, RayDir_z, maxDist); | |
803 | + RayDist = sqrt(d*d - MinDist*MinDist); //(レイ始点から)点に最も近づく距離 | |
804 | + RDist = sqrt(s_r*s_r - MinDist*MinDist); //(点半径から)点に最も近づく距離 | |
805 | + | |
806 | + *Dist = RayDist - RDist; //レイ視点最短 - 半径最短 = レイ視点から半径までの最短 | |
807 | + } | |
808 | + return true; | |
809 | + } | |
810 | + | |
811 | + return false; | |
812 | +} | |
813 | + | |
814 | +//! @brief AABBとレイ(光線)のあたり判定 | |
815 | +//! @param box_min_x 物体の最少 X座標 | |
816 | +//! @param box_min_y 物体の最少 Y座標 | |
817 | +//! @param box_min_z 物体の最少 Z座標 | |
818 | +//! @param box_max_x 物体の最大 X座標 | |
819 | +//! @param box_max_y 物体の最大 Y座標 | |
820 | +//! @param box_max_z 物体の最大 Z座標 | |
821 | +//! @param RayPos_x レイの位置(始点)を指定する X座標 | |
822 | +//! @param RayPos_y レイの位置(始点)を指定する Y座標 | |
823 | +//! @param RayPos_z レイの位置(始点)を指定する Z座標 | |
824 | +//! @param RayDir_x レイのベクトルを指定する X成分 | |
825 | +//! @param RayDir_y レイのベクトルを指定する Y成分 | |
826 | +//! @param RayDir_z レイのベクトルを指定する Z成分 | |
827 | +//! @param Dist 当たったAABBとの距離を受け取るポインタ | |
828 | +//! @param maxDist 判定を行う最大距離 (0.0 未満で無効・無限) | |
829 | +//! @return 当たっている:true 当たっていない:false | |
830 | +//! @warning RayPos(始点)と RayDir(ベクトル)を間違えないこと。 | |
831 | +//! @warning 判定を行う最大距離を指定しないと、パフォーマンスが大幅に低下します。 | |
832 | +//! @todo 当たった距離として近似値を返すので、正確な値を求める。 | |
833 | +bool CollideAABBRay(float box_min_x, float box_min_y, float box_min_z, float box_max_x, float box_max_y, float box_max_z, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float *Dist, float maxDist) | |
834 | +{ | |
835 | + if( box_min_x > box_max_x ){ return false; } | |
836 | + if( box_min_y > box_max_y ){ return false; } | |
837 | + if( box_min_z > box_max_z ){ return false; } | |
838 | + | |
839 | + if( maxDist > 0.0f ){ | |
840 | + float pmin_x, pmin_y, pmin_z, pmax_x, pmax_y, pmax_z; | |
841 | + | |
842 | + //レイのAABBを作る | |
843 | + pmin_x = RayPos_x + RayDir_x * maxDist; | |
844 | + pmin_y = RayPos_y + RayDir_y * maxDist; | |
845 | + pmin_z = RayPos_z + RayDir_z * maxDist; | |
846 | + pmax_x = pmin_x; | |
847 | + pmax_y = pmin_y; | |
848 | + pmax_z = pmin_z; | |
849 | + if( pmin_x > RayPos_x ){ pmin_x = RayPos_x; } | |
850 | + if( pmin_y > RayPos_y ){ pmin_y = RayPos_y; } | |
851 | + if( pmin_z > RayPos_z ){ pmin_z = RayPos_z; } | |
852 | + if( pmax_x < RayPos_x ){ pmax_x = RayPos_x; } | |
853 | + if( pmax_y < RayPos_y ){ pmax_y = RayPos_y; } | |
854 | + if( pmax_z < RayPos_z ){ pmax_z = RayPos_z; } | |
855 | + | |
856 | + //境界ボックス同士で判定 | |
857 | + if( CollideBoxAABB(box_min_x, box_min_y, box_min_z, box_max_x, box_max_y, box_max_z, pmin_x, pmin_y, pmin_z, pmax_x, pmax_y, pmax_z) == FALSE ){ | |
858 | + return false; | |
859 | + } | |
860 | + } | |
861 | + | |
862 | + D3DXVECTOR3 pMin(box_min_x, box_min_y, box_min_z); | |
863 | + D3DXVECTOR3 pMax(box_max_x, box_max_y, box_max_z); | |
864 | + D3DXVECTOR3 pRayPos(RayPos_x, RayPos_y, RayPos_z); | |
865 | + D3DXVECTOR3 pRayDir(RayDir_x, RayDir_y, RayDir_z); | |
866 | + | |
867 | + //AABBとレイ(光線)の判定 | |
868 | + if( D3DXBoxBoundProbe(&pMin, &pMax, &pRayPos, &pRayDir) == TRUE ){ | |
869 | + if( Dist != NULL ){ | |
870 | + float x, y, z; | |
871 | + float d, mind; | |
872 | + | |
873 | + //AABBの各頂点から距離を算出して、一番近い距離を「当たった距離」とする。 | |
874 | + // ちゃんと計算しろよ >< | |
875 | + | |
876 | + x = box_min_x - RayPos_x; | |
877 | + y = box_min_y - RayPos_y; | |
878 | + z = box_min_z - RayPos_z; | |
879 | + d = sqrt(x*x + y*y + z*z); | |
880 | + mind = d; | |
881 | + | |
882 | + x = box_max_x - RayPos_x; | |
883 | + y = box_min_y - RayPos_y; | |
884 | + z = box_min_z - RayPos_z; | |
885 | + d = sqrt(x*x + y*y + z*z); | |
886 | + if( d < mind ){ mind = d; } | |
887 | + | |
888 | + x = box_min_x - RayPos_x; | |
889 | + y = box_max_y - RayPos_y; | |
890 | + z = box_min_z - RayPos_z; | |
891 | + d = sqrt(x*x + y*y + z*z); | |
892 | + if( d < mind ){ mind = d; } | |
893 | + | |
894 | + x = box_max_x - RayPos_x; | |
895 | + y = box_max_y - RayPos_y; | |
896 | + z = box_min_z - RayPos_z; | |
897 | + d = sqrt(x*x + y*y + z*z); | |
898 | + if( d < mind ){ mind = d; } | |
899 | + | |
900 | + x = box_min_x - RayPos_x; | |
901 | + y = box_min_y - RayPos_y; | |
902 | + z = box_max_z - RayPos_z; | |
903 | + d = sqrt(x*x + y*y + z*z); | |
904 | + if( d < mind ){ mind = d; } | |
905 | + | |
906 | + x = box_max_x - RayPos_x; | |
907 | + y = box_min_y - RayPos_y; | |
908 | + z = box_max_z - RayPos_z; | |
909 | + d = sqrt(x*x + y*y + z*z); | |
910 | + if( d < mind ){ mind = d; } | |
911 | + | |
912 | + x = box_min_x - RayPos_x; | |
913 | + y = box_max_y - RayPos_y; | |
914 | + z = box_max_z - RayPos_z; | |
915 | + d = sqrt(x*x + y*y + z*z); | |
916 | + if( d < mind ){ mind = d; } | |
917 | + | |
918 | + x = box_max_x - RayPos_x; | |
919 | + y = box_max_y - RayPos_y; | |
920 | + z = box_max_z - RayPos_z; | |
921 | + d = sqrt(x*x + y*y + z*z); | |
922 | + if( d < mind ){ mind = d; } | |
923 | + | |
924 | + *Dist = mind; | |
925 | + } | |
926 | + return true; | |
927 | + } | |
928 | + | |
929 | + return false; | |
930 | +} | |
931 | + | |
932 | +//! @brief 点とレイの最短距離を求める | |
933 | +//! @param Pos_x 点のX座標 | |
934 | +//! @param Pos_y 点のY座標 | |
935 | +//! @param Pos_z 点のZ座標 | |
936 | +//! @param RayPos_x レイの位置(始点)を指定する X座標 | |
937 | +//! @param RayPos_y レイの位置(始点)を指定する Y座標 | |
938 | +//! @param RayPos_z レイの位置(始点)を指定する Z座標 | |
939 | +//! @param RayDir_x レイのベクトルを指定する X成分 | |
940 | +//! @param RayDir_y レイのベクトルを指定する Y成分 | |
941 | +//! @param RayDir_z レイのベクトルを指定する Z成分 | |
942 | +//! @param maxDist 判定を行う最大距離 | |
943 | +//! @return 最短距離 | |
944 | +//! @warning RayPos(始点)と RayDir(ベクトル)を間違えないこと。 | |
945 | +float DistancePosRay(float Pos_x, float Pos_y, float Pos_z, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float maxDist) | |
946 | +{ | |
947 | + float x1, y1, z1; | |
948 | + float x2, y2, z2; | |
949 | + D3DXVECTOR3 in1, in2, out; | |
950 | + | |
951 | + x1 = Pos_x - RayPos_x; | |
952 | + y1 = Pos_y - RayPos_y; | |
953 | + z1 = Pos_z - RayPos_z; | |
954 | + x2 = RayDir_x * maxDist; | |
955 | + y2 = RayDir_y * maxDist; | |
956 | + z2 = RayDir_z * maxDist; | |
957 | + | |
958 | + in1 = D3DXVECTOR3(x1, y1, z1); | |
959 | + in2 = D3DXVECTOR3(x2, y2, z2); | |
960 | + | |
961 | + D3DXVec3Cross(&out, &in1, &in2); | |
962 | + | |
963 | + return sqrt(out.x*out.x + out.y*out.y + out.z*out.z) / maxDist; | |
964 | +} | |
965 | + | |
966 | +//! @brief 線分と線分の当たり判定(2D) | |
967 | +//! @param A1x 線分Aの始点 X座標 | |
968 | +//! @param A1y 線分Aの始点 Y座標 | |
969 | +//! @param A2x 線分Aの終点 X座標 | |
970 | +//! @param A2y 線分Aの終点 Y座標 | |
971 | +//! @param B1x 線分Bの始点 X座標 | |
972 | +//! @param B1y 線分Bの始点 Y座標 | |
973 | +//! @param B2x 線分Bの終点 X座標 | |
974 | +//! @param B2y 線分Bの終点 Y座標 | |
975 | +//! @param out_x 交点の X座標 を受け取るポインタ(NULL可) | |
976 | +//! @param out_y 交点の Y座標 を受け取るポインタ(NULL可) | |
977 | +//! @return 交差する:true 交差しない:false | |
978 | +bool Collide2DLine(int A1x, int A1y, int A2x, int A2y, int B1x, int B1y, int B2x, int B2y, int *out_x, int *out_y) | |
979 | +{ | |
980 | + //線分のベクトルを求める | |
981 | + int Avx = A2x - A1x; | |
982 | + int Avy = A2y - A1y; | |
983 | + int Bvx = B2x - B1x; | |
984 | + int Bvy = B2y - B1y; | |
985 | + | |
986 | + float v1_v2 = (float)(Avx * Bvy - Avy * Bvx); //外積 | |
987 | + if( v1_v2 == 0.0f ){ | |
988 | + return false; //平行 | |
989 | + } | |
990 | + | |
991 | + float vx = (float)(B1x - A1x); | |
992 | + float vy = (float)(B1y - A1y); | |
993 | + float v_v1 = vx * Avy - vy * Avx; //外積 | |
994 | + float v_v2 = vx * Bvy - vy * Bvx; //外積 | |
995 | + float t1 = v_v2 / v1_v2; | |
996 | + float t2 = v_v1 / v1_v2; | |
997 | + | |
998 | + if( (t1 <= 0)||(1 <= t1)||(t2 <= 0)||(1 <= t2) ){ | |
999 | + return false; //交差してない | |
1000 | + } | |
1001 | + | |
1002 | + if( out_x != NULL ){ *out_x = (int)(A1x + Avx * t1); } | |
1003 | + if( out_y != NULL ){ *out_y = (int)(A1y + Avy * t1); } | |
1004 | + | |
1005 | + return true; | |
1006 | +} | |
1007 | + | |
1008 | +//! @brief 四角形に収まる線分を求める(2D) | |
1009 | +//! @param line_x1 線分の始点 X座標 | |
1010 | +//! @param line_y1 線分の始点 Y座標 | |
1011 | +//! @param line_x2 線分の終点 X座標 | |
1012 | +//! @param line_y2 線分の終点 Y座標 | |
1013 | +//! @param box_x1 四角形の左上 X座標 | |
1014 | +//! @param box_y1 四角形の左上 Y座標 | |
1015 | +//! @param box_x2 四角形の右下 X座標 | |
1016 | +//! @param box_y2 四角形の右下 Y座標 | |
1017 | +//! @param out_line_x1 四角形に収まる 線分の始点 X座標 を受け取るポインタ | |
1018 | +//! @param out_line_y1 四角形に収まる 線分の始点 Y座標 を受け取るポインタ | |
1019 | +//! @param out_line_x2 四角形に収まる 線分の終点 X座標 を受け取るポインタ | |
1020 | +//! @param out_line_y2 四角形に収まる 線分の終点 Y座標 を受け取るポインタ | |
1021 | +//! @return 有効(描画する):true 無効(描画しない):false | |
1022 | +//! @warning 引数は必ず「box_x1 < box_x2」かつ「box_x1 < box_x2」にすること | |
1023 | +//! @note 簡易レーダーのマップ表示用 | |
1024 | +bool Get2DLineInBox(int line_x1, int line_y1, int line_x2, int line_y2, int box_x1, int box_y1, int box_x2, int box_y2, int *out_line_x1, int *out_line_y1, int *out_line_x2, int *out_line_y2) | |
1025 | +{ | |
1026 | + //四角形指定が異常 | |
1027 | + if( (box_x1 >= box_x2)||(box_x1 >= box_x2) ){ return false; } | |
1028 | + | |
1029 | + //上下左右の空間にあるなら、的外れ | |
1030 | + if( (line_x1 < box_x1)&&(line_x2 < box_x1) ){ return false; } | |
1031 | + if( (line_y1 < box_y1)&&(line_y2 < box_y1) ){ return false; } | |
1032 | + if( (box_x2 < line_x1)&&(box_x2 < line_x2) ){ return false; } | |
1033 | + if( (box_y2 < line_x1)&&(box_y2 < line_x2) ){ return false; } | |
1034 | + | |
1035 | + //既に四角形に収まる | |
1036 | + if( (box_x1 <= line_x1)&&(line_x1 <= box_x2)&&(box_y1 <= line_y1)&&(line_y1 <= box_y2) ){ | |
1037 | + if( (box_x1 <= line_x2)&&(line_x2 <= box_x2)&&(box_y1 <= line_y2)&&(line_y2 <= box_y2) ){ | |
1038 | + *out_line_x1 = line_x1; | |
1039 | + *out_line_y1 = line_y1; | |
1040 | + *out_line_x2 = line_x2; | |
1041 | + *out_line_y2 = line_y2; | |
1042 | + return true; | |
1043 | + } | |
1044 | + } | |
1045 | + | |
1046 | + int x, y; | |
1047 | + | |
1048 | + //上辺 | |
1049 | + if( Collide2DLine(box_x1, box_y1, box_x2, box_y1, line_x1, line_y1, line_x2, line_y2, &x, &y) == true ){ | |
1050 | + //始点が四角形の内側なら終点を、違えば(=終点が内側)始点を書き換える。 | |
1051 | + if( (box_x1 <= line_x1)&&(line_x1 <= box_x2)&&(box_y1 <= line_y1)&&(line_y1 <= box_y2) ){ | |
1052 | + line_x2 = x; | |
1053 | + line_y2 = y; | |
1054 | + } | |
1055 | + else{ | |
1056 | + line_x1 = x; | |
1057 | + line_y1 = y; | |
1058 | + } | |
1059 | + } | |
1060 | + //右辺 | |
1061 | + if( Collide2DLine(box_x2, box_y1, box_x2, box_y2, line_x1, line_y1, line_x2, line_y2, &x, &y) == true ){ | |
1062 | + //始点が四角形の内側なら終点を、違えば(=終点が内側)始点を書き換える。 | |
1063 | + if( (box_x1 <= line_x1)&&(line_x1 <= box_x2)&&(box_y1 <= line_y1)&&(line_y1 <= box_y2) ){ | |
1064 | + line_x2 = x; | |
1065 | + line_y2 = y; | |
1066 | + } | |
1067 | + else{ | |
1068 | + line_x1 = x; | |
1069 | + line_y1 = y; | |
1070 | + } | |
1071 | + } | |
1072 | + //下辺 | |
1073 | + if( Collide2DLine(box_x2, box_y2, box_x1, box_y2, line_x1, line_y1, line_x2, line_y2, &x, &y) == true ){ | |
1074 | + //始点が四角形の内側なら終点を、違えば(=終点が内側)始点を書き換える。 | |
1075 | + if( (box_x1 <= line_x1)&&(line_x1 <= box_x2)&&(box_y1 <= line_y1)&&(line_y1 <= box_y2) ){ | |
1076 | + line_x2 = x; | |
1077 | + line_y2 = y; | |
1078 | + } | |
1079 | + else{ | |
1080 | + line_x1 = x; | |
1081 | + line_y1 = y; | |
1082 | + } | |
1083 | + } | |
1084 | + //左辺 | |
1085 | + if( Collide2DLine(box_x1, box_y2, box_x1, box_y1, line_x1, line_y1, line_x2, line_y2, &x, &y) == true ){ | |
1086 | + //始点が四角形の内側なら終点を、違えば(=終点が内側)始点を書き換える。 | |
1087 | + if( (box_x1 <= line_x1)&&(line_x1 <= box_x2)&&(box_y1 <= line_y1)&&(line_y1 <= box_y2) ){ | |
1088 | + line_x2 = x; | |
1089 | + line_y2 = y; | |
1090 | + } | |
1091 | + else{ | |
1092 | + line_x1 = x; | |
1093 | + line_y1 = y; | |
1094 | + } | |
1095 | + } | |
1096 | + | |
1097 | + //改めて四角形に収まるか確認 | |
1098 | + if( (box_x1 <= line_x1)&&(line_x1 <= box_x2)&&(box_y1 <= line_y1)&&(line_y1 <= box_y2) ){ | |
1099 | + if( (box_x1 <= line_x2)&&(line_x2 <= box_x2)&&(box_y1 <= line_y2)&&(line_y2 <= box_y2) ){ | |
1100 | + *out_line_x1 = line_x1; | |
1101 | + *out_line_y1 = line_y1; | |
1102 | + *out_line_x2 = line_x2; | |
1103 | + *out_line_y2 = line_y2; | |
1104 | + return true; | |
1105 | + } | |
1106 | + } | |
1107 | + | |
1108 | + return false; | |
1109 | +} | |
1110 | + | |
1111 | +//! @brief 観測点から対象点への 距離判定・角度算出 | |
1112 | +//! @param pos_x 観測点のX座標 | |
1113 | +//! @param pos_y 観測点のY座標 | |
1114 | +//! @param pos_z 観測点のZ座標 | |
1115 | +//! @param rx 観測点の水平角度 | |
1116 | +//! @param ry 観測点の垂直角度 | |
1117 | +//! @param target_x 対象点のX座標 | |
1118 | +//! @param target_y 対象点のY座標 | |
1119 | +//! @param target_z 対象点のZ座標 | |
1120 | +//! @param checkdist 判定距離(0.0f以下で判定無効) | |
1121 | +//! @param out_rx 対象点への水平角度(π〜-π)を受け取るポインタ(NULL可) | |
1122 | +//! @param out_ry 対象点への垂直角度を受け取るポインタ(NULL可) | |
1123 | +//! @param out_dist2 対象点への距離<b>の二乗</b>を受け取るポインタ(NULL可) | |
1124 | +//! @return 成功:true 失敗:false | |
1125 | +//! @warning out_dist2は距離の<b>二乗</b>です。必要に応じて改めて sqrt()関数 などを用いてください。 | |
1126 | +//! @attention 引数 checkdist に有効な距離を与えた場合は、観測点から対象点への距離判定も行います。指定された距離より離れている場合、角度を計算せずに false を返します。 | |
1127 | +//! @attention 逆に、引数 checkdist に0.0f以下を与えた場合、距離による判定を行いません。関数は常に true を返します。 | |
1128 | +bool CheckTargetAngle(float pos_x, float pos_y, float pos_z, float rx, float ry, float target_x, float target_y, float target_z, float checkdist, float *out_rx, float *out_ry, float *out_dist2) | |
1129 | +{ | |
1130 | + float x, y, z; | |
1131 | + float dist2 = 0.0f; | |
1132 | + float angleX, angleY; | |
1133 | + | |
1134 | + x = target_x - pos_x; | |
1135 | + y = target_y - pos_y; | |
1136 | + z = target_z - pos_z; | |
1137 | + | |
1138 | + if( (checkdist > 0.0f)||(out_dist2 != NULL) ){ | |
1139 | + dist2 = (x*x + y*y + z*z); | |
1140 | + } | |
1141 | + | |
1142 | + if( checkdist > 0.0f ){ | |
1143 | + if( dist2 > checkdist * checkdist ){ | |
1144 | + return false; | |
1145 | + } | |
1146 | + } | |
1147 | + | |
1148 | + if( out_rx != NULL ){ | |
1149 | + angleX = atan2(z, x) - rx; | |
1150 | + for(; angleX > (float)M_PI; angleX -= (float)M_PI*2){} | |
1151 | + for(; angleX < (float)M_PI*-1; angleX += (float)M_PI*2){} | |
1152 | + | |
1153 | + *out_rx = angleX; | |
1154 | + } | |
1155 | + if( out_ry != NULL ){ | |
1156 | + angleY = atan2(y, sqrt(x*x + z*z)) - ry; | |
1157 | + | |
1158 | + *out_ry = angleY; | |
1159 | + } | |
1160 | + if( out_dist2 != NULL ){ *out_dist2 = dist2; } | |
1161 | + | |
1162 | + return true; | |
1163 | +} | |
\ No newline at end of file |
@@ -0,0 +1,233 @@ | ||
1 | +//! @file gamemain.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 GAMEMAIN_H | |
33 | +#define GAMEMAIN_H | |
34 | + | |
35 | +#define ENABLE_DEBUGCONSOLE //!< @brief デバック用コンソールの有効化(コメント化で機能無効) | |
36 | + | |
37 | +#define MAINMENU_X 280 //!< メニューの表示 X座標(左上基準) | |
38 | +#define MAINMENU_Y 140 //!< メニューの表示 Y座標(〃) | |
39 | +#define TOTAL_MENUITEMS 8 //!< メニュー1画面に表示するミッション数 | |
40 | +#define MAINMENU_H (TOTAL_MENUITEMS+2)*30 + 25 //!< メニューの表示サイズ・高さ | |
41 | + | |
42 | +#define HUDA_WEAPON_POSX (SCREEN_WIDTH - 255) //!< 武器情報を表示する領域・X座標 | |
43 | +#define HUDA_WEAPON_POSY (SCREEN_HEIGHT - 98) //!< 武器情報を表示する領域・Y座標 | |
44 | +#define HUDA_WEAPON_SIZEW 8 //!< 武器情報を表示する領域・横サイズ(32ピクセルの配置個数) | |
45 | +#define HUDA_WEAPON_SIZEH 3 //!< 武器情報を表示する領域・縦サイズ(32ピクセルの配置個数) | |
46 | + | |
47 | +#define VIEW_HEIGHT 19.0f //!< 視点の高さ | |
48 | +#define VIEWANGLE_NORMAL ((float)M_PI/180*65) //!< 視野角 標準 | |
49 | +#define VIEWANGLE_SCOPE_1 ((float)M_PI/180*30) //!< 視野角 スコープ1 | |
50 | +#define VIEWANGLE_SCOPE_2 ((float)M_PI/180*15) //!< 視野角 スコープ2 | |
51 | + | |
52 | +#define TOTAL_EVENTLINE 3 //!< イベントのライン数 | |
53 | +#define TOTAL_EVENTENTRYPOINT_0 -100 //!< ライン 0 の開始認識番号 | |
54 | +#define TOTAL_EVENTENTRYPOINT_1 -110 //!< ライン 1 の開始認識番号 | |
55 | +#define TOTAL_EVENTENTRYPOINT_2 -120 //!< ライン 2 の開始認識番号 | |
56 | + | |
57 | +#define TOTAL_EVENTENT_SHOWMESSEC 5.0f //!< イベントメッセージを表示する秒数 | |
58 | + | |
59 | +#ifdef ENABLE_DEBUGCONSOLE | |
60 | + #define MAX_CONSOLELEN 45 //!< デバック用コンソールの文字数(行) | |
61 | + #define MAX_CONSOLELINES 9 //!< デバック用コンソールの行数 | |
62 | + #define CONSOLE_PROMPT ">" //!< デバック用コンソールのプロンプト | |
63 | +#endif | |
64 | + | |
65 | +#ifndef H_LAYERLEVEL | |
66 | + #define H_LAYERLEVEL 3 //!< Select include file. | |
67 | +#endif | |
68 | +#include "main.h" | |
69 | + | |
70 | +int InitGame(HWND hWnd); | |
71 | + | |
72 | +//! ゲームの状態を受け渡しする構造体 | |
73 | +struct GameInfo{ | |
74 | + bool selectaddon; //!< addonを選択 | |
75 | + int selectmission_id; //!< 選択されたミッション | |
76 | + bool missioncomplete; //!< ミッション完了 | |
77 | + unsigned int framecnt; //!< フレーム数 | |
78 | + int fire; //!< 射撃回数 | |
79 | + int ontarget; //!< 命中数 | |
80 | + int kill; //!< 倒した敵の数 | |
81 | + int headshot; //!< 敵の頭部に命中した数 | |
82 | +}; | |
83 | + | |
84 | +#ifdef ENABLE_DEBUGCONSOLE | |
85 | +//! コンソールを管理する構造体 | |
86 | +struct ConsoleData{ | |
87 | + int color; //!< 色 | |
88 | + char textdata[MAX_CONSOLELEN]; //!< 文字列 | |
89 | +}; | |
90 | +#endif | |
91 | + | |
92 | +//! @brief オープニング画面管理クラス | |
93 | +//! @details オープニング画面を管理します。 | |
94 | +class opening : public D3Dscene | |
95 | +{ | |
96 | + //int opening_banner; //!< オープニングで表示するテクスチャID | |
97 | + void Render3D(); | |
98 | + void Render2D(); | |
99 | + | |
100 | +public: | |
101 | + opening(); | |
102 | + ~opening(); | |
103 | + int Create(); | |
104 | + void Process(); | |
105 | + void Destroy(); | |
106 | +}; | |
107 | + | |
108 | +//! @brief メニュー画面管理クラス | |
109 | +//! @details メニュー画面を管理します。 | |
110 | +class mainmenu : public D3Dscene | |
111 | +{ | |
112 | + int mainmenu_mouseX; //!< メニュー画面マウスX座標 | |
113 | + int mainmenu_mouseY; //!< メニュー画面マウスY座標 | |
114 | + int mainmenu_scrollitems_official; //!< メニュー画面のスクロールしたアイテム数 | |
115 | + int mainmenu_scrollitems_addon; //!< メニュー画面のスクロールしたアイテム数 | |
116 | + float mainmenu_scrollbar_official_height; //!< メニュー画面のスクロールバーの高さ | |
117 | + float mainmenu_scrollbar_official_scale; //!< メニュー画面のスクロールバーの目盛 | |
118 | + int mainmenu_scrollbar_official_y; //!< メニュー画面のスクロールバーのY座標 | |
119 | + float mainmenu_scrollbar_addon_height; //!< メニュー画面のスクロールバーの高さ | |
120 | + float mainmenu_scrollbar_addon_scale; //!< メニュー画面のスクロールバーの目盛 | |
121 | + int mainmenu_scrollbar_addon_y; //!< メニュー画面のスクロールバーのY座標 | |
122 | + bool mainmenu_scrollbar_flag; //!< メニュー画面のスクロールバーを操作中を示すフラグ | |
123 | + int gametitle; //!< ゲームタイトル画像 | |
124 | + void Render3D(); | |
125 | + void Render2D(); | |
126 | + | |
127 | +public: | |
128 | + mainmenu(); | |
129 | + ~mainmenu(); | |
130 | + int Create(); | |
131 | + void Input(); | |
132 | + void Process(); | |
133 | + void Destroy(); | |
134 | +}; | |
135 | + | |
136 | +//! @brief ブリーフィング画面管理クラス | |
137 | +//! @details ブリーフィング画面を管理します。 | |
138 | +class briefing : public D2Dscene | |
139 | +{ | |
140 | + bool TwoTexture; //!< ブリーフィング画像を2枚使用 | |
141 | + int TextureA; //!< ブリーフィング画像A | |
142 | + int TextureB; //!< ブリーフィング画像B | |
143 | + void Render2D(); | |
144 | + | |
145 | +public: | |
146 | + briefing(); | |
147 | + ~briefing(); | |
148 | + int Create(); | |
149 | + void Destroy(); | |
150 | +}; | |
151 | + | |
152 | +//! @brief メインゲーム画面管理クラス | |
153 | +//! @details メインゲーム画面を管理します。 | |
154 | +class maingame : public D3Dscene | |
155 | +{ | |
156 | + //class EventControl Event[TOTAL_EVENTLINE]; //!< イベント制御クラス | |
157 | + float mouse_rx; //!< マウスによる水平軸角度 | |
158 | + float mouse_ry; //!< マウスによる垂直軸角度 | |
159 | + float view_rx; //!< マウス角度とカメラ角度の差(水平軸) | |
160 | + float view_ry; //!< マウス角度とカメラ角度の差(垂直軸) | |
161 | + bool ShowInfo_Debugmode; //!< 座標などを表示するデバックモード | |
162 | + bool Camera_Debugmode; //!< カメラデバックモード | |
163 | + bool tag; //!< オブジェクトのタグを表示 | |
164 | + bool radar; //!< 簡易レーダー表示 | |
165 | + bool wireframe; //!< マップをワイヤーフレーム表示 | |
166 | + bool CenterLine; //!< 3D空間に中心線を表示 | |
167 | + bool Camera_F1mode; //!< カメラF1モード | |
168 | + int Camera_F2mode; //!< カメラF2モード | |
169 | + bool Camera_HOMEmode; //!< カメラHOMEモード | |
170 | + bool Cmd_F5; //!< 裏技F5モード | |
171 | + int InvincibleID; //!< 無敵な人の判定 | |
172 | + bool PlayerAI; //!< プレイヤー操作をAIに委ねる | |
173 | + bool AIstop; //!< AI処理を停止する | |
174 | + bool AINoFight; //!< AIが非戦闘化する(戦わない) | |
175 | + int start_framecnt; //!< メインゲーム開始時のカウント | |
176 | + int end_framecnt; //!< メインゲーム終了のカウント | |
177 | + int message_id; //!< 表示中のイベントメッセージ番号 | |
178 | + int message_cnt; //!< 表示中のイベントメッセージカウント | |
179 | + bool redflash_flag; //!< レッドフラッシュ描画フラグ | |
180 | + int time; //!< timer | |
181 | + int time_input; //!< 入力取得の処理時間 | |
182 | + int time_process_object; //!< 基本オブジェクトの処理時間 | |
183 | + int time_process_ai; //!< AIの処理時間 | |
184 | + int time_process_event; //!< イベントの処理時間 | |
185 | + int time_sound; //!< サウンドの処理時間 | |
186 | + int time_render; //!< 描画の処理時間 | |
187 | + GameInfo MainGameInfo; //!< リザルト用管理クラス | |
188 | + bool CheckInputControl(int CheckKey, int mode); | |
189 | + void Render3D(); | |
190 | + void Render2D(); | |
191 | + bool 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); | |
192 | + void RenderRadar(); | |
193 | + | |
194 | +#ifdef ENABLE_DEBUGCONSOLE | |
195 | + bool Show_Console; //!< デバック用コンソールを表示 | |
196 | + ConsoleData *InfoConsoleData; //!< デバック用コンソールデータ(表示済み) | |
197 | + ConsoleData *InputConsoleData; //!< デバック用コンソールデータ(入力中) | |
198 | + char NewCommand[MAX_CONSOLELEN]; //!< 新たに入力された未処理のコマンド | |
199 | + bool ScreenShot; //!< SSを撮影する | |
200 | + void AddInfoConsole(int color, char *str); | |
201 | + void ConsoleInputText(char inchar); | |
202 | + void ConsoleDeleteText(); | |
203 | + bool GetCommandNum(char *cmd, int *num); | |
204 | + void InputConsole(); | |
205 | + void ProcessConsole(); | |
206 | + void RenderConsole(); | |
207 | +#endif | |
208 | + | |
209 | +public: | |
210 | + maingame(); | |
211 | + ~maingame(); | |
212 | + int Create(); | |
213 | + void Input(); | |
214 | + void Process(); | |
215 | + void Sound(); | |
216 | + void Destroy(); | |
217 | +}; | |
218 | + | |
219 | +//! @brief リザルト画面管理クラス | |
220 | +//! @details リザルト(結果表示)画面を管理します。 | |
221 | +class result : public D2Dscene | |
222 | +{ | |
223 | + void Render2D(); | |
224 | + | |
225 | +public: | |
226 | + result(); | |
227 | + ~result(); | |
228 | +}; | |
229 | + | |
230 | +void InitScreen(opening *Opening, mainmenu *MainMenu, briefing *Briefing, maingame *MainGame, result *Result); | |
231 | +void ProcessScreen(HWND hWnd, opening *Opening, mainmenu *MainMenu, briefing *Briefing, maingame *MainGame, result *Result, unsigned int framecnt); | |
232 | + | |
233 | +#endif | |
\ No newline at end of file |
@@ -0,0 +1,64 @@ | ||
1 | +//! @file event.h | |
2 | +//! @brief EventControlクラスの宣言 | |
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 EVENT_H | |
33 | +#define EVENT_H | |
34 | + | |
35 | +#define TOTAL_EVENTFRAMESTEP 6 //!< 1フレーム中に1ラインあたり実行するステップ数 | |
36 | +#define DISTANCE_CHECKPOINT 25.0f //!< 「到着待ち」「ケース待ち」の判定距離 | |
37 | + | |
38 | +#ifndef H_LAYERLEVEL | |
39 | + #define H_LAYERLEVEL 3 //!< Select include file. | |
40 | +#endif | |
41 | +#include "main.h" | |
42 | + | |
43 | +//! @brief イベントを処理するクラス | |
44 | +//! @details ミッションのイベントポイントを処理します。 | |
45 | +//! @details このクラスは1つのイベント処理(流れ)に専念します。複数のイベントを並列に処理させる場合は、このクラスのオブジェクトを複数呼び出す必要があります。(例えば3つ同時に処理させる場合、このクラスのオブジェクトを3つ作成してください。) | |
46 | +class EventControl | |
47 | +{ | |
48 | + class PointDataInterface *Point; //!< PointDataInterfaceクラスのポインタ | |
49 | + class ObjectManager *ObjMgr; //!< ObjectManagerクラスのポインタ | |
50 | + signed char nextp4; //!< 次に処理するP4:認識番号 | |
51 | + int waitcnt; //!< 時間待ち用カウント | |
52 | + | |
53 | + bool CheckHaveCase(human *in_human); | |
54 | + | |
55 | +public: | |
56 | + EventControl(PointDataInterface *in_Point = NULL, ObjectManager *in_ObjMgr = NULL); | |
57 | + ~EventControl(); | |
58 | + void SetClass(PointDataInterface *in_Point, ObjectManager *in_ObjMgr); | |
59 | + void Reset(signed char EntryP4); | |
60 | + signed char GetNextP4(); | |
61 | + int Execution(int *endcnt, bool *complete, int *MessageID, bool *SetMessageID); | |
62 | +}; | |
63 | + | |
64 | +#endif | |
\ No newline at end of file |
@@ -0,0 +1,87 @@ | ||
1 | +//! @file collision.h | |
2 | +//! @brief Collisionクラスの宣言 | |
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 COLLISION_H | |
33 | +#define COLLISION_H | |
34 | + | |
35 | +#ifndef H_LAYERLEVEL | |
36 | + #define H_LAYERLEVEL 2 //!< Select include file. | |
37 | +#endif | |
38 | +#include "main.h" | |
39 | + | |
40 | +#pragma warning(disable:4819) //VC++警告防止 | |
41 | +#include <d3dx9math.h> | |
42 | +#pragma warning(default:4819) | |
43 | + | |
44 | +#pragma comment(lib, "d3dx9.lib") | |
45 | + | |
46 | +//! @brief 当たり判定を行うクラス | |
47 | +//! @details マップとして使用されるブロックデータへの当たり判定(追突検出)を行います。 | |
48 | +//! @details 内部ではDirectX 9を使用しています。 | |
49 | +class Collision | |
50 | +{ | |
51 | + class BlockDataInterface* blockdata; //!< 読み込んだブロックデータが格納されたクラスへのポインタ | |
52 | + D3DXPLANE bdata_plane[MAX_BLOCKS][6][2]; //!< 各ブロックの面情報 | |
53 | + float *bmin_x; //!< 各ブロック X座標の最大値 | |
54 | + float *bmin_y; //!< 各ブロック Y座標の最大値 | |
55 | + float *bmin_z; //!< 各ブロック Z座標の最大値 | |
56 | + float *bmax_x; //!< 各ブロック X座標の最小値 | |
57 | + float *bmax_y; //!< 各ブロック Y座標の最小値 | |
58 | + float *bmax_z; //!< 各ブロック Z座標の最小値 | |
59 | + bool *BoardBlock; //!< 各ブロック が厚さ0で板状になっているか | |
60 | + int *bdata_worldgroup; //!< 空間分割のグループ | |
61 | + | |
62 | +public: | |
63 | + Collision(); | |
64 | + ~Collision(); | |
65 | + int InitCollision(BlockDataInterface* in_blockdata); | |
66 | + void GetBlockPosMINMAX(struct blockdata data, float *min_x, float *min_y, float *min_z, float *max_x, float *max_y, float *max_z); | |
67 | + int GetWorldGroup(float x, float z); | |
68 | + bool CheckBlockInside(int blockid, float x, float y, float z, bool worldgroup, int *planeid); | |
69 | + bool CheckALLBlockInside(float x, float y, float z); | |
70 | + bool CheckBlockIntersectRay(int blockid, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, int *face, float *Dist, float maxDist); | |
71 | + bool CheckALLBlockIntersectRay(float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, int *id, int *face, float *Dist, float maxDist); | |
72 | + bool CheckALLBlockIntersectDummyRay(float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, int *id, int *face, float *Dist, float maxDist); | |
73 | + void ScratchVector(BlockDataInterface* in_blockdata, int id, int face, float in_vx, float in_vy, float in_vz, float *out_vx, float *out_vy, float *out_vz); | |
74 | + void ReflectVector(BlockDataInterface* in_blockdata, int id, int face, float in_vx, float in_vy, float in_vz, float *out_vx, float *out_vy, float *out_vz); | |
75 | +}; | |
76 | + | |
77 | +bool CollideBoxAABB(float box1_min_x, float box1_min_y, float box1_min_z, float box1_max_x, float box1_max_y, float box1_max_z, float box2_min_x, float box2_min_y, float box2_min_z, float box2_max_x, float box2_max_y, float box2_max_z); | |
78 | +bool CollideCylinder(float c1_x, float c1_y, float c1_z, float c1_r, float c1_h, float c2_x, float c2_y, float c2_z, float c2_r, float c2_h, float *angle, float *length); | |
79 | +bool CollideSphereRay(float s_x, float s_y, float s_z, float s_r, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float *Dist, float maxDist); | |
80 | +bool CollideAABBRay(float box_min_x, float box_min_y, float box_min_z, float box_max_x, float box_max_y, float box_max_z, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float *Dist, float maxDist); | |
81 | +float DistancePosRay(float Pos_x, float Pos_y, float Pos_z, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float maxDist); | |
82 | +bool Collide2DLine(int A1x, int A1y, int A2x, int A2y, int B1x, int B1y, int B2x, int B2y, int *out_x, int *out_y); | |
83 | +bool Get2DLineInBox(int line_x1, int line_y1, int line_x2, int line_y2, int box_x1, int box_y1, int box_x2, int box_y2, int *out_line_x1, int *out_line_y1, int *out_line_x2, int *out_line_y2); | |
84 | + | |
85 | +bool CheckTargetAngle(float pos_x, float pos_y, float pos_z, float rx, float ry, float target_x, float target_y, float target_z, float checkdist, float *out_rx, float *out_ry, float *out_dist2); | |
86 | + | |
87 | +#endif | |
\ No newline at end of file |
@@ -0,0 +1,210 @@ | ||
1 | +//! @file event.cpp | |
2 | +//! @brief EventControlクラスの定義 | |
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 "event.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +EventControl::EventControl(PointDataInterface *in_Point, ObjectManager *in_ObjMgr) | |
36 | +{ | |
37 | + Point = in_Point; | |
38 | + ObjMgr = in_ObjMgr; | |
39 | + nextp4 = 0; | |
40 | + waitcnt = 0; | |
41 | +} | |
42 | + | |
43 | +//! @brief ディストラクタ | |
44 | +EventControl::~EventControl() | |
45 | +{} | |
46 | + | |
47 | +//! @brief 対象クラスを設定 | |
48 | +//! @param in_Point ポイントデータ管理クラス | |
49 | +//! @param in_ObjMgr オブジェクト管理クラス | |
50 | +//! @attention この関数で設定を行わないと、クラス自体が正しく機能しません。 | |
51 | +void EventControl::SetClass(PointDataInterface *in_Point, ObjectManager *in_ObjMgr) | |
52 | +{ | |
53 | + Point = in_Point; | |
54 | + ObjMgr = in_ObjMgr; | |
55 | +} | |
56 | + | |
57 | +//! @brief リセット | |
58 | +//! @param EntryP4 イベント処理を開始する認識番号 (-100、-110、-120 など) | |
59 | +void EventControl::Reset(signed char EntryP4) | |
60 | +{ | |
61 | + nextp4 = EntryP4; | |
62 | + waitcnt = 0; | |
63 | +} | |
64 | + | |
65 | +//! @brief 次に処理する認識番号 | |
66 | +//! @return P4:認識番号 | |
67 | +signed char EventControl::GetNextP4() | |
68 | +{ | |
69 | + return nextp4; | |
70 | +} | |
71 | + | |
72 | +//! @brief 対象の人物がケースを持っているかチェック | |
73 | +//! @param in_human 調べる対象のhumanのポインタ | |
74 | +//! @return 持っている:true 持っていない:false | |
75 | +bool EventControl::CheckHaveCase(human *in_human) | |
76 | +{ | |
77 | + int selectweapon; | |
78 | + weapon *out_weapon[TOTAL_HAVEWEAPON]; | |
79 | + int weaponid; | |
80 | + | |
81 | + //所有する武器オブジェクトを全て取得 | |
82 | + in_human->GetWeapon(&selectweapon, out_weapon); | |
83 | + | |
84 | + //全て調べる | |
85 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
86 | + if( out_weapon[i] != NULL ){ | |
87 | + | |
88 | + //武器の種類番号を取得し、それがケースかどうか。 | |
89 | + out_weapon[i]->GetParamData(&weaponid, NULL, NULL); | |
90 | + if( weaponid == ID_WEAPON_CASE ){ | |
91 | + return true; | |
92 | + } | |
93 | + } | |
94 | + } | |
95 | + return false; | |
96 | +} | |
97 | + | |
98 | +//! @brief 処理を実行 | |
99 | +//! @param endcnt 終了カウントのポインタ | |
100 | +//! @param complete ミッション成功フラグのポインタ | |
101 | +//! @param MessageID イベントメッセージ番号のポインタ | |
102 | +//! @param SetMessageID イベントメッセージ読み出しフラグ | |
103 | +//! @return 実行したステップ数 | |
104 | +//! @attention 渡された引数に変更がない場合、渡された引数のデータは操作されません。 | |
105 | +//! @attention SetMessageID は、メッセージイベントが実行された場合に true になります。<b>前回から変更されたとは限りません。</b> | |
106 | +int EventControl::Execution(int *endcnt, bool *complete, int *MessageID, bool *SetMessageID) | |
107 | +{ | |
108 | + pointdata data, pathdata; | |
109 | + int cnt = 0; | |
110 | + human* thuman; | |
111 | + smallobject* tsmallobject; | |
112 | + float hx, hy, hz; | |
113 | + float x, y, z; | |
114 | + int pid; | |
115 | + | |
116 | + for(int i=0; i<TOTAL_EVENTFRAMESTEP; i++){ | |
117 | + cnt = i; | |
118 | + | |
119 | + //次のポイントを探す | |
120 | + if( Point->SearchPointdata(&data, 0x08, 0, 0, 0, nextp4, 0) == 0 ){ return cnt; } | |
121 | + if( (data.p1 < 10)||(19 < data.p1) ){ return cnt; } | |
122 | + | |
123 | + switch(data.p1){ | |
124 | + case 10: //任務達成 | |
125 | + *endcnt += 1; | |
126 | + *complete = true; | |
127 | + return cnt; | |
128 | + | |
129 | + case 11: //任務失敗 | |
130 | + *endcnt += 1; | |
131 | + *complete = false; | |
132 | + return cnt; | |
133 | + | |
134 | + case 12: //死亡待ち | |
135 | + thuman = ObjMgr->SearchHuman(data.p2); | |
136 | + if( thuman == NULL ){ return cnt; } | |
137 | + if( thuman->GetDeadFlag() == false ){ return cnt; } | |
138 | + nextp4 = data.p3; | |
139 | + break; | |
140 | + | |
141 | + case 13: //到着待ち | |
142 | + thuman = ObjMgr->SearchHuman(data.p2); | |
143 | + if( thuman == NULL ){ return cnt; } | |
144 | + thuman->GetPosData(&hx, &hy, &hz, NULL); | |
145 | + x = hx - data.x; | |
146 | + y = hy - data.y; | |
147 | + z = hz - data.z; | |
148 | + if( sqrt(x*x + y*y+ + z*z) > DISTANCE_CHECKPOINT ){ return cnt; } | |
149 | + nextp4 = data.p3; | |
150 | + break; | |
151 | + | |
152 | + case 14: //歩きに変更 | |
153 | + if( Point->SearchPointdata(&pid, 0x08, 0, 0, 0, data.p2, 0) > 0 ){ | |
154 | + //対象がAIパスならば、強制的にパラメータを書き換える | |
155 | + Point->Getdata(&pathdata, pid); | |
156 | + if( (pathdata.p1 == 3)||(pathdata.p1 == 8) ){ | |
157 | + pathdata.p2 = 0; | |
158 | + } | |
159 | + Point->SetParam(pid, pathdata.p1, pathdata.p2, pathdata.p3, pathdata.p4); | |
160 | + } | |
161 | + nextp4 = data.p3; | |
162 | + break; | |
163 | + | |
164 | + case 15: //小物破壊待ち | |
165 | + tsmallobject = ObjMgr->SearchSmallobject(data.p2); | |
166 | + if( tsmallobject == NULL ){ return cnt; } | |
167 | + if( tsmallobject->GetDrawFlag() == true ){ return cnt; } | |
168 | + nextp4 = data.p3; | |
169 | + break; | |
170 | + | |
171 | + case 16: //ケース待ち | |
172 | + thuman = ObjMgr->SearchHuman(data.p2); | |
173 | + if( thuman == NULL ){ return cnt; } | |
174 | + thuman->GetPosData(&hx, &hy, &hz, NULL); | |
175 | + x = hx - data.x; | |
176 | + y = hy - data.y; | |
177 | + z = hz - data.z; | |
178 | + if( sqrt(x*x + y*y+ + z*z) > DISTANCE_CHECKPOINT ){ return cnt; } | |
179 | + if( CheckHaveCase(thuman) == false ){ return cnt; } | |
180 | + nextp4 = data.p3; | |
181 | + break; | |
182 | + | |
183 | + case 17: //時間待ち | |
184 | + if( (int)GAMEFPS * ((unsigned char)data.p2) > waitcnt ){ | |
185 | + waitcnt += 1; | |
186 | + return cnt; | |
187 | + } | |
188 | + waitcnt = 0; | |
189 | + nextp4 = data.p3; | |
190 | + break; | |
191 | + | |
192 | + case 18: //メッセージ | |
193 | + if( (0 <= data.p2)&&(data.p2 < MAX_POINTMESSAGES) ){ | |
194 | + *MessageID = data.p2; | |
195 | + } | |
196 | + nextp4 = data.p3; | |
197 | + //break; | |
198 | + *SetMessageID = true; | |
199 | + return cnt; | |
200 | + | |
201 | + case 19: //チーム変更 | |
202 | + thuman = ObjMgr->SearchHuman(data.p2); | |
203 | + if( thuman == NULL ){ return cnt; } | |
204 | + thuman->SetTeamID(0); | |
205 | + nextp4 = data.p3; | |
206 | + break; | |
207 | + } | |
208 | + } | |
209 | + return cnt; | |
210 | +} | |
\ No newline at end of file |
@@ -0,0 +1,2596 @@ | ||
1 | +//! @file object.cpp | |
2 | +//! @brief objectクラスの定義 | |
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 "object.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +object::object(class ParameterInfo *in_Param, float x, float y, float z, float rx, float size, bool flag) | |
36 | +{ | |
37 | + Param = in_Param; | |
38 | + pos_x = x; | |
39 | + pos_y = y; | |
40 | + pos_z = z; | |
41 | + rotation_x = rx; | |
42 | + RenderFlag = flag; | |
43 | + model_size = size; | |
44 | + | |
45 | + id_parameter = 0; | |
46 | + id_model = -1; | |
47 | + id_texture = -1; | |
48 | +} | |
49 | + | |
50 | +//! @brief ディストラクタ | |
51 | +object::~object() | |
52 | +{} | |
53 | + | |
54 | +//! @brief 設定値を管理するクラスを登録 | |
55 | +//! @attention 各関数を使用する前に実行すること。 | |
56 | +void object::SetParameterInfoClass(class ParameterInfo *in_Param) | |
57 | +{ | |
58 | + Param = in_Param; | |
59 | +} | |
60 | + | |
61 | +//! @brief 座標と角度を設定 | |
62 | +//! @param x X座標 | |
63 | +//! @param y Y座標 | |
64 | +//! @param z Z座標 | |
65 | +//! @param rx 横軸回転 | |
66 | +void object::SetPosData(float x, float y, float z, float rx) | |
67 | +{ | |
68 | + pos_x = x; | |
69 | + pos_y = y; | |
70 | + pos_z = z; | |
71 | + rotation_x = rx; | |
72 | +} | |
73 | + | |
74 | +//! @brief 座標と角度を取得 | |
75 | +//! @param x X座標を受け取るポインタ(NULL可) | |
76 | +//! @param y Y座標を受け取るポインタ(NULL可) | |
77 | +//! @param z Z座標を受け取るポインタ(NULL可) | |
78 | +//! @param rx 横軸回転を受け取るポインタ(NULL可) | |
79 | +void object::GetPosData(float *x, float *y, float *z, float *rx) | |
80 | +{ | |
81 | + if( x != NULL ){ *x = pos_x; } | |
82 | + if( y != NULL ){ *y = pos_y; } | |
83 | + if( z != NULL ){ *z = pos_z; } | |
84 | + if( rx != NULL ){ *rx = rotation_x; } | |
85 | +} | |
86 | + | |
87 | +//! @brief 描画フラグを設定 | |
88 | +//! @param flag 設定するフラグ | |
89 | +void object::SetDrawFlag(bool flag) | |
90 | +{ | |
91 | + RenderFlag = flag; | |
92 | +} | |
93 | + | |
94 | +//! @brief 描画フラグを取得 | |
95 | +//! @return 現在設定されているフラグ | |
96 | +bool object::GetDrawFlag() | |
97 | +{ | |
98 | + return RenderFlag; | |
99 | +} | |
100 | + | |
101 | +//! @brief モデルデータを設定 | |
102 | +//! @param id モデル認識番号 | |
103 | +//! @param size 表示倍率 | |
104 | +void object::SetModel(int id, float size) | |
105 | +{ | |
106 | + id_model = id; | |
107 | + model_size = size; | |
108 | +} | |
109 | + | |
110 | +//! @brief テクスチャを設定 | |
111 | +//! @param id テクスチャ認識番号 | |
112 | +void object::SetTexture(int id) | |
113 | +{ | |
114 | + id_texture = id; | |
115 | +} | |
116 | + | |
117 | +//! @brief 計算を実行(自由落下など) | |
118 | +int object::RunFrame() | |
119 | +{ | |
120 | + return 0; | |
121 | +} | |
122 | + | |
123 | +//! @brief 描画 | |
124 | +//! @param d3dg D3DGraphicsのポインタ | |
125 | +void object::Render(D3DGraphics *d3dg) | |
126 | +{ | |
127 | + if( d3dg == NULL ){ return; } | |
128 | + if( RenderFlag == false ){ return; } | |
129 | + | |
130 | + d3dg->SetWorldTransform(pos_x, pos_y, pos_z, rotation_x, 0.0f, model_size); | |
131 | + d3dg->RenderModel(id_model, id_texture); | |
132 | +} | |
133 | + | |
134 | +//! @brief コンストラクタ | |
135 | +human::human(class ParameterInfo *in_Param, float x, float y, float z, float rx, int id_param, int dataid, signed char p4, int team, bool flag) | |
136 | +{ | |
137 | + //HumanParameter data; | |
138 | + | |
139 | + Param = in_Param; | |
140 | + pos_x = x; | |
141 | + pos_y = y; | |
142 | + pos_z = z; | |
143 | + move_x = 0.0f; | |
144 | + move_y = 0.0f; | |
145 | + move_z = 0.0f; | |
146 | + move_y_flag = false; | |
147 | + rotation_x = rx; | |
148 | + id_parameter = id_param; | |
149 | + upmodel_size = 9.4f; | |
150 | + armmodel_size = 9.0f; | |
151 | + legmodel_size = 9.0f; | |
152 | + RenderFlag = flag; | |
153 | + rotation_y = 0.0f; | |
154 | + armrotation_y = 0.0f; | |
155 | + reaction_y = 0.0f; | |
156 | + legrotation_x = 0.0f; | |
157 | + point_dataid = dataid; | |
158 | + point_p4 = p4; | |
159 | + teamid = team; | |
160 | + | |
161 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
162 | + weapon[i] = NULL; | |
163 | + } | |
164 | + selectweapon = 1; | |
165 | + //if( Param->GetHuman(id_param, &data) == 0 ){ | |
166 | + // hp = data.hp; | |
167 | + //} | |
168 | + //else{ | |
169 | + hp = 0; | |
170 | + //} | |
171 | +#ifdef HUMAN_DEADBODY_COLLISION | |
172 | + deadstate = 0; | |
173 | +#endif | |
174 | + id_texture = -1; | |
175 | + id_upmodel = -1; | |
176 | + for(int i=0; i<TOTAL_ARMMODE; i++){ | |
177 | + id_armmodel[i] = -1; | |
178 | + } | |
179 | + id_legmodel = -1; | |
180 | + for(int i=0; i<TOTAL_WALKMODE; i++){ | |
181 | + id_walkmodel[i] = -1; | |
182 | + } | |
183 | + for(int i=0; i<TOTAL_RUNMODE; i++){ | |
184 | + id_runmodel[i] = -1; | |
185 | + } | |
186 | + | |
187 | + move_rx = 0.0f; | |
188 | + MoveFlag = 0x00; | |
189 | + MoveFlag_lt = MoveFlag; | |
190 | + scopemode = 0; | |
191 | + HitFlag = false; | |
192 | + walkcnt = 0; | |
193 | + runcnt = 0; | |
194 | + totalmove = 0.0f; | |
195 | + StateGunsightErrorRange = 0; | |
196 | + ReactionGunsightErrorRange = 0; | |
197 | +} | |
198 | + | |
199 | +//! @brief ディストラクタ | |
200 | +human::~human() | |
201 | +{} | |
202 | + | |
203 | +//! @brief 設定値を設定 | |
204 | +//! @param id_param 人の種類番号 | |
205 | +//! @param dataid ポイントのデータ番号 | |
206 | +//! @param p4 第4パラメータ | |
207 | +//! @param team チーム番号 | |
208 | +//! @param init オブジェクトを初期化 | |
209 | +void human::SetParamData(int id_param, int dataid, signed char p4, int team, bool init) | |
210 | +{ | |
211 | + id_parameter = id_param; | |
212 | + point_dataid = dataid; | |
213 | + point_p4 = p4; | |
214 | + teamid = team; | |
215 | + | |
216 | + if( init == true ){ | |
217 | + HumanParameter data; | |
218 | + | |
219 | + move_x = 0.0f; | |
220 | + move_y = 0.0f; | |
221 | + move_z = 0.0f; | |
222 | + move_y_flag = false; | |
223 | + rotation_y = 0.0f; | |
224 | + armrotation_y = (float)M_PI/18 * -3; | |
225 | + reaction_y = 0.0f; | |
226 | + legrotation_x = 0.0f; | |
227 | + | |
228 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
229 | + weapon[i] = NULL; | |
230 | + } | |
231 | + selectweapon = 1; | |
232 | + if( Param->GetHuman(id_param, &data) == 0 ){ | |
233 | + hp = data.hp; | |
234 | + } | |
235 | + else{ | |
236 | + hp = 0; | |
237 | + } | |
238 | +#ifdef HUMAN_DEADBODY_COLLISION | |
239 | + deadstate = 0; | |
240 | +#endif | |
241 | + MoveFlag = 0x00; | |
242 | + MoveFlag_lt = MoveFlag; | |
243 | + scopemode = 0; | |
244 | + HitFlag = false; | |
245 | + totalmove = 0.0f; | |
246 | + Invincible = false; | |
247 | + } | |
248 | +} | |
249 | + | |
250 | +//! @brief 設定値を取得 | |
251 | +//! @param id_param 人の種類番号を受け取るポインタ(NULL可) | |
252 | +//! @param dataid ポイントのデータ番号を受け取るポインタ(NULL可) | |
253 | +//! @param p4 第4パラメータを受け取るポインタ(NULL可) | |
254 | +//! @param team チーム番号を受け取るポインタ(NULL可) | |
255 | +void human::GetParamData(int *id_param, int *dataid, signed char *p4, int *team) | |
256 | +{ | |
257 | + if( id_param != NULL ){ *id_param = id_parameter; } | |
258 | + if( dataid != NULL ){ *dataid = point_dataid; } | |
259 | + if( p4 != NULL ){ *p4 = point_p4; } | |
260 | + if( team != NULL ){ *team = teamid; } | |
261 | +} | |
262 | + | |
263 | +//! @brief HPを取得 | |
264 | +//! @return HP | |
265 | +int human::GetHP() | |
266 | +{ | |
267 | + return hp; | |
268 | +} | |
269 | + | |
270 | +//! @brief HPを設定 | |
271 | +//! @param in_hp 新たに設定するHP | |
272 | +//! @return 成功:true 失敗:false | |
273 | +//! @attention HPが1以上の人に対して実行しないと失敗します。 | |
274 | +bool human::SetHP(int in_hp) | |
275 | +{ | |
276 | + if( hp > 0 ){ | |
277 | + hp = in_hp; | |
278 | + return true; | |
279 | + } | |
280 | + return false; | |
281 | +} | |
282 | + | |
283 | + | |
284 | +//! @brief 死体かどうか判定 | |
285 | +//! @return 死体:true 死体でない:false | |
286 | +//! @warning 完全に静止した状態を「死体」と判定します。倒れている最中の人は対象に含まれないため、hp <= 0 が全て死体と判定されるとは限りません。 | |
287 | +bool human::GetDeadFlag() | |
288 | +{ | |
289 | +#ifdef HUMAN_DEADBODY_COLLISION | |
290 | + if( deadstate == 5 ){ return true; } | |
291 | + return false; | |
292 | +#else | |
293 | + if( hp <= 0 ){ return true; } | |
294 | + return false; | |
295 | +#endif | |
296 | +} | |
297 | + | |
298 | +//! @brief チーム番号を設定(上書き) | |
299 | +//! @param id 新しいチーム番号 | |
300 | +void human::SetTeamID(int id) | |
301 | +{ | |
302 | + teamid = id; | |
303 | +} | |
304 | + | |
305 | +//! @brief 無敵フラグを取得 | |
306 | +//! @return true:無敵 false:通常 | |
307 | +//! @attention 無敵状態の場合、銃弾・手榴弾の爆発・落下 によるダメージを一切受けません。 | |
308 | +bool human::GetInvincibleFlag() | |
309 | +{ | |
310 | + return Invincible; | |
311 | +} | |
312 | + | |
313 | +//! @brief 無敵フラグを設定 | |
314 | +//! @param flag true:無敵 false:通常 | |
315 | +//! @attention 無敵状態の場合、銃弾・手榴弾の爆発・落下 によるダメージを一切受けません。 | |
316 | +void human::SetInvincibleFlag(bool flag) | |
317 | +{ | |
318 | + Invincible = flag; | |
319 | +} | |
320 | + | |
321 | +//! @brief 前処理の移動量を取得 | |
322 | +//! @param *x X軸移動量を取得するポインタ(NULL可) | |
323 | +//! @param *y Y軸移動量を取得するポインタ(NULL可) | |
324 | +//! @param *z Z軸移動量を取得するポインタ(NULL可) | |
325 | +void human::GetMovePos(float *x, float *y, float *z) | |
326 | +{ | |
327 | + if( x != NULL ){ *x = move_x; } | |
328 | + if( y != NULL ){ *y = move_y; } | |
329 | + if( z != NULL ){ *z = move_z; } | |
330 | +} | |
331 | + | |
332 | +//! @brief モデルデータを設定 | |
333 | +//! @param upmodel 上半身のモデル | |
334 | +//! @param armmodel[] 腕のモデルの配列(配列数:TOTAL_ARMMODE) | |
335 | +//! @param legmodel 足(静止状態)のモデル | |
336 | +//! @param walkmodel[] 腕のモデルの配列(配列数:TOTAL_WALKMODE) | |
337 | +//! @param runmodel[] 腕のモデルの配列(配列数:TOTAL_RUNMODE) | |
338 | +void human::SetModel(int upmodel, int armmodel[], int legmodel, int walkmodel[], int runmodel[]) | |
339 | +{ | |
340 | + id_upmodel = upmodel; | |
341 | + for(int i=0; i<TOTAL_ARMMODE; i++){ | |
342 | + id_armmodel[i] = armmodel[i]; | |
343 | + } | |
344 | + id_legmodel = legmodel; | |
345 | + for(int i=0; i<TOTAL_WALKMODE; i++){ | |
346 | + id_walkmodel[i] = walkmodel[i]; | |
347 | + } | |
348 | + for(int i=0; i<TOTAL_RUNMODE; i++){ | |
349 | + id_runmodel[i] = runmodel[i]; | |
350 | + } | |
351 | +} | |
352 | + | |
353 | +//! @brief 武器を設定 | |
354 | +//! @param in_weapon[] 設定するweaponクラスのポインタ配列 | |
355 | +//! @warning 通常は PickupWeapon()関数 を使用すること | |
356 | +void human::SetWeapon(class weapon *in_weapon[]) | |
357 | +{ | |
358 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
359 | + if( in_weapon[i] == NULL ){ | |
360 | + weapon[i] = NULL; | |
361 | + } | |
362 | + else{ | |
363 | + //武器を正しく拾えれば、所持武器として登録 | |
364 | + if( in_weapon[i]->Pickup() == 0 ){ | |
365 | + weapon[i] = in_weapon[i]; | |
366 | + } | |
367 | + } | |
368 | + } | |
369 | +} | |
370 | + | |
371 | +//! @brief 武器を拾う | |
372 | +//! @param in_weapon[] 設定するweaponクラスのポインタ | |
373 | +//! @return 成功:1 失敗:0 | |
374 | +//! @attention 人の種類が ゾンビ の場合、この関数は失敗します。 | |
375 | +int human::PickupWeapon(class weapon *in_weapon) | |
376 | +{ | |
377 | + if( in_weapon == NULL ){ | |
378 | + return 0; | |
379 | + } | |
380 | + | |
381 | + //人の種類が ゾンビ ならば、失敗 | |
382 | + HumanParameter Paraminfo; | |
383 | + Param->GetHuman(id_parameter, &Paraminfo); | |
384 | + if( Paraminfo.type == 2 ){ | |
385 | + return 0; | |
386 | + } | |
387 | + | |
388 | + if( weapon[selectweapon] == NULL ){ | |
389 | + //武器を正しく拾えれば、所持武器として登録 | |
390 | + if( in_weapon->Pickup() == 0 ){ | |
391 | + weapon[selectweapon] = in_weapon; | |
392 | + | |
393 | + //切り替え完了のカウント | |
394 | + selectweaponcnt = 10; | |
395 | + | |
396 | + return 1; | |
397 | + } | |
398 | + } | |
399 | + return 0; | |
400 | +} | |
401 | + | |
402 | +//! @brief 武器を切り替える(持ち替える) | |
403 | +//! @param id 持ち替える武器 (-1 で次の武器) | |
404 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
405 | +void human::ChangeWeapon(int id) | |
406 | +{ | |
407 | + //体力がなければ失敗 | |
408 | + if( hp <= 0 ){ return; } | |
409 | + | |
410 | + //リロード中なら失敗 | |
411 | + if( weapon[selectweapon] != NULL ){ | |
412 | + if( weapon[selectweapon]->GetReloadCnt() > 0 ){ return; } | |
413 | + } | |
414 | + | |
415 | + //同じ武器に切り替えようとしているなら、失敗 | |
416 | + if( selectweapon == id ){ return; } | |
417 | + | |
418 | + //武器切り替え中なら失敗 | |
419 | + if( selectweaponcnt > 0 ){ return; } | |
420 | + | |
421 | + if( id == -1 ){ | |
422 | + //次の武器番号を選択 | |
423 | + selectweapon += 1; | |
424 | + if( selectweapon == TOTAL_HAVEWEAPON ){ | |
425 | + selectweapon = 0; | |
426 | + } | |
427 | + } | |
428 | + else{ | |
429 | + //武器番号が範囲内か確認 | |
430 | + if( (id < 0)||((TOTAL_HAVEWEAPON -1) < id ) ){ return; } | |
431 | + selectweapon = id; | |
432 | + } | |
433 | + | |
434 | + //スコープ表示を解除 | |
435 | + SetDisableScope(); | |
436 | + | |
437 | + //腕の角度(反動)を設定 | |
438 | + reaction_y = (float)M_PI/18*2 * -1; | |
439 | + | |
440 | + //切り替え完了のカウント | |
441 | + selectweaponcnt = 10; | |
442 | +} | |
443 | + | |
444 | +//! @brief 武器の切り替えカウントを取得 | |
445 | +//! @return カウント数 (1以上で切り替え中) | |
446 | +int human::GetChangeWeaponCnt() | |
447 | +{ | |
448 | + return selectweaponcnt; | |
449 | +} | |
450 | + | |
451 | +//! @brief 武器を取得 | |
452 | +//! @param out_selectweapon 選択されている武器 (0 〜 [TOTAL_HAVEWEAPON]-1) | |
453 | +//! @param out_weapon 受け取るweaponクラスのポインタ配列 (配列数:TOTAL_HAVEWEAPON) | |
454 | +void human::GetWeapon(int *out_selectweapon, class weapon *out_weapon[]) | |
455 | +{ | |
456 | + *out_selectweapon = selectweapon; | |
457 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
458 | + out_weapon[i] = weapon[i]; | |
459 | + } | |
460 | +} | |
461 | + | |
462 | +//! @brief 現在装備している武器の種類番号を取得 | |
463 | +//! @return 武器の種類番号(0 〜 TOTAL_PARAMETERINFO_WEAPON -1) | |
464 | +//! @attention 現在手に持っている武器の種類番号です。 GetWeapon()関数 を用いて調べるのと同等です。 | |
465 | +int human::GetMainWeaponTypeNO() | |
466 | +{ | |
467 | + if( weapon[selectweapon] == NULL ){ | |
468 | + return ID_WEAPON_NONE; | |
469 | + } | |
470 | + | |
471 | + int id_param; | |
472 | + weapon[selectweapon]->GetParamData(&id_param, NULL, NULL); | |
473 | + return id_param; | |
474 | +} | |
475 | + | |
476 | +//! @brief 連射設定を取得 | |
477 | +//! @return 連射可能:true 連射不可:false | |
478 | +bool human::GetWeaponBlazingmode() | |
479 | +{ | |
480 | + int param_id; | |
481 | + WeaponParameter data; | |
482 | + | |
483 | + //武器を装備していなければ、失敗 | |
484 | + if( weapon[selectweapon] == NULL ){ return false; } | |
485 | + | |
486 | + //装備している武器の種類番号を取得 | |
487 | + weapon[selectweapon]->GetParamData(¶m_id, NULL, NULL); | |
488 | + | |
489 | + //連射設定を返す | |
490 | + Param->GetWeapon(param_id, &data); | |
491 | + return data.blazingmode; | |
492 | +} | |
493 | + | |
494 | +//! @brief 発砲処理 | |
495 | +//! @param weapon_paramid 発砲した武器の番号を受け取るポインタ | |
496 | +//! @param GunsightErrorRange 発砲した際の照準誤差を受け取るポインタ | |
497 | +//! @return 成功:1 失敗:0 | |
498 | +//! @attention 弾オブジェクトの処理や、発砲音の再生は別途行う必要があります。 | |
499 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
500 | +bool human::ShotWeapon(int *weapon_paramid, int *GunsightErrorRange) | |
501 | +{ | |
502 | + int param_id; | |
503 | + | |
504 | + //武器切り替え中なら失敗 | |
505 | + if( selectweaponcnt > 0 ){ return false; } | |
506 | + | |
507 | + //武器を装備していなければ、失敗 | |
508 | + if( weapon[selectweapon] == NULL ){ return false; } | |
509 | + | |
510 | + //弾の発射処理を行う | |
511 | + if( weapon[selectweapon]->Shot() != 0 ){ return false; } | |
512 | + | |
513 | + //武器の種類番号を取得 | |
514 | + weapon[selectweapon]->GetParamData(¶m_id, NULL, NULL); | |
515 | + | |
516 | + | |
517 | + //武器の設定値を取得 | |
518 | + WeaponParameter ParamData; | |
519 | + if( Param->GetWeapon(param_id, &ParamData) != 0 ){ return false; } | |
520 | + | |
521 | + //精密スコープの武器でスコープを覗いていなければ、誤差 20。 | |
522 | + if( (scopemode == 0)&&(ParamData.scopemode == 2) ){ | |
523 | + ReactionGunsightErrorRange = 20; | |
524 | + } | |
525 | + | |
526 | + | |
527 | + //武器の種類番号と誤差を返す | |
528 | + *weapon_paramid = param_id; | |
529 | + *GunsightErrorRange = StateGunsightErrorRange + ReactionGunsightErrorRange; | |
530 | + | |
531 | + | |
532 | + //精密スコープ以外の武器を、スコープを使わずに使っていたら、設定された誤差を加算。 | |
533 | + if( (ParamData.scopemode != 2)&&(scopemode == 0) ){ | |
534 | + ReactionGunsightErrorRange += ParamData.reaction; | |
535 | + } | |
536 | + | |
537 | + //スコープを使用している状態の反動を加算 | |
538 | + if( (ParamData.scopemode == 1)&&(scopemode != 0) ){ | |
539 | + armrotation_y += (float)M_PI/180 * (WEAPONERRORRANGE_SCALE * ParamData.reaction); | |
540 | + } | |
541 | + if( ParamData.scopemode == 2 ){ | |
542 | + armrotation_y += (float)M_PI/180 * (WEAPONERRORRANGE_SCALE * ParamData.reaction); | |
543 | + } | |
544 | + | |
545 | + //腕に反動を伝える | |
546 | + if( param_id == ID_WEAPON_GRENADE ){ | |
547 | + reaction_y = (float)M_PI/18*2; | |
548 | + } | |
549 | + else{ | |
550 | + reaction_y = (float)M_PI/360 * ParamData.reaction; | |
551 | + } | |
552 | + | |
553 | + //武器が無くなっていれば、装備から外した扱いに。 (手榴弾用) | |
554 | + if( weapon[selectweapon]->GetDrawFlag() == false ){ | |
555 | + weapon[selectweapon] = NULL; | |
556 | + } | |
557 | + return true; | |
558 | +} | |
559 | + | |
560 | +//! @brief リロード | |
561 | +//! @return 成功:true 失敗:false | |
562 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
563 | +bool human::ReloadWeapon() | |
564 | +{ | |
565 | + //武器切り替え中なら失敗 | |
566 | + if( selectweaponcnt > 0 ){ return false; } | |
567 | + | |
568 | + //何かしらの武器を装備していれば〜 | |
569 | + if( weapon[selectweapon] != NULL ){ | |
570 | + //リロード中なら失敗 | |
571 | + if( weapon[selectweapon]->GetReloadCnt() > 0 ){ return false; } | |
572 | + | |
573 | + //リロード処理を開始 | |
574 | + if( weapon[selectweapon]->StartReload() != 0 ){ return false; } | |
575 | + | |
576 | + //スコープモードを解除 | |
577 | + SetDisableScope(); | |
578 | + return true; | |
579 | + } | |
580 | + return false; | |
581 | +} | |
582 | + | |
583 | +//! @brief 武器を捨てる | |
584 | +//! @return 成功:true 失敗:false | |
585 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
586 | +bool human::DumpWeapon() | |
587 | +{ | |
588 | + //武器切り替え中なら失敗 | |
589 | + if( selectweaponcnt > 0 ){ return false; } | |
590 | + | |
591 | + //何かしらの武器を装備していれば〜 | |
592 | + if( weapon[selectweapon] != NULL ){ | |
593 | + //リロード中なら失敗 | |
594 | + if( weapon[selectweapon]->GetReloadCnt() > 0 ){ return false; } | |
595 | + | |
596 | + //武器を捨て、装備を解除 | |
597 | + weapon[selectweapon]->Dropoff(pos_x, pos_y, pos_z, rotation_x, 1.63f); | |
598 | + weapon[selectweapon] = NULL; | |
599 | + | |
600 | + //スコープモードを解除 | |
601 | + SetDisableScope(); | |
602 | + | |
603 | + return true; | |
604 | + } | |
605 | + | |
606 | + return false; | |
607 | +} | |
608 | + | |
609 | +//! @brief 武器のショットモード切り替え | |
610 | +//! @return 成功:0 失敗:1 | |
611 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
612 | +int human::ChangeShotMode() | |
613 | +{ | |
614 | + //武器を装備してなければ失敗 | |
615 | + if( weapon[selectweapon] == NULL ){ return 1; } | |
616 | + | |
617 | + //装備している武器の情報を取得 | |
618 | + int param_id, lnbs, nbs; | |
619 | + weapon[selectweapon]->GetParamData(¶m_id, &lnbs, &nbs); | |
620 | + | |
621 | + //武器のショットモード切り替え先(新しい武器番号)を調べる | |
622 | + WeaponParameter ParamData; | |
623 | + int ChangeWeapon; | |
624 | + if( Param->GetWeapon(param_id, &ParamData) != 0 ){ return 1; } | |
625 | + ChangeWeapon = ParamData.ChangeWeapon; | |
626 | + | |
627 | + //新しい武器番号が正しいか確認 | |
628 | + if( ChangeWeapon == param_id ){ return 1; } | |
629 | + if( (ChangeWeapon < 0)||(TOTAL_PARAMETERINFO_WEAPON-1 < ChangeWeapon) ){ return 1; } | |
630 | + | |
631 | + //設定を適用 | |
632 | + weapon[selectweapon]->SetParamData(ChangeWeapon, lnbs, nbs, false); | |
633 | + return 0; | |
634 | +} | |
635 | + | |
636 | +//! @brief 前進(走り)を設定 | |
637 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
638 | +void human::SetMoveForward() | |
639 | +{ | |
640 | + SetFlag(MoveFlag, MOVEFLAG_FORWARD); | |
641 | +} | |
642 | + | |
643 | +//! @brief 後退を設定 | |
644 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
645 | +void human::SetMoveBack() | |
646 | +{ | |
647 | + SetFlag(MoveFlag, MOVEFLAG_BACK); | |
648 | +} | |
649 | + | |
650 | +//! @brief 左走りを設定 | |
651 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
652 | +void human::SetMoveLeft() | |
653 | +{ | |
654 | + SetFlag(MoveFlag, MOVEFLAG_LEFT); | |
655 | +} | |
656 | + | |
657 | +//! @brief 右走りを設定 | |
658 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
659 | +void human::SetMoveRight() | |
660 | +{ | |
661 | + SetFlag(MoveFlag, MOVEFLAG_RIGHT); | |
662 | +} | |
663 | + | |
664 | +//! @brief 歩きを設定 | |
665 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
666 | +void human::SetMoveWalk() | |
667 | +{ | |
668 | + SetFlag(MoveFlag, MOVEFLAG_WALK); | |
669 | +} | |
670 | + | |
671 | +//! @brief 人の移動モードを取得 | |
672 | +//! @param nowdata 現在の値を取得:true 前フレームの値を使用:false | |
673 | +//! @return 歩き:1 走り:2 移動してない:0 | |
674 | +int human::GetMovemode(bool nowdata) | |
675 | +{ | |
676 | + //使用されていないか、処理されていなければ終了 | |
677 | + if( RenderFlag == false ){ return 0; } | |
678 | + if( hp <= 0 ){ return 0; } | |
679 | + | |
680 | + if( nowdata == false ){ //前のデータ | |
681 | + //歩きならば 1 | |
682 | + if( GetFlag(MoveFlag_lt, MOVEFLAG_WALK) ){ | |
683 | + return 1; | |
684 | + } | |
685 | + //走りならば 2 | |
686 | + if( GetFlag(MoveFlag_lt, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) ){ | |
687 | + return 2; | |
688 | + } | |
689 | + } | |
690 | + else{ //現在のデータ | |
691 | + //歩きならば 1 | |
692 | + if( GetFlag(MoveFlag, MOVEFLAG_WALK) ){ | |
693 | + return 1; | |
694 | + } | |
695 | + //走りならば 2 | |
696 | + if( GetFlag(MoveFlag, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) ){ | |
697 | + return 2; | |
698 | + } | |
699 | + } | |
700 | + | |
701 | + //移動してない | |
702 | + return 0; | |
703 | +} | |
704 | + | |
705 | +//! @brief スコープを設定 | |
706 | +//! @return 成功:true 失敗:false | |
707 | +bool human::SetEnableScope() | |
708 | +{ | |
709 | + int param_id; | |
710 | + WeaponParameter data; | |
711 | + | |
712 | + //何も武器を装備してなければ失敗 | |
713 | + if( weapon[selectweapon] == NULL ){ return false; } | |
714 | + | |
715 | + //武器の種類番号を取得 | |
716 | + weapon[selectweapon]->GetParamData(¶m_id, NULL, NULL); | |
717 | + | |
718 | + //武器の設定値を取得 | |
719 | + Param->GetWeapon(param_id, &data); | |
720 | + | |
721 | + //スコープを設定 | |
722 | + scopemode = data.scopemode; | |
723 | + return true; | |
724 | +} | |
725 | + | |
726 | +//! @brief スコープを解除 | |
727 | +void human::SetDisableScope() | |
728 | +{ | |
729 | + scopemode = 0; | |
730 | +} | |
731 | + | |
732 | +//! @brief スコープ設定を取得 | |
733 | +int human::GetScopeMode() | |
734 | +{ | |
735 | + return scopemode; | |
736 | +} | |
737 | + | |
738 | +//! @brief 横軸と縦軸の向きを取得 | |
739 | +//! @param rx 横軸を取得するポインタ | |
740 | +//! @param ry 縦軸を取得するポインタ | |
741 | +void human::GetRxRy(float *rx, float *ry) | |
742 | +{ | |
743 | + *rx = rotation_x; | |
744 | + *ry = armrotation_y; | |
745 | +} | |
746 | + | |
747 | +//! @brief 横軸と縦軸の向きを設定 | |
748 | +//! @param rx 設定する横軸 | |
749 | +//! @param ry 設定する縦軸 | |
750 | +void human::SetRxRy(float rx, float ry) | |
751 | +{ | |
752 | + rotation_x = rx; | |
753 | + armrotation_y = ry; | |
754 | +} | |
755 | + | |
756 | +//! @brief 全体の回転角度取得 | |
757 | +//! @return 縦軸を取得するポインタ | |
758 | +//! @warning 死亡して倒れる際の角度です。GetRxRy()関数で受け取る値とは異なります。 | |
759 | +float human::GetDeadRy() | |
760 | +{ | |
761 | + return rotation_y; | |
762 | +} | |
763 | + | |
764 | +//! @brief ジャンプ | |
765 | +//! @return 成功:0 失敗:1 | |
766 | +//! @attention ゲーム上から直接呼び出すことは避け、ObjectManagerクラスから呼び出してください。 | |
767 | +int human::Jump() | |
768 | +{ | |
769 | + //地面に触れており、落下速度が0.0ならば | |
770 | + if( move_y_flag == false ){ | |
771 | + if( move_y == 0.0f ){ | |
772 | + move_y = HUMAN_JUMP_SPEED; | |
773 | + return 0; | |
774 | + } | |
775 | + } | |
776 | + return 1; | |
777 | +} | |
778 | + | |
779 | +//! @brief 押しだす・力を加える | |
780 | +//! @param rx 横軸 | |
781 | +//! @param ry 縦軸 | |
782 | +//! @param speed 速度 | |
783 | +void human::AddPosOrder(float rx, float ry, float speed) | |
784 | +{ | |
785 | + move_x += cos(rx) * cos(ry) * speed; | |
786 | + move_y += sin(ry) * speed; | |
787 | + move_z += sin(rx) * cos(ry) * speed; | |
788 | +} | |
789 | + | |
790 | +//! @brief 弾が 頭 にヒット | |
791 | +//! @param attacks 弾の攻撃力 | |
792 | +void human::HitBulletHead(int attacks) | |
793 | +{ | |
794 | + if( Invincible == false ){ | |
795 | + hp -= (int)((float)attacks * HUMAN_DAMAGE_HEAD); | |
796 | + } | |
797 | + HitFlag = true; | |
798 | +} | |
799 | + | |
800 | +//! @brief 弾が 上半身 にヒット | |
801 | +//! @param attacks 弾の攻撃力 | |
802 | +void human::HitBulletUp(int attacks) | |
803 | +{ | |
804 | + if( Invincible == false ){ | |
805 | + hp -= (int)((float)attacks * HUMAN_DAMAGE_UP); | |
806 | + } | |
807 | + HitFlag = true; | |
808 | +} | |
809 | + | |
810 | +//! @brief 弾が 下半身 にヒット | |
811 | +//! @param attacks 弾の攻撃力 | |
812 | +void human::HitBulletLeg(int attacks) | |
813 | +{ | |
814 | + if( Invincible == false ){ | |
815 | + hp -= (int)((float)attacks * HUMAN_DAMAGE_LEG); | |
816 | + } | |
817 | + HitFlag = true; | |
818 | +} | |
819 | + | |
820 | +//! @brief ゾンビの攻撃がヒット | |
821 | +void human::HitZombieAttack() | |
822 | +{ | |
823 | + if( Invincible == false ){ | |
824 | + hp -= HUMAN_DAMAGE_ZOMBIEU + GetRand(HUMAN_DAMAGE_ZOMBIEA); | |
825 | + } | |
826 | + HitFlag = true; | |
827 | +} | |
828 | + | |
829 | +//! @brief 手榴弾の爆風がヒット | |
830 | +//! @param attacks 爆風の攻撃力 | |
831 | +//! @attention 距離による計算を事前に済ませてください。 | |
832 | +void human::HitGrenadeExplosion(int attacks) | |
833 | +{ | |
834 | + if( Invincible == false ){ | |
835 | + hp -= attacks; | |
836 | + } | |
837 | + HitFlag = true; | |
838 | +} | |
839 | + | |
840 | +//! @brief 被弾したかチェックする | |
841 | +//! @return 被弾した:true 被弾してない:false | |
842 | +//! @attention 実行すると、フラグは false に初期化されます。 | |
843 | +bool human::CheckHit() | |
844 | +{ | |
845 | + bool returnflag = HitFlag; | |
846 | + HitFlag = false; | |
847 | + return returnflag; | |
848 | +} | |
849 | + | |
850 | +//! @brief 合計移動量を取得 | |
851 | +//! @return 合計移動量 | |
852 | +float human::GetTotalMove() | |
853 | +{ | |
854 | + return totalmove; | |
855 | +} | |
856 | + | |
857 | +//! @brief 照準の状態誤差の処理 | |
858 | +//! @attention ControlProcess()より前で処理すること | |
859 | +void human::GunsightErrorRange() | |
860 | +{ | |
861 | + //初期化 | |
862 | + StateGunsightErrorRange = 0; | |
863 | + | |
864 | + //各操作による誤差を設定 | |
865 | + if( GetFlag(MoveFlag, MOVEFLAG_WALK) ){ | |
866 | + StateGunsightErrorRange = 4; | |
867 | + } | |
868 | + if( GetFlag(MoveFlag, MOVEFLAG_FORWARD) ){ | |
869 | + StateGunsightErrorRange = 8; | |
870 | + } | |
871 | + if( GetFlag(MoveFlag, MOVEFLAG_BACK) ){ | |
872 | + StateGunsightErrorRange = 6; | |
873 | + } | |
874 | + if( GetFlag(MoveFlag, (MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) ){ | |
875 | + StateGunsightErrorRange = 7; | |
876 | + } | |
877 | + if( move_y_flag == true ){ | |
878 | + StateGunsightErrorRange = 22; | |
879 | + } | |
880 | + if( hp < 40 ){ | |
881 | + StateGunsightErrorRange += 3; | |
882 | + } | |
883 | + | |
884 | + //何か武器を装備していれば | |
885 | + if( weapon[selectweapon] != NULL ){ | |
886 | + //武器の設定データを取得 | |
887 | + int param; | |
888 | + WeaponParameter data; | |
889 | + weapon[selectweapon]->GetParamData(¶m, NULL, NULL); | |
890 | + Param->GetWeapon(param, &data); | |
891 | + | |
892 | + //誤差を 1 減らす | |
893 | + ReactionGunsightErrorRange -= 1; | |
894 | + | |
895 | + //誤差の範囲を補正 | |
896 | + if( ReactionGunsightErrorRange < 0 ){ ReactionGunsightErrorRange = 0; } | |
897 | + if( ReactionGunsightErrorRange > data.ErrorRangeMAX ){ ReactionGunsightErrorRange = data.ErrorRangeMAX; } | |
898 | + } | |
899 | + else{ | |
900 | + ReactionGunsightErrorRange = 0; | |
901 | + } | |
902 | +} | |
903 | + | |
904 | +//! @brief 死亡判定と倒れる処理 | |
905 | +//! @return 静止した死体:4 倒れ終わった直後:3 倒れている最中:2 倒れ始める:1 何もしない:0 | |
906 | +int human::CheckAndProcessDead(class Collision *CollD) | |
907 | +{ | |
908 | +#ifdef HUMAN_DEADBODY_COLLISION | |
909 | + float add_ry = 0.0f; | |
910 | + float check_posx, check_posy, check_posz; | |
911 | + | |
912 | + if( deadstate == 0 ){ | |
913 | + if( hp <= 0 ){ //HPが 0 以下になった(死亡した)瞬間なら、倒し始める | |
914 | + //体の角度・腕の角度 | |
915 | + switch( GetRand(4) ){ | |
916 | + case 0: | |
917 | + add_ry = (float)M_PI/180*6; | |
918 | + armrotation_y = (float)M_PI/2; | |
919 | + break; | |
920 | + case 1: | |
921 | + add_ry = (float)M_PI/180*6 * -1; | |
922 | + armrotation_y = (float)M_PI/2; | |
923 | + break; | |
924 | + case 2: | |
925 | + add_ry = (float)M_PI/180*6; | |
926 | + armrotation_y = (float)M_PI/2 * -1; | |
927 | + break; | |
928 | + case 3: | |
929 | + add_ry = (float)M_PI/180*6 * -1; | |
930 | + armrotation_y = (float)M_PI/2 * -1; | |
931 | + break; | |
932 | + } | |
933 | + | |
934 | + //死体が埋まらぬよう、高さを +1.0 する | |
935 | + pos_y += 1.0f; | |
936 | + | |
937 | + //所持している武器を全て捨てる | |
938 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
939 | + if( weapon[i] != NULL ){ | |
940 | + weapon[i]->Dropoff(pos_x, pos_y, pos_z, (float)M_PI/18*GetRand(36), 1.5f); | |
941 | + weapon[i] = NULL; | |
942 | + } | |
943 | + } | |
944 | + | |
945 | + //スコープモードを解除 | |
946 | + SetDisableScope(); | |
947 | + | |
948 | + //次のフレームの頭の座標を取得 | |
949 | + check_posx = pos_x + cos(rotation_x*-1 - (float)M_PI/2) * sin(add_ry) * HUMAN_HEIGTH; | |
950 | + check_posy = pos_y + cos(add_ry) * HUMAN_HEIGTH; | |
951 | + check_posz = pos_z + sin(rotation_x*-1 - (float)M_PI/2) * sin(add_ry) * HUMAN_HEIGTH; | |
952 | + | |
953 | + if( CollD->CheckALLBlockInside(check_posx, check_posy, check_posz) == true ){ | |
954 | + deadstate = 2; | |
955 | + } | |
956 | + else{ | |
957 | + rotation_y += add_ry; | |
958 | + deadstate = 1; | |
959 | + } | |
960 | + return 1; | |
961 | + } | |
962 | + return 0; | |
963 | + } | |
964 | + | |
965 | + if( deadstate == 1 ){ | |
966 | + //135度以上倒れていれば | |
967 | + if( abs(rotation_y) >= (float)M_PI/4*3 ){ | |
968 | + deadstate = 2; | |
969 | + return 2; | |
970 | + } | |
971 | + | |
972 | + if( pos_y <= (HUMAN_DEADLINE + 10.0f) ){ | |
973 | + //90度以上倒れていれば | |
974 | + if( abs(rotation_y) >= (float)M_PI/2 ){ | |
975 | + deadstate = 4; | |
976 | + return 2; | |
977 | + } | |
978 | + } | |
979 | + | |
980 | + //前後に倒す | |
981 | + if( rotation_y > 0.0f ){ //rotation_y < (float)M_PI/4*3 | |
982 | + add_ry = (float)M_PI/180*6; | |
983 | + } | |
984 | + else if( rotation_y < 0.0f ){ //rotation_y > (float)M_PI/4*3 * -1 | |
985 | + add_ry = (float)M_PI/180*6 * -1; | |
986 | + } | |
987 | + | |
988 | + if( pos_y <= HUMAN_DEADLINE ){ | |
989 | + rotation_y += add_ry; | |
990 | + } | |
991 | + else{ | |
992 | + //次のフレームの頭の座標を取得 | |
993 | + check_posx = pos_x + cos(rotation_x*-1 - (float)M_PI/2) * sin(rotation_y + add_ry) * HUMAN_HEIGTH; | |
994 | + check_posy = pos_y + cos(rotation_y + add_ry) * HUMAN_HEIGTH; | |
995 | + check_posz = pos_z + sin(rotation_x*-1 - (float)M_PI/2) * sin(rotation_y + add_ry) * HUMAN_HEIGTH; | |
996 | + | |
997 | + if( CollD->CheckALLBlockInside(check_posx, check_posy, check_posz) == true ){ | |
998 | + deadstate = 3; | |
999 | + } | |
1000 | + else{ | |
1001 | + rotation_y += add_ry; | |
1002 | + } | |
1003 | + } | |
1004 | + | |
1005 | + return 2; | |
1006 | + } | |
1007 | + | |
1008 | + if( deadstate == 2 ){ | |
1009 | + if( pos_y <= HUMAN_DEADLINE ){ | |
1010 | + deadstate = 4; | |
1011 | + return 2; | |
1012 | + } | |
1013 | + | |
1014 | + //次のフレームの足の座標 | |
1015 | + check_posx = pos_x; | |
1016 | + check_posy = pos_y - 0.5f; | |
1017 | + check_posz = pos_z; | |
1018 | + | |
1019 | + if( CollD->CheckALLBlockInside(check_posx, check_posy, check_posz) == true ){ | |
1020 | + deadstate = 4; | |
1021 | + } | |
1022 | + else{ | |
1023 | + pos_y -= 0.5f; | |
1024 | + } | |
1025 | + | |
1026 | + return 2; | |
1027 | + } | |
1028 | + | |
1029 | + if( deadstate == 3 ){ | |
1030 | + //deadstate = 4; | |
1031 | + | |
1032 | + //90度以上倒れていれば | |
1033 | + if( abs(rotation_y) >= (float)M_PI/2 ){ | |
1034 | + deadstate = 4; | |
1035 | + return 2; | |
1036 | + } | |
1037 | + | |
1038 | + //前後に倒す | |
1039 | + if( rotation_y > 0.0f ){ //rotation_y < (float)M_PI/2 | |
1040 | + add_ry = (float)M_PI/180*6; | |
1041 | + } | |
1042 | + else if( rotation_y < 0.0f ){ //rotation_y > (float)M_PI/2 * -1 | |
1043 | + add_ry = (float)M_PI/180*6 * -1; | |
1044 | + } | |
1045 | + | |
1046 | + //次のフレームの足の座標を取得 | |
1047 | + check_posx = pos_x - cos(rotation_x*-1 - (float)M_PI/2) * sin(rotation_y + add_ry) * HUMAN_HEIGTH; | |
1048 | + check_posy = pos_y + 0.1f; | |
1049 | + check_posz = pos_z - sin(rotation_x*-1 - (float)M_PI/2) * sin(rotation_y + add_ry) * HUMAN_HEIGTH; | |
1050 | + | |
1051 | + if( CollD->CheckALLBlockInside(check_posx, check_posy, check_posz) == true ){ | |
1052 | + deadstate = 4; | |
1053 | + return 2; | |
1054 | + } | |
1055 | + | |
1056 | + //次のフレームの頭の座標を取得 | |
1057 | + check_posx = pos_x - cos(rotation_x*-1 - (float)M_PI/2) * sin(rotation_y + add_ry) * HUMAN_HEIGTH; | |
1058 | + check_posy = pos_y + cos(rotation_y + add_ry) * HUMAN_HEIGTH; | |
1059 | + check_posz = pos_z - sin(rotation_x*-1 - (float)M_PI/2) * sin(rotation_y + add_ry) * HUMAN_HEIGTH; | |
1060 | + | |
1061 | + if( CollD->CheckALLBlockInside(check_posx, check_posy, check_posz) == true ){ | |
1062 | + deadstate = 4; | |
1063 | + return 2; | |
1064 | + } | |
1065 | + | |
1066 | + //足の座標を移動 | |
1067 | + pos_x -= cos(rotation_x*-1 - (float)M_PI/2) * sin(add_ry) * HUMAN_HEIGTH; | |
1068 | + pos_z -= sin(rotation_x*-1 - (float)M_PI/2) * sin(add_ry) * HUMAN_HEIGTH; | |
1069 | + | |
1070 | + rotation_y += add_ry; | |
1071 | + return 2; | |
1072 | + } | |
1073 | + | |
1074 | + if( deadstate == 4 ){ | |
1075 | + //何もしない(固定) | |
1076 | + deadstate = 5; | |
1077 | + return 3; | |
1078 | + } | |
1079 | + | |
1080 | + if( deadstate == 5 ){ | |
1081 | + //何もしない(固定) | |
1082 | + return 4; | |
1083 | + } | |
1084 | + | |
1085 | + return 0; | |
1086 | +#else | |
1087 | + if( abs(rotation_y) >= (float)M_PI/2 ){ | |
1088 | + return 4; | |
1089 | + } | |
1090 | + else if( rotation_y > 0.0f ){ //倒れ始めていれば、そのまま倒れる。 | |
1091 | + if( rotation_y < (float)M_PI/2 ){ | |
1092 | + rotation_y += (float)M_PI/180*6; | |
1093 | + return 2; | |
1094 | + } | |
1095 | + return 3; | |
1096 | + } | |
1097 | + else if( rotation_y < 0.0f ){ //倒れ始めていれば、そのまま倒れる。 | |
1098 | + if( rotation_y > (float)M_PI/2 * -1 ){ | |
1099 | + rotation_y -= (float)M_PI/180*6; | |
1100 | + return 2; | |
1101 | + } | |
1102 | + return 3; | |
1103 | + } | |
1104 | + else if( hp <= 0 ){ //HPが 0 以下になった(死亡した)瞬間なら、倒し始める | |
1105 | + //体の角度・腕の角度 | |
1106 | + switch( GetRand(4) ){ | |
1107 | + case 0: | |
1108 | + rotation_y = (float)M_PI/180*6; | |
1109 | + armrotation_y = (float)M_PI/2; | |
1110 | + break; | |
1111 | + case 1: | |
1112 | + rotation_y = (float)M_PI/180*6 * -1; | |
1113 | + armrotation_y = (float)M_PI/2; | |
1114 | + break; | |
1115 | + case 2: | |
1116 | + rotation_y = (float)M_PI/180*6; | |
1117 | + armrotation_y = (float)M_PI/2 * -1; | |
1118 | + break; | |
1119 | + case 3: | |
1120 | + rotation_y = (float)M_PI/180*6 * -1; | |
1121 | + armrotation_y = (float)M_PI/2 * -1; | |
1122 | + break; | |
1123 | + } | |
1124 | + | |
1125 | + //死体が埋まらぬよう、高さを +1.0 する | |
1126 | + pos_y += 1.0f; | |
1127 | + | |
1128 | + //所持している武器を全て捨てる | |
1129 | + for(int i=0; i<TOTAL_HAVEWEAPON; i++){ | |
1130 | + if( weapon[i] != NULL ){ | |
1131 | + weapon[i]->Dropoff(pos_x, pos_y, pos_z, (float)M_PI/18*GetRand(36), 1.5f); | |
1132 | + weapon[i] = NULL; | |
1133 | + } | |
1134 | + } | |
1135 | + | |
1136 | + //スコープモードを解除 | |
1137 | + SetDisableScope(); | |
1138 | + | |
1139 | + return 1; | |
1140 | + } | |
1141 | + | |
1142 | + return 0; | |
1143 | +#endif | |
1144 | +} | |
1145 | + | |
1146 | +//! @brief 操作による移動計算 | |
1147 | +//! @attention 実行すると、各キーフラグは false に初期化されます。 | |
1148 | +void human::ControlProcess() | |
1149 | +{ | |
1150 | + //進行方向と速度を決定 | |
1151 | + if( GetFlag(MoveFlag, MOVEFLAG_WALK) ){ | |
1152 | + move_rx = 0.0f; | |
1153 | + AddPosOrder(rotation_x*-1 + move_rx + (float)M_PI/2, 0.0f, HUMAN_PROGRESSWALK_ACCELERATION); | |
1154 | + walkcnt += 1; | |
1155 | + runcnt = 0; | |
1156 | + } | |
1157 | + else if( GetFlag(MoveFlag, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) == MOVEFLAG_FORWARD ){ | |
1158 | + move_rx = 0.0f; | |
1159 | + AddPosOrder(rotation_x*-1 + move_rx + (float)M_PI/2, 0.0f, HUMAN_PROGRESSRUN_ACCELERATION); | |
1160 | + walkcnt = 0; | |
1161 | + runcnt += 1; | |
1162 | + } | |
1163 | + else if( GetFlag(MoveFlag, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) == MOVEFLAG_BACK ){ | |
1164 | + move_rx = (float)M_PI; | |
1165 | + AddPosOrder(rotation_x*-1 + move_rx + (float)M_PI/2, 0.0f, HUMAN_REGRESSRUN_ACCELERATION); | |
1166 | + walkcnt = 0; | |
1167 | + runcnt += 1; | |
1168 | + } | |
1169 | + else if( GetFlag(MoveFlag, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) == MOVEFLAG_LEFT ){ | |
1170 | + move_rx = (float)M_PI/2; | |
1171 | + AddPosOrder(rotation_x*-1 + move_rx + (float)M_PI/2, 0.0f, HUMAN_SIDEWAYSRUN_ACCELERATION); | |
1172 | + walkcnt = 0; | |
1173 | + runcnt += 1; | |
1174 | + } | |
1175 | + else if( GetFlag(MoveFlag, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) == MOVEFLAG_RIGHT ){ | |
1176 | + move_rx = (float)M_PI/2 * -1; | |
1177 | + AddPosOrder(rotation_x*-1 + move_rx + (float)M_PI/2, 0.0f, HUMAN_SIDEWAYSRUN_ACCELERATION); | |
1178 | + walkcnt = 0; | |
1179 | + runcnt += 1; | |
1180 | + } | |
1181 | + else if( GetFlag(MoveFlag, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) == (MOVEFLAG_FORWARD | MOVEFLAG_LEFT) ){ | |
1182 | + move_rx = (float)M_PI/4; | |
1183 | + AddPosOrder(rotation_x*-1 + move_rx + (float)M_PI/2, 0.0f, HUMAN_PROGRESSRUN_SIDEWAYSRUN_ACCELERATION); | |
1184 | + walkcnt = 0; | |
1185 | + runcnt += 1; | |
1186 | + } | |
1187 | + else if( GetFlag(MoveFlag, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) == (MOVEFLAG_BACK | MOVEFLAG_LEFT) ){ | |
1188 | + move_rx = (float)M_PI/4*3; | |
1189 | + AddPosOrder(rotation_x*-1 + move_rx + (float)M_PI/2, 0.0f, HUMAN_REGRESSRUN_SIDEWAYSRUN_ACCELERATION); | |
1190 | + walkcnt = 0; | |
1191 | + runcnt += 1; | |
1192 | + } | |
1193 | + else if( GetFlag(MoveFlag, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) == (MOVEFLAG_BACK | MOVEFLAG_RIGHT) ){ | |
1194 | + move_rx = (float)M_PI/4*3 * -1; | |
1195 | + AddPosOrder(rotation_x*-1 + move_rx + (float)M_PI/2, 0.0f, HUMAN_REGRESSRUN_SIDEWAYSRUN_ACCELERATION); | |
1196 | + walkcnt = 0; | |
1197 | + runcnt += 1; | |
1198 | + } | |
1199 | + else if( GetFlag(MoveFlag, (MOVEFLAG_FORWARD | MOVEFLAG_BACK | MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) == (MOVEFLAG_FORWARD | MOVEFLAG_RIGHT) ){ | |
1200 | + move_rx = (float)M_PI/4 * -1; | |
1201 | + AddPosOrder(rotation_x*-1 + move_rx + (float)M_PI/2, 0.0f, HUMAN_PROGRESSRUN_SIDEWAYSRUN_ACCELERATION); | |
1202 | + walkcnt = 0; | |
1203 | + runcnt += 1; | |
1204 | + } | |
1205 | + else{ | |
1206 | + move_rx = 0.0f; | |
1207 | + walkcnt = 0; | |
1208 | + runcnt = 0; | |
1209 | + } | |
1210 | + | |
1211 | + //フラグをバックアップ | |
1212 | + MoveFlag_lt = MoveFlag; | |
1213 | + | |
1214 | + //キーフラグを元に戻す | |
1215 | + MoveFlag = 0x00; | |
1216 | +} | |
1217 | + | |
1218 | +//! @brief 特定の方向(ベクトル)に対して、ブロックの面が表面か裏面か調べる | |
1219 | +//! @param inblockdata BlockDataInterfaceクラスのポインタ | |
1220 | +//! @param bid 判定するブロック番号 | |
1221 | +//! @param fid 判定する面番号 | |
1222 | +//! @param vx X軸ベクトルのポインタ | |
1223 | +//! @param vz Z軸ベクトルのポインタ | |
1224 | +//! @return 表向き:true 裏向き:false | |
1225 | +bool human::CheckBlockAngle(class BlockDataInterface *inblockdata, int bid, int fid, float vx, float vz) | |
1226 | +{ | |
1227 | + if( inblockdata == NULL ){ return false; } | |
1228 | + if( (bid < 0)||(inblockdata->GetTotaldatas() <= bid) ){ return false; } | |
1229 | + | |
1230 | + float costheta; | |
1231 | + struct blockdata bdata; | |
1232 | + | |
1233 | + inblockdata->Getdata(&bdata, bid); | |
1234 | + costheta = (vx * bdata.material[fid].vx + vz * bdata.material[fid].vz) / (sqrt(vx * vx + vz * vz) * sqrt(bdata.material[fid].vx * bdata.material[fid].vx + bdata.material[fid].vz * bdata.material[fid].vz)); | |
1235 | + if( acos(costheta) > (float)M_PI/2 ){ | |
1236 | + return true; | |
1237 | + } | |
1238 | + return false; | |
1239 | +} | |
1240 | + | |
1241 | +//! @brief マップとの当たり判定 | |
1242 | +//! @param CollD Collisionクラスのポインタ | |
1243 | +//! @param inblockdata BlockDataInterfaceクラスのポインタ | |
1244 | +//! @param FallDist Y軸の移動量を取得するポインタ | |
1245 | +//! @return ブロックに埋まっている:true 埋まっていない:false | |
1246 | +bool human::MapCollisionDetection(class Collision *CollD, class BlockDataInterface *inblockdata, float *FallDist) | |
1247 | +{ | |
1248 | + bool inside = false; | |
1249 | + int id; | |
1250 | + int face; | |
1251 | + float vx, vz; | |
1252 | + float vy = 0.1f; | |
1253 | + float speed; | |
1254 | + float Dist; | |
1255 | + float FallDistance; | |
1256 | + float offset; | |
1257 | + | |
1258 | + //足元ギリギリは当たり判定から除外する | |
1259 | + offset = 0.1f; | |
1260 | + | |
1261 | + // 上下方向のあたり判定(ジャンプ・自然落下) | |
1262 | + //-------------------------------------------------- | |
1263 | + | |
1264 | + //足元がブロックに埋まっていなければ | |
1265 | + if( CollD->CheckALLBlockInside(pos_x, pos_y + offset, pos_z) == false ){ | |
1266 | + //落下速度を計算 | |
1267 | + move_y -= HUMAN_DAMAGE_SPEED; | |
1268 | + if( move_y < HUMAN_DAMAGE_MAXSPEED ){ move_y = HUMAN_DAMAGE_MAXSPEED; } | |
1269 | + | |
1270 | + if( move_y > 0.0f ){ | |
1271 | + //上方向へ当たり判定 | |
1272 | + if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + HUMAN_HEIGTH, pos_z, 0, 1, 0, NULL, NULL, &Dist, move_y) == true ){ | |
1273 | + CollD->CheckALLBlockIntersectRay(pos_x, pos_y + HUMAN_HEIGTH, pos_z, 0, 1, 0, NULL, NULL, &Dist, move_y); | |
1274 | + | |
1275 | + FallDistance = Dist; | |
1276 | + move_y = 0.0f; | |
1277 | + } | |
1278 | + else{ | |
1279 | + FallDistance = move_y; | |
1280 | + } | |
1281 | + FallDistance = move_y; | |
1282 | + move_y_flag = true; | |
1283 | + } | |
1284 | + else{ | |
1285 | + int id, face; | |
1286 | + struct blockdata bdata; | |
1287 | + | |
1288 | + //下方向へ当たり判定 | |
1289 | + if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + offset, pos_z, 0, -1, 0, NULL, NULL, &Dist, move_y*-1 + offset) == true ){ | |
1290 | + CollD->CheckALLBlockIntersectRay(pos_x, pos_y + offset, pos_z, 0, -1, 0, &id, &face, &Dist, move_y + offset); | |
1291 | + | |
1292 | + if( Invincible == false ){ | |
1293 | + //ダメージ計算 | |
1294 | + if( move_y > HUMAN_DAMAGE_MINSPEED ){ hp -= 0; } | |
1295 | + else{ hp -= (int)((float)HUMAN_DAMAGE_MAXFALL / abs(HUMAN_DAMAGE_MAXSPEED - (HUMAN_DAMAGE_MINSPEED)) * abs(move_y - (HUMAN_DAMAGE_MINSPEED))); } | |
1296 | + } | |
1297 | + | |
1298 | + FallDistance = (Dist - offset) * -1; | |
1299 | + move_y = 0.0f; | |
1300 | + | |
1301 | + inblockdata->Getdata(&bdata, id); | |
1302 | + | |
1303 | + //斜面に立っているなら | |
1304 | + if( acos(bdata.material[face].vy) > HUMAN_MAPCOLLISION_SLOPEANGLE ){ | |
1305 | + //地面と認めない (ジャンプ対策) | |
1306 | + move_y_flag = true; | |
1307 | + | |
1308 | + //押し出す | |
1309 | + move_x += bdata.material[face].vx * HUMAN_MAPCOLLISION_SLOPEFORCE; | |
1310 | + move_z += bdata.material[face].vz * HUMAN_MAPCOLLISION_SLOPEFORCE; | |
1311 | + } | |
1312 | + else{ | |
1313 | + move_y_flag = false; | |
1314 | + } | |
1315 | + } | |
1316 | + else{ | |
1317 | + FallDistance = move_y; | |
1318 | + move_y_flag = true; | |
1319 | + } | |
1320 | + } | |
1321 | + } | |
1322 | + else{ //埋まっている | |
1323 | + FallDistance = move_y; | |
1324 | + move_y = 0.0f; | |
1325 | + move_y_flag = false; | |
1326 | + } | |
1327 | + | |
1328 | + | |
1329 | + // 水平方向のあたり判定(移動) | |
1330 | + //-------------------------------------------------- | |
1331 | + | |
1332 | + if( (move_x*move_x + move_z*move_z) ){ | |
1333 | + int surface; | |
1334 | + float ang = atan2(move_z, move_x); | |
1335 | + float newpos_x, newpos_y, newpos_z; | |
1336 | + | |
1337 | + //腰付近を当たり判定 | |
1338 | + for(int i=0; i<MAX_BLOCKS; i++){ | |
1339 | + surface = -1; | |
1340 | + CollD->CheckBlockInside(i, pos_x, pos_y + HUMAN_MAPCOLLISION_HEIGTH, pos_z, false, &surface); | |
1341 | + | |
1342 | + if( surface != -1 ){ | |
1343 | + //HUMAN_MAPCOLLISION_R 分の先を調べる | |
1344 | + if( CollD->CheckBlockInside(i, pos_x + cos(ang)*HUMAN_MAPCOLLISION_R, pos_y + HUMAN_MAPCOLLISION_HEIGTH, pos_z + sin(ang)*HUMAN_MAPCOLLISION_R, true, NULL) == true ){ | |
1345 | + CollD->ScratchVector(inblockdata, i, surface, move_x, vy, move_z, &move_x, &vy, &move_z); | |
1346 | + } | |
1347 | + | |
1348 | + //左右90度づつを調べる | |
1349 | + if( CollD->CheckBlockInside(i, pos_x + cos(ang + (float)M_PI/2)*HUMAN_MAPCOLLISION_R, pos_y + HUMAN_MAPCOLLISION_HEIGTH, pos_z + sin(ang + (float)M_PI/2)*HUMAN_MAPCOLLISION_R, true, NULL) == true ){ | |
1350 | + if( CheckBlockAngle(inblockdata, i, surface, cos(ang), sin(ang)) == true ){ //進行方向に対して表向きなら〜 | |
1351 | + CollD->ScratchVector(inblockdata, i, surface, move_x, vy, move_z, &move_x, &vy, &move_z); | |
1352 | + } | |
1353 | + } | |
1354 | + if( CollD->CheckBlockInside(i, pos_x + cos(ang - (float)M_PI/2)*HUMAN_MAPCOLLISION_R, pos_y + HUMAN_MAPCOLLISION_HEIGTH, pos_z + sin(ang - (float)M_PI/2)*HUMAN_MAPCOLLISION_R, true, NULL) == true ){ | |
1355 | + if( CheckBlockAngle(inblockdata, i, surface, cos(ang), sin(ang)) == true ){ //進行方向に対して表向きなら〜 | |
1356 | + CollD->ScratchVector(inblockdata, i, surface, move_x, vy, move_z, &move_x, &vy, &move_z); | |
1357 | + } | |
1358 | + } | |
1359 | + } | |
1360 | + } | |
1361 | + | |
1362 | + //進行方向を示すベクトルを算出 | |
1363 | + vx = move_x; | |
1364 | + vz = move_z; | |
1365 | + speed = sqrt(vx*vx + vz*vz); | |
1366 | + if( speed > 0.0f ){ | |
1367 | + vx = vx / speed; | |
1368 | + vz = vz / speed; | |
1369 | + } | |
1370 | + | |
1371 | + //頭を当たり判定 | |
1372 | + if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + HUMAN_HEIGTH, pos_z, vx, 0, vz, NULL, NULL, &Dist, speed) == true ){ | |
1373 | + CollD->CheckALLBlockIntersectRay(pos_x, pos_y + FallDistance + HUMAN_HEIGTH, pos_z, vx, 0, vz, &id, &face, &Dist, speed); | |
1374 | + CollD->ScratchVector(inblockdata, id, face, move_x, vy, move_z, &move_x, &vy, &move_z); | |
1375 | + } | |
1376 | + | |
1377 | + //足元がブロックに埋まっていなければ | |
1378 | + if( CollD->CheckALLBlockInside(pos_x, pos_y + offset, pos_z) == false ){ | |
1379 | + | |
1380 | + //進行方向を示すベクトルを算出 | |
1381 | + vx = move_x; | |
1382 | + vz = move_z; | |
1383 | + speed = sqrt(vx*vx + vz*vz); | |
1384 | + if( speed > 0.0f ){ | |
1385 | + vx = vx / speed; | |
1386 | + vz = vz / speed; | |
1387 | + } | |
1388 | + | |
1389 | + //足元を当たり判定 | |
1390 | + if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + offset, pos_z, vx, 0, vz, NULL, NULL, &Dist, speed) == true ){ | |
1391 | + CollD->CheckALLBlockIntersectRay(pos_x, pos_y + offset, pos_z, vx, 0, vz, &id, &face, &Dist, speed); | |
1392 | + | |
1393 | + struct blockdata bdata; | |
1394 | + inblockdata->Getdata(&bdata, id); | |
1395 | + | |
1396 | + if( acos(bdata.material[face].vy) > HUMAN_MAPCOLLISION_SLOPEANGLE ){ //斜面〜壁なら | |
1397 | + //乗り越えられる高さか調べる | |
1398 | + if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y + 3.5f + offset, pos_z, vx, 0, vz, NULL, NULL, &Dist, speed) == false ){ | |
1399 | + //人を上に持ち上げる | |
1400 | + FallDistance = 0.4f; | |
1401 | + move_y = 0.0f; | |
1402 | + } | |
1403 | + | |
1404 | + //足元を当たり判定 | |
1405 | + CollD->ScratchVector(inblockdata, id, face, move_x, vy, move_z, &move_x, &vy, &move_z); | |
1406 | + } | |
1407 | + else{ //水平〜斜面なら | |
1408 | + //地面と認めない (ジャンプ対策) | |
1409 | + move_y_flag = true; | |
1410 | + | |
1411 | + //移動先の位置を計算 | |
1412 | + newpos_x = pos_x + move_x; | |
1413 | + newpos_y = pos_y + FallDistance; | |
1414 | + newpos_z = pos_z + move_z; | |
1415 | + | |
1416 | + //移動先の高さを調べる | |
1417 | + if( CollD->CheckALLBlockInside(newpos_x, newpos_y + HUMAN_HEIGTH, newpos_z) == false ){ | |
1418 | + if( CollD->CheckALLBlockIntersectRay(newpos_x, newpos_y + HUMAN_HEIGTH, newpos_z, 0, -1, 0, NULL, NULL, &Dist, HUMAN_HEIGTH) == true ){ | |
1419 | + float height = HUMAN_HEIGTH - Dist; | |
1420 | + | |
1421 | + //人を上に持ち上げる | |
1422 | + if( height > 0.9f ){ | |
1423 | + FallDistance = 0.4f; | |
1424 | + } | |
1425 | + else{ | |
1426 | + FallDistance = height; | |
1427 | + } | |
1428 | + | |
1429 | + move_y = 0.0f; | |
1430 | + } | |
1431 | + } | |
1432 | + } | |
1433 | + } | |
1434 | + } | |
1435 | + | |
1436 | + //移動先の位置を計算 | |
1437 | + newpos_x = pos_x + move_x; | |
1438 | + newpos_y = pos_y + FallDistance; | |
1439 | + newpos_z = pos_z + move_z; | |
1440 | + | |
1441 | + //全身を改めて確認 | |
1442 | + if( | |
1443 | + (CollD->CheckALLBlockInside(newpos_x, newpos_y + offset, newpos_z) == true)|| | |
1444 | + (CollD->CheckALLBlockIntersectRay(newpos_x, newpos_y + offset, newpos_z, 0, 1, 0, NULL, NULL, &Dist, HUMAN_HEIGTH - offset - 1.0f) == true) | |
1445 | + ){ | |
1446 | + //めり込むなら移動しない | |
1447 | + move_x = 0.0f; | |
1448 | + move_z = 0.0f; | |
1449 | + inside = true; | |
1450 | + } | |
1451 | + } | |
1452 | + | |
1453 | + *FallDist = FallDistance; | |
1454 | + return inside; | |
1455 | +} | |
1456 | + | |
1457 | +//! @brief 計算を実行(当たり判定) | |
1458 | +//! @param CollD Collisionのポインタ | |
1459 | +//! @param inblockdata BlockDataInterfaceのポインタ | |
1460 | +//! @param F5mode 上昇機能(F5裏技)のフラグ (有効:true 無効:false) | |
1461 | +//! @return 処理なし:0 通常処理:1 死亡して倒れ終わった直後:2 静止した死体:3 | |
1462 | +int human::RunFrame(class Collision *CollD, class BlockDataInterface *inblockdata, bool F5mode) | |
1463 | +{ | |
1464 | + if( CollD == NULL ){ return 0; } | |
1465 | + if( RenderFlag == false ){ return 0; } | |
1466 | + | |
1467 | +#ifdef HUMAN_DEADBODY_COLLISION | |
1468 | + if( deadstate == 5 ){ return 3; } | |
1469 | +#else | |
1470 | + if( hp <= 0 ){ return 3; } | |
1471 | +#endif | |
1472 | + | |
1473 | + float FallDistance; | |
1474 | + int CheckDead; | |
1475 | + | |
1476 | + //武器切り替えカウント | |
1477 | + if( selectweaponcnt > 0 ){ | |
1478 | + selectweaponcnt -= 1; | |
1479 | + } | |
1480 | + | |
1481 | + //発砲による反動 | |
1482 | + if( reaction_y > 0.0f ){ | |
1483 | + if( reaction_y > (float)M_PI/180*2 ){ reaction_y -= (float)M_PI/180*2; } | |
1484 | + else{ reaction_y = 0.0f; } | |
1485 | + } | |
1486 | + if( reaction_y < 0.0f ){ | |
1487 | + if( reaction_y < (float)M_PI/180*2 ){ reaction_y += (float)M_PI/180*2; } | |
1488 | + else{ reaction_y = 0.0f; } | |
1489 | + } | |
1490 | + | |
1491 | + //リロード中なら腕の角度を再設定 | |
1492 | + if( weapon[selectweapon] != NULL ){ | |
1493 | + if( weapon[selectweapon]->GetReloadCnt() > 0 ){ | |
1494 | + reaction_y = ARMRAD_RELOADWEAPON; | |
1495 | + } | |
1496 | + } | |
1497 | + | |
1498 | + //足の角度を、-90度〜90度の範囲に設定 | |
1499 | + if( hp <= 0 ){ | |
1500 | + legrotation_x = 0.0f; | |
1501 | + } | |
1502 | + else{ | |
1503 | + float add_legrx; | |
1504 | + | |
1505 | + //目標値を設定 | |
1506 | + if( fabs(move_rx) > (float)M_PI/2 ){ | |
1507 | + add_legrx = move_rx + (float)M_PI - legrotation_x; | |
1508 | + } | |
1509 | + else{ | |
1510 | + add_legrx = move_rx - legrotation_x; | |
1511 | + } | |
1512 | + for(; add_legrx > (float)M_PI; add_legrx -= (float)M_PI*2){} | |
1513 | + for(; add_legrx < (float)M_PI*-1; add_legrx += (float)M_PI*2){} | |
1514 | + | |
1515 | + //補正していく | |
1516 | + if( add_legrx > (float)M_PI/18 ){ legrotation_x += (float)M_PI/18; } | |
1517 | + else if( add_legrx < (float)M_PI/18*-1 ){ legrotation_x -= (float)M_PI/18; } | |
1518 | + else{ legrotation_x += add_legrx; } | |
1519 | + } | |
1520 | + | |
1521 | + //照準の状態誤差の処理 | |
1522 | + GunsightErrorRange(); | |
1523 | + | |
1524 | + //死亡判定と倒れる処理 | |
1525 | + CheckDead = CheckAndProcessDead(CollD); | |
1526 | + if( CheckDead == 3 ){ return 2; } | |
1527 | + if( CheckDead != 0 ){ return 3; } | |
1528 | + | |
1529 | + //進行方向と速度を決定 | |
1530 | + ControlProcess(); | |
1531 | + | |
1532 | + //マップとの当たり判定 | |
1533 | + MapCollisionDetection(CollD, inblockdata, &FallDistance); | |
1534 | + | |
1535 | + //移動するなら | |
1536 | + if( (move_x*move_x + move_z*move_z) > 0.0f * 0.0f ){ | |
1537 | + totalmove += sqrt(move_x*move_x + move_z*move_z); | |
1538 | + } | |
1539 | + | |
1540 | + //座標移動 | |
1541 | + pos_x += move_x; | |
1542 | + pos_z += move_z; | |
1543 | + | |
1544 | + //移動量を減衰 | |
1545 | + move_x *= HUMAN_ATTENUATION; | |
1546 | + move_z *= HUMAN_ATTENUATION; | |
1547 | + | |
1548 | + //F5を使用していなければ、計算結果を反映 | |
1549 | + if( F5mode == false ){ | |
1550 | + pos_y += FallDistance; | |
1551 | + } | |
1552 | + else{ | |
1553 | + move_y = 0.0f; | |
1554 | + pos_y += 5.0f; //使用していれば、強制的に上昇 | |
1555 | + } | |
1556 | + | |
1557 | + | |
1558 | + //-100.0より下に落ちたら、死亡 | |
1559 | + if( pos_y < HUMAN_DEADLINE ){ | |
1560 | + pos_y = HUMAN_DEADLINE; | |
1561 | + hp = 0; | |
1562 | + } | |
1563 | + | |
1564 | + return 1; | |
1565 | +} | |
1566 | + | |
1567 | +//! @brief 標準誤差を取得 | |
1568 | +int human::GetGunsightErrorRange() | |
1569 | +{ | |
1570 | + return StateGunsightErrorRange + ReactionGunsightErrorRange; | |
1571 | +} | |
1572 | + | |
1573 | +//! @brief 描画 | |
1574 | +//! @param d3dg D3DGraphicsのポインタ | |
1575 | +//! @param Resource ResourceManagerのポインタ | |
1576 | +//! @param DrawArm 腕と武器のみ描画する | |
1577 | +//! @param player 対象の人物がプレイヤーかどうか | |
1578 | +//! @todo 腕の位置を行列で求める | |
1579 | +//! @todo 死体の部位の高さ(Y軸)がおかしい | |
1580 | +void human::Render(class D3DGraphics *d3dg, class ResourceManager *Resource, bool DrawArm, bool player) | |
1581 | +{ | |
1582 | + //正しく初期化されていなければ、処理しない | |
1583 | + if( d3dg == NULL ){ return; } | |
1584 | + if( RenderFlag == false ){ return; } | |
1585 | + | |
1586 | + //現在装備する武器のクラスを取得 | |
1587 | + class weapon *nowweapon; | |
1588 | + nowweapon = weapon[selectweapon]; | |
1589 | + | |
1590 | + if( DrawArm == false ){ | |
1591 | + int legmodelid; | |
1592 | + | |
1593 | + //上半身を描画 | |
1594 | + d3dg->SetWorldTransform(pos_x, pos_y - 1.0f, pos_z, rotation_x + (float)M_PI, rotation_y, upmodel_size); | |
1595 | + d3dg->RenderModel(id_upmodel, id_texture); | |
1596 | + | |
1597 | + //足のモデルを設定 | |
1598 | + legmodelid = id_legmodel; //立ち止まり | |
1599 | + if( GetFlag(MoveFlag_lt, MOVEFLAG_WALK) ){ | |
1600 | + legmodelid = id_walkmodel[ (walkcnt/3 % TOTAL_WALKMODE) ]; //歩き | |
1601 | + } | |
1602 | + if( GetFlag(MoveFlag_lt, (MOVEFLAG_LEFT | MOVEFLAG_RIGHT)) ){ | |
1603 | + legmodelid = id_runmodel[ (runcnt/3 % TOTAL_RUNMODE) ]; //左右走り | |
1604 | + } | |
1605 | + if( GetFlag(MoveFlag_lt, MOVEFLAG_FORWARD) ){ | |
1606 | + legmodelid = id_runmodel[ (runcnt/2 % TOTAL_RUNMODE) ]; //前走り | |
1607 | + } | |
1608 | + if( GetFlag(MoveFlag_lt, MOVEFLAG_BACK) ){ | |
1609 | + legmodelid = id_runmodel[ (runcnt/4 % TOTAL_RUNMODE) ]; //後ろ走り | |
1610 | + } | |
1611 | + | |
1612 | + //足を描画 | |
1613 | + d3dg->SetWorldTransform(pos_x, pos_y, pos_z, rotation_x + (float)M_PI + legrotation_x*-1, rotation_y, legmodel_size); | |
1614 | + d3dg->RenderModel(legmodelid, id_texture); | |
1615 | + } | |
1616 | + | |
1617 | + //腕を描画 | |
1618 | + if( rotation_y != 0.0f ){ //死亡して倒れている or 倒れ始めた | |
1619 | + float x = pos_x + cos(rotation_x*-1 - (float)M_PI/2)*sin(rotation_y)*16.0f; | |
1620 | + float y = pos_y + cos(rotation_y)*16.0f; | |
1621 | + float z = pos_z + sin(rotation_x*-1 - (float)M_PI/2)*sin(rotation_y)*16.0f; | |
1622 | + d3dg->SetWorldTransform(x, y, z, rotation_x + (float)M_PI, armrotation_y + rotation_y, armmodel_size); | |
1623 | + d3dg->RenderModel(id_armmodel[0], id_texture); | |
1624 | + } | |
1625 | + else if( nowweapon == NULL ){ //手ぶら | |
1626 | + float ry; | |
1627 | + if( player == true ){ | |
1628 | + ry = ARMRAD_NOWEAPON; | |
1629 | + } | |
1630 | + else{ | |
1631 | + ry = armrotation_y; | |
1632 | + } | |
1633 | + d3dg->SetWorldTransform(pos_x, pos_y + 16.0f, pos_z, rotation_x + (float)M_PI, ry, armmodel_size); | |
1634 | + d3dg->RenderModel(id_armmodel[0], id_texture); | |
1635 | + } | |
1636 | + else{ //何か武器を持っている | |
1637 | + //武器のモデルとテクスチャを取得 | |
1638 | + int id_param; | |
1639 | + int armmodelid = 0; | |
1640 | + WeaponParameter paramdata; | |
1641 | + int model, texture; | |
1642 | + float ry = 0.0f; | |
1643 | + nowweapon->GetParamData(&id_param, NULL, NULL); | |
1644 | + Param->GetWeapon(id_param, ¶mdata); | |
1645 | + Resource->GetWeaponModelTexture(id_param, &model, &texture); | |
1646 | + | |
1647 | + //腕の形と角度を決定 | |
1648 | + if( paramdata.WeaponP == 0 ){ | |
1649 | + armmodelid = 1; | |
1650 | + ry = armrotation_y + reaction_y; | |
1651 | + } | |
1652 | + if( paramdata.WeaponP == 1 ){ | |
1653 | + armmodelid = 2; | |
1654 | + ry = armrotation_y + reaction_y; | |
1655 | + } | |
1656 | + if( paramdata.WeaponP == 2 ){ | |
1657 | + armmodelid = 0; | |
1658 | + ry = ARMRAD_NOWEAPON; | |
1659 | + } | |
1660 | + | |
1661 | + //腕を描画 | |
1662 | + d3dg->SetWorldTransform(pos_x, pos_y + 16.0f, pos_z, rotation_x + (float)M_PI, ry, armmodel_size); | |
1663 | + d3dg->RenderModel(id_armmodel[armmodelid], id_texture); | |
1664 | + | |
1665 | + //武器を描画 | |
1666 | + d3dg->SetWorldTransformHumanWeapon(pos_x, pos_y + 16.0f, pos_z, paramdata.mx/10*-1, paramdata.my/10, paramdata.mz/10*-1, rotation_x + (float)M_PI, ry, paramdata.size); | |
1667 | + d3dg->RenderModel(model, texture); | |
1668 | + } | |
1669 | +} | |
1670 | + | |
1671 | +//! @brief コンストラクタ | |
1672 | +weapon::weapon(class ParameterInfo *in_Param, float x, float y, float z, float rx, int id_param, int nbs, bool flag) | |
1673 | +{ | |
1674 | + Param = in_Param; | |
1675 | + pos_x = x; | |
1676 | + pos_y = y; | |
1677 | + pos_z = z; | |
1678 | + move_x = 0.0f; | |
1679 | + move_y = 0.0f; | |
1680 | + move_z = 0.0f; | |
1681 | + rotation_x = rx; | |
1682 | + RenderFlag = flag; | |
1683 | + | |
1684 | + id_parameter = id_param; | |
1685 | + usingflag = false; | |
1686 | + bullets = nbs; | |
1687 | + Loadbullets = 0; | |
1688 | + shotcnt = 0; | |
1689 | + motionflag = true; | |
1690 | + | |
1691 | + if( Param != NULL ){ | |
1692 | + WeaponParameter ParamData; | |
1693 | + if( Param->GetWeapon(id_param, &ParamData) == 0 ){ | |
1694 | + model_size = ParamData.size; | |
1695 | + //id_model = ParamData.id_model; | |
1696 | + //id_texture = ParamData.id_texture; | |
1697 | + } | |
1698 | + } | |
1699 | + id_model = -1; | |
1700 | + id_texture = -1; | |
1701 | +} | |
1702 | + | |
1703 | +//! @brief ディストラクタ | |
1704 | +weapon::~weapon() | |
1705 | +{} | |
1706 | + | |
1707 | +//! @brief 座標と角度を設定 | |
1708 | +//! @param x X座標 | |
1709 | +//! @param y Y座標 | |
1710 | +//! @param z Z座標 | |
1711 | +//! @param rx 横軸回転 | |
1712 | +void weapon::SetPosData(float x, float y, float z, float rx) | |
1713 | +{ | |
1714 | + pos_x = x; | |
1715 | + pos_y = y; | |
1716 | + pos_z = z; | |
1717 | + move_x = 0.0f; | |
1718 | + move_y = 0.0f; | |
1719 | + move_z = 0.0f; | |
1720 | + rotation_x = rx; | |
1721 | +} | |
1722 | + | |
1723 | +//! @brief 設定値を設定 | |
1724 | +//! @param id_param 武器の種類番号 | |
1725 | +//! @param lnbs 装弾数 | |
1726 | +//! @param nbs 合計弾数 | |
1727 | +//! @param init オブジェクトを初期化 | |
1728 | +void weapon::SetParamData(int id_param, int lnbs, int nbs, bool init) | |
1729 | +{ | |
1730 | + id_parameter = id_param; | |
1731 | + bullets = nbs; | |
1732 | + Loadbullets = lnbs; | |
1733 | + | |
1734 | + if( init == true ){ | |
1735 | + usingflag = false; | |
1736 | + shotcnt = 0; | |
1737 | + reloadcnt = 0; | |
1738 | + motionflag = true; | |
1739 | + } | |
1740 | +} | |
1741 | + | |
1742 | +//! @brief 設定値を取得 | |
1743 | +//! @param id_param 武器の種類番号を受け取るポインタ(NULL可) | |
1744 | +//! @param lnbs 装弾数を受け取るポインタ(NULL可) | |
1745 | +//! @param nbs 合計弾数を受け取るポインタ(NULL可) | |
1746 | +void weapon::GetParamData(int *id_param, int *lnbs, int *nbs) | |
1747 | +{ | |
1748 | + if( id_param != NULL ){ *id_param = id_parameter; } | |
1749 | + if( lnbs != NULL ){ *lnbs = Loadbullets; } | |
1750 | + if( nbs != NULL ){ *nbs = bullets; } | |
1751 | +} | |
1752 | + | |
1753 | +//! @brief 武器の使用状況の取得 | |
1754 | +//! @return 使用中:true 未使用:false | |
1755 | +bool weapon::GetUsingFlag() | |
1756 | +{ | |
1757 | + return usingflag; | |
1758 | +} | |
1759 | + | |
1760 | +//! @brief 武器を拾う | |
1761 | +//! @return 成功:0 失敗:1 | |
1762 | +int weapon::Pickup() | |
1763 | +{ | |
1764 | + if( usingflag == true ){ return 1; } | |
1765 | + usingflag = true; | |
1766 | + return 0; | |
1767 | +} | |
1768 | + | |
1769 | +//! @brief 武器を捨てる | |
1770 | +//! @param x X座標 | |
1771 | +//! @param y Y座標 | |
1772 | +//! @param z Z座標 | |
1773 | +//! @param rx 横軸回転 | |
1774 | +//! @param speed 捨てる初速 | |
1775 | +void weapon::Dropoff(float x, float y, float z, float rx, float speed) | |
1776 | +{ | |
1777 | + //表示する座標と角度を設定 | |
1778 | + move_x = cos(rx*-1 + (float)M_PI/2) * speed; | |
1779 | + move_y = 0.0f; | |
1780 | + move_z = sin(rx*-1 + (float)M_PI/2) * speed; | |
1781 | + pos_x = x + cos(rx*-1 + (float)M_PI/2) * 5.0f; | |
1782 | + pos_y = y + 16.0f + move_y; | |
1783 | + pos_z = z + sin(rx*-1 + (float)M_PI/2) * 5.0f; | |
1784 | + rotation_x = rx + (float)M_PI; | |
1785 | + | |
1786 | + //未使用(未装備)に設定し、座標移動を有効に | |
1787 | + usingflag = false; | |
1788 | + motionflag = true; | |
1789 | +} | |
1790 | + | |
1791 | +//! @brief 発砲 | |
1792 | +//! @return 成功:0 失敗:1 | |
1793 | +//! @attention 連射間隔も考慮されます。 | |
1794 | +//! @attention 関数が失敗するのは、いずれかの条件です。 「連射間隔に満たない」「リロード実行中」「弾がない」「無効な武器の種類が設定されている」 | |
1795 | +int weapon::Shot() | |
1796 | +{ | |
1797 | + //クラスが設定されていなければ失敗 | |
1798 | + if( Param == NULL ){ return 1; } | |
1799 | + | |
1800 | + //発射間隔に満たないか、リロード中か、弾が無ければ失敗 | |
1801 | + if( shotcnt > 0 ){ return 1; } | |
1802 | + if( reloadcnt > 0 ){ return 1; } | |
1803 | + if( Loadbullets == 0 ){ return 1; } | |
1804 | + | |
1805 | + //設定値を取得 | |
1806 | + WeaponParameter ParamData; | |
1807 | + if( Param->GetWeapon(id_parameter, &ParamData) == 1 ){ return 1; } | |
1808 | + | |
1809 | + //武器が手榴弾ならば〜 | |
1810 | + if( id_parameter == ID_WEAPON_GRENADE ){ | |
1811 | + //弾を減らし、連射カウントを設定 | |
1812 | + bullets -= 1; | |
1813 | + Loadbullets -= 1; | |
1814 | + shotcnt = ParamData.blazings; | |
1815 | + | |
1816 | + if( (bullets - Loadbullets) <= 0 ){ //(リロードしていない)弾が無くなれば、武器ごと消滅させる。 | |
1817 | + RenderFlag = false; | |
1818 | + usingflag = false; | |
1819 | + } | |
1820 | + else if( Loadbullets <= 0 ){ //自動リロード | |
1821 | + Loadbullets = 1; | |
1822 | + } | |
1823 | + return 0; | |
1824 | + } | |
1825 | + | |
1826 | + //弾を減らし、連射カウントを設定 | |
1827 | + Loadbullets -= 1; | |
1828 | + bullets -= 1; | |
1829 | + shotcnt = ParamData.blazings; | |
1830 | + return 0; | |
1831 | +} | |
1832 | + | |
1833 | +//! @brief リロードを開始 | |
1834 | +//! @return 成功:0 失敗:1 | |
1835 | +//! @attention リロード時間も考慮されます。 | |
1836 | +//! @attention 関数が失敗するのは、いずれかの条件です。 「リロード実行中」「弾がない」「無効な武器の種類が設定されている」 | |
1837 | +int weapon::StartReload() | |
1838 | +{ | |
1839 | + //クラスが設定されていなければ失敗 | |
1840 | + if( Param == NULL ){ return 1; } | |
1841 | + | |
1842 | + //リロード中か、弾が無ければ失敗 | |
1843 | + if( reloadcnt > 0 ){ return 1; } | |
1844 | + if( (bullets - Loadbullets) == 0 ){ return 1; } | |
1845 | + | |
1846 | + //武器の性能値を取得 | |
1847 | + WeaponParameter ParamData; | |
1848 | + if( Param->GetWeapon(id_parameter, &ParamData) != 0 ){ return 1; } | |
1849 | + | |
1850 | + //リロードカウントを設定 | |
1851 | + reloadcnt = ParamData.reloads + 1; | |
1852 | + return 0; | |
1853 | +} | |
1854 | + | |
1855 | +//! @brief リロードを実行 | |
1856 | +//! @attention StartReload()関数と異なり、瞬時に弾を補充します。リロード時間は考慮されません。 | |
1857 | +//! @attention リロード時間を考慮する場合、StartReload()関数を呼び出してください。この関数は自動的に実行されます。 | |
1858 | +int weapon::RunReload() | |
1859 | +{ | |
1860 | + //クラスが設定されていなければ失敗 | |
1861 | + if( Param == NULL ){ return 1; } | |
1862 | + | |
1863 | + //弾が無ければ失敗 | |
1864 | + if( (bullets - Loadbullets) == 0 ){ return 1; } | |
1865 | + | |
1866 | + //武器の性能値から、装填する弾数を取得 | |
1867 | + WeaponParameter ParamData; | |
1868 | + int nbsmax = 0; | |
1869 | + if( Param->GetWeapon(id_parameter, &ParamData) == 0 ){ | |
1870 | + nbsmax = ParamData.nbsmax; | |
1871 | + } | |
1872 | + | |
1873 | + if( (bullets - Loadbullets) < nbsmax ){ //残りの弾数より装填する弾数が多ければ | |
1874 | + bullets = (bullets - Loadbullets); | |
1875 | + Loadbullets = bullets; | |
1876 | + } | |
1877 | + else{ //残りの弾数の方が多ければ | |
1878 | + bullets -= Loadbullets; | |
1879 | + Loadbullets = nbsmax; | |
1880 | + } | |
1881 | + | |
1882 | + return 0; | |
1883 | +} | |
1884 | + | |
1885 | +//! @brief リロードカウントを取得 | |
1886 | +//! @return カウント数 (リロード中:1以上) | |
1887 | +int weapon::GetReloadCnt() | |
1888 | +{ | |
1889 | + return reloadcnt; | |
1890 | +} | |
1891 | + | |
1892 | +//! @brief 武器の種類・装弾数の変更 | |
1893 | +//! @param Resource ResourceManagerのポインタ | |
1894 | +//! @param id_param 種類番号 | |
1895 | +//! @param lnbs 装弾数 | |
1896 | +//! @param nbs 合計弾数 | |
1897 | +//! @return 成功:1 失敗:0 | |
1898 | +//! @attention プレイヤーによる裏技(F6・F7)用に用意された関数です。手榴弾が選択された場合、自動的に弾を補充します。 | |
1899 | +//! @attention 使用されていない武器オブジェクトに対して実行すると、この関数は失敗します。 | |
1900 | +bool weapon::ResetWeaponParam(class ResourceManager *Resource, int id_param, int lnbs, int nbs) | |
1901 | +{ | |
1902 | + //初期化されていなければ、失敗 | |
1903 | + if( RenderFlag == false ){ return 0; } | |
1904 | + | |
1905 | + //指定された設定値へ上書き | |
1906 | + id_parameter = id_param; | |
1907 | + bullets = nbs; | |
1908 | + Loadbullets = lnbs; | |
1909 | + | |
1910 | + //もし手榴弾ならば、自動リロード | |
1911 | + if( id_param == ID_WEAPON_GRENADE ){ | |
1912 | + if( (bullets > 0)&&(Loadbullets == 0) ){ | |
1913 | + Loadbullets = 1; | |
1914 | + } | |
1915 | + } | |
1916 | + | |
1917 | + //モデルとテクスチャを設定 | |
1918 | + Resource->GetWeaponModelTexture(id_param, &id_model, &id_texture); | |
1919 | + WeaponParameter param; | |
1920 | + if( Param->GetWeapon(id_param, ¶m) == 0 ){ | |
1921 | + model_size = param.size; | |
1922 | + } | |
1923 | + | |
1924 | + return 1; | |
1925 | +} | |
1926 | + | |
1927 | +//! @brief 計算を実行(自由落下) | |
1928 | +//! @param CollD Collisionのポインタ | |
1929 | +int weapon::RunFrame(class Collision *CollD) | |
1930 | +{ | |
1931 | + //クラスが設定されていなければ失敗 | |
1932 | + if( CollD == NULL ){ return 0; } | |
1933 | + | |
1934 | + //初期化されていなければ、失敗 | |
1935 | + if( RenderFlag == false ){ return 0; } | |
1936 | + | |
1937 | + //連射カウントが残っていれば、1 減らす | |
1938 | + if( shotcnt > 0 ){ | |
1939 | + shotcnt -= 1; | |
1940 | + } | |
1941 | + else if( reloadcnt > 0 ){ | |
1942 | + //リロードカウントが残っていれば 1 減らし、カウントが 0 ならばリロード処理を実行 | |
1943 | + reloadcnt -= 1; | |
1944 | + if( reloadcnt == 0 ){ | |
1945 | + RunReload(); | |
1946 | + } | |
1947 | + } | |
1948 | + | |
1949 | + //誰にも使われておらず、移動フラグが有効ならば〜 | |
1950 | + if( (usingflag == false)&&(motionflag == true) ){ | |
1951 | + float Dist; | |
1952 | + float maxDist; | |
1953 | + | |
1954 | + //移動速度を更新 | |
1955 | + move_x *= 0.96f; | |
1956 | + move_z *= 0.96f; | |
1957 | + if( move_y > -1.8f ){ | |
1958 | + move_y -= 0.3f; | |
1959 | + } | |
1960 | + | |
1961 | + //ブロックに埋まっていれば処理しない | |
1962 | + if( CollD->CheckALLBlockInside(pos_x, pos_y, pos_z) == true ){ | |
1963 | + motionflag = false; | |
1964 | + return 0; | |
1965 | + } | |
1966 | + | |
1967 | + //水平の移動速度を求める | |
1968 | + maxDist = sqrt(move_x*move_x + move_z*move_z); | |
1969 | + if( maxDist < 0.1f ){ | |
1970 | + maxDist = 0.0f; | |
1971 | + move_x = 0.0f; | |
1972 | + move_z = 0.0f; | |
1973 | + } | |
1974 | + | |
1975 | + //ブロックに接していれば、それ以上は水平移動しない。 | |
1976 | + if( maxDist > 0.0f ){ | |
1977 | + if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y, pos_z, move_x/maxDist, 0, move_z/maxDist, NULL, NULL, &Dist, maxDist) == true ){ | |
1978 | + //ブロックに埋まらないように手前に | |
1979 | + Dist -= 0.1f; | |
1980 | + | |
1981 | + //接している座標まで移動 | |
1982 | + pos_x += move_x/maxDist * Dist; | |
1983 | + pos_z += move_z/maxDist * Dist; | |
1984 | + | |
1985 | + //移動量を 0 に | |
1986 | + move_x = 0.0f; | |
1987 | + move_z = 0.0f; | |
1988 | + } | |
1989 | + } | |
1990 | + | |
1991 | + //ブロックに接していれば、そこまで落下する | |
1992 | + if( CollD->CheckALLBlockIntersectDummyRay(pos_x, pos_y, pos_z, 0, -1, 0, NULL, NULL, &Dist, abs(move_y)) == true ){ | |
1993 | + CollD->CheckALLBlockIntersectRay(pos_x, pos_y, pos_z, 0, -1, 0, NULL, NULL, &Dist, abs(move_y)); | |
1994 | + pos_y -= Dist - 0.2f; | |
1995 | + motionflag = false; | |
1996 | + return 0; | |
1997 | + } | |
1998 | + | |
1999 | + //座標を反映 | |
2000 | + pos_x += move_x; | |
2001 | + pos_y += move_y; | |
2002 | + pos_z += move_z; | |
2003 | + } | |
2004 | + | |
2005 | + return 0; | |
2006 | +} | |
2007 | + | |
2008 | +//! @brief 描画 | |
2009 | +//! @param d3dg D3DGraphicsのポインタ | |
2010 | +void weapon::Render(class D3DGraphics *d3dg) | |
2011 | +{ | |
2012 | + //クラスが設定されていなければ失敗 | |
2013 | + if( d3dg == NULL ){ return; } | |
2014 | + | |
2015 | + //初期化されてないか、誰かに使われていれば処理しない | |
2016 | + if( RenderFlag == false ){ return; } | |
2017 | + if( usingflag == true ){ return; } | |
2018 | + | |
2019 | + //武器を描画 | |
2020 | + d3dg->SetWorldTransform(pos_x, pos_y, pos_z, rotation_x, 0.0f, (float)M_PI/2, model_size); | |
2021 | + d3dg->RenderModel(id_model, id_texture); | |
2022 | +} | |
2023 | + | |
2024 | +//! @brief コンストラクタ | |
2025 | +smallobject::smallobject(class ParameterInfo *in_Param, class MIFInterface *in_MIFdata, float x, float y, float z, float rx, int id_param, signed char p4, bool flag) | |
2026 | +{ | |
2027 | + Param = in_Param; | |
2028 | + MIFdata = in_MIFdata; | |
2029 | + pos_x = x; | |
2030 | + pos_y = y; | |
2031 | + pos_z = z; | |
2032 | + rotation_x = rx; | |
2033 | + rotation_y = 0.0f; | |
2034 | + RenderFlag = flag; | |
2035 | + model_size = 5.0f; | |
2036 | + | |
2037 | + id_parameter = id_param; | |
2038 | + point_p4 = p4; | |
2039 | + | |
2040 | + hp = 0; //暫定 | |
2041 | + jump_rx = 0.0f; | |
2042 | + move_rx = 0.0f; | |
2043 | + add_rx = 0.0f; | |
2044 | + add_ry = 0.0f; | |
2045 | + jump_cnt = 0; | |
2046 | + | |
2047 | + if( Param != NULL ){ | |
2048 | + SmallObjectParameter ParamData; | |
2049 | + if( Param->GetSmallObject(id_param, &ParamData) == 0 ){ | |
2050 | + hp = ParamData.hp; | |
2051 | + } | |
2052 | + } | |
2053 | + id_model = -1; | |
2054 | + id_texture = -1; | |
2055 | +} | |
2056 | + | |
2057 | +//! @brief ディストラクタ | |
2058 | +smallobject::~smallobject() | |
2059 | +{} | |
2060 | + | |
2061 | +//! @brief MIFデータを管理するクラスを設定 | |
2062 | +//! @param in_MIFdata MIFInterfaceクラスのポインタ | |
2063 | +void smallobject::SetMIFInterfaceClass(class MIFInterface *in_MIFdata) | |
2064 | +{ | |
2065 | + MIFdata = in_MIFdata; | |
2066 | +} | |
2067 | + | |
2068 | +//! @brief 設定値を設定 | |
2069 | +//! @param id_param 小物の種類番号 | |
2070 | +//! @param p4 第4パラメータ | |
2071 | +//! @param init オブジェクトを初期化 | |
2072 | +void smallobject::SetParamData(int id_param, signed char p4, bool init) | |
2073 | +{ | |
2074 | + rotation_y = 0.0f; | |
2075 | + id_parameter = id_param; | |
2076 | + point_p4 = p4; | |
2077 | + | |
2078 | + if( init == true ){ | |
2079 | + hp = 0; //暫定 | |
2080 | + jump_rx = 0.0f; | |
2081 | + move_rx = 0.0f; | |
2082 | + add_rx = 0.0f; | |
2083 | + add_ry = 0.0f; | |
2084 | + jump_cnt = 0; | |
2085 | + | |
2086 | + if( id_param == TOTAL_PARAMETERINFO_SMALLOBJECT+1 -1 ){ | |
2087 | + if( MIFdata != NULL ){ | |
2088 | + hp = MIFdata->GetAddSmallobjectHP(); | |
2089 | + } | |
2090 | + } | |
2091 | + else{ | |
2092 | + if( Param != NULL ){ | |
2093 | + SmallObjectParameter ParamData; | |
2094 | + if( Param->GetSmallObject(id_param, &ParamData) == 0 ){ | |
2095 | + hp = ParamData.hp; | |
2096 | + } | |
2097 | + } | |
2098 | + } | |
2099 | + } | |
2100 | +} | |
2101 | + | |
2102 | +//! @brief 設定値を取得 | |
2103 | +//! @param id_param 小物の種類番号を受け取るポインタ(NULL可) | |
2104 | +//! @param p4 第4パラメータを受け取るポインタ(NULL可) | |
2105 | +void smallobject::GetParamData(int *id_param, signed char *p4) | |
2106 | +{ | |
2107 | + if( id_param != NULL ){ *id_param = id_parameter; } | |
2108 | + if( p4 != NULL ){ *p4 = point_p4; } | |
2109 | +} | |
2110 | + | |
2111 | +//! @brief 体力を取得 | |
2112 | +//! @return 体力値 | |
2113 | +int smallobject::GetHP() | |
2114 | +{ | |
2115 | + return hp; | |
2116 | +} | |
2117 | + | |
2118 | +//! @brief ブロックの上に移動 | |
2119 | +//! @param CollD Collisionのポインタ | |
2120 | +//! @return 元の座標からの移動量(0で移動なし) | |
2121 | +float smallobject::CollisionMap(class Collision *CollD) | |
2122 | +{ | |
2123 | + //クラスが設定されていなければ失敗 | |
2124 | + if( CollD == NULL ){ return 0.0f; } | |
2125 | + | |
2126 | + float Dist; | |
2127 | + SmallObjectParameter ParamData; | |
2128 | + | |
2129 | + //ブロックに埋まっていれば、そのまま | |
2130 | + if( CollD->CheckALLBlockInside(pos_x, pos_y, pos_z) == true ){ return 0.0f; } | |
2131 | + | |
2132 | + //下方向に当たり判定 | |
2133 | + if( CollD->CheckALLBlockIntersectRay(pos_x, pos_y, pos_z, 0, -1, 0, NULL, NULL, &Dist, 1000.0f) == true ){ | |
2134 | + //当たり判定の大きさを取得 | |
2135 | + if( id_parameter == TOTAL_PARAMETERINFO_SMALLOBJECT+1 -1 ){ | |
2136 | + Dist -= (float)MIFdata->GetAddSmallobjectDecide()/10.0f; | |
2137 | + } | |
2138 | + else{ | |
2139 | + if( Param->GetSmallObject(id_parameter, &ParamData) == 0 ){ | |
2140 | + Dist -= (float)ParamData.decide/10.0f; | |
2141 | + } | |
2142 | + } | |
2143 | + | |
2144 | + //座標を移動する | |
2145 | + pos_y -= Dist; | |
2146 | + return Dist; | |
2147 | + } | |
2148 | + | |
2149 | + return 0.0f; | |
2150 | +} | |
2151 | + | |
2152 | +//! @brief 弾がヒットした | |
2153 | +//! @param attacks 弾の攻撃力 | |
2154 | +void smallobject::HitBullet(int attacks) | |
2155 | +{ | |
2156 | + hp -= attacks; | |
2157 | + if( hp <= 0 ){ | |
2158 | + Destruction(); | |
2159 | + } | |
2160 | +} | |
2161 | + | |
2162 | +//! @brief 手榴弾の爆風がヒットした | |
2163 | +//! @param attacks 爆風の攻撃力 | |
2164 | +//! @attention 距離による計算を事前に済ませてください。 | |
2165 | +void smallobject::HitGrenadeExplosion(int attacks) | |
2166 | +{ | |
2167 | + hp -= attacks; | |
2168 | + if( hp <= 0 ){ | |
2169 | + Destruction(); | |
2170 | + } | |
2171 | +} | |
2172 | + | |
2173 | +//! @brief 小物を破壊する | |
2174 | +//! @attention 通常は HitBullet()関数 および GrenadeExplosion()関数 から自動的に実行されるため、直接呼び出す必要はありません。 | |
2175 | +void smallobject::Destruction() | |
2176 | +{ | |
2177 | + //RenderFlag = false; | |
2178 | + //return; | |
2179 | + | |
2180 | + //小物の設定値を取得 | |
2181 | + SmallObjectParameter paramdata; | |
2182 | + Param->GetSmallObject(id_parameter, ¶mdata); | |
2183 | + | |
2184 | + //飛ばす | |
2185 | + hp = 0; | |
2186 | + jump_cnt = paramdata.jump; | |
2187 | + | |
2188 | + //姿勢設定 | |
2189 | + jump_rx = (float)M_PI/18 * GetRand(36); | |
2190 | + move_rx = (float)paramdata.jump * 0.04243f; | |
2191 | + add_rx = (float)M_PI/180 * GetRand(20); | |
2192 | + add_ry = (float)M_PI/180 * GetRand(20); | |
2193 | +} | |
2194 | + | |
2195 | +//! @brief 計算を実行(破壊時の移動など) | |
2196 | +int smallobject::RunFrame() | |
2197 | +{ | |
2198 | + //描画されていないか、体力が残っていなければ処理しない。 | |
2199 | + if( RenderFlag == false ){ return 0; } | |
2200 | + if( hp > 0 ){ return 0; } | |
2201 | + | |
2202 | + int cnt; | |
2203 | + SmallObjectParameter paramdata; | |
2204 | + | |
2205 | + //吹き飛んでいるカウント数を計算 | |
2206 | + cnt = Param->GetSmallObject(id_parameter, ¶mdata) - jump_cnt; | |
2207 | + | |
2208 | + //姿勢から座標・角度を計算 | |
2209 | + pos_x += cos(jump_rx) * move_rx; | |
2210 | + pos_y += jump_cnt * 0.1f; | |
2211 | + pos_z += sin(jump_rx) * move_rx; | |
2212 | + rotation_x += add_rx; | |
2213 | + rotation_y += add_ry; | |
2214 | + | |
2215 | + jump_cnt -= 1; | |
2216 | + | |
2217 | + //1秒飛んでいたら描画終了 | |
2218 | + if( cnt > (int)GAMEFPS ){ | |
2219 | + RenderFlag = false; | |
2220 | + return 2; | |
2221 | + } | |
2222 | + | |
2223 | + return 1; | |
2224 | +} | |
2225 | + | |
2226 | +//! @brief 描画 | |
2227 | +//! @param d3dg D3DGraphicsのポインタ | |
2228 | +void smallobject::Render(D3DGraphics *d3dg) | |
2229 | +{ | |
2230 | + //クラスが設定されていなければ失敗 | |
2231 | + if( d3dg == NULL ){ return; } | |
2232 | + | |
2233 | + //初期化されていなければ処理しない。 | |
2234 | + if( RenderFlag == false ){ return; } | |
2235 | + | |
2236 | + //描画 | |
2237 | + d3dg->SetWorldTransform(pos_x, pos_y, pos_z, rotation_x, rotation_y, model_size); | |
2238 | + d3dg->RenderModel(id_model, id_texture); | |
2239 | +} | |
2240 | + | |
2241 | +//! @brief コンストラクタ | |
2242 | +bullet::bullet(int modelid, int textureid) | |
2243 | +{ | |
2244 | + model_size = 1.0f; | |
2245 | + id_model = modelid; | |
2246 | + id_texture = textureid; | |
2247 | + RenderFlag = false; | |
2248 | +} | |
2249 | + | |
2250 | +//! @brief ディストラクタ | |
2251 | +bullet::~bullet() | |
2252 | +{} | |
2253 | + | |
2254 | +//! @brief 座標と角度を設定 | |
2255 | +//! @param x X座標 | |
2256 | +//! @param y Y座標 | |
2257 | +//! @param z Z座標 | |
2258 | +//! @param rx 横軸回転 | |
2259 | +//! @param ry 縦軸回転 | |
2260 | +void bullet::SetPosData(float x, float y, float z, float rx, float ry) | |
2261 | +{ | |
2262 | + pos_x = x; | |
2263 | + pos_y = y; | |
2264 | + pos_z = z; | |
2265 | + rotation_x = rx; | |
2266 | + rotation_y = ry; | |
2267 | +} | |
2268 | + | |
2269 | +//! @brief 設定値を設定 | |
2270 | +//! @param _attacks 攻撃力 | |
2271 | +//! @param _penetration 貫通力 | |
2272 | +//! @param _speed 弾速 | |
2273 | +//! @param _teamid チーム番号 | |
2274 | +//! @param _humanid 人のデータ番号 | |
2275 | +//! @param init オブジェクトを初期化 | |
2276 | +void bullet::SetParamData(int _attacks, int _penetration, int _speed, int _teamid, int _humanid, bool init) | |
2277 | +{ | |
2278 | + attacks = _attacks; | |
2279 | + penetration = _penetration; | |
2280 | + speed = _speed; | |
2281 | + teamid = _teamid; | |
2282 | + humanid = _humanid; | |
2283 | + | |
2284 | + if( init == true ){ | |
2285 | + cnt = 0; | |
2286 | + } | |
2287 | +} | |
2288 | + | |
2289 | +//! @brief 座標と角度を取得 | |
2290 | +//! @param x X座標を受け取るポインタ(NULL可) | |
2291 | +//! @param y Y座標を受け取るポインタ(NULL可) | |
2292 | +//! @param z Z座標を受け取るポインタ(NULL可) | |
2293 | +//! @param rx 横軸回転を受け取るポインタ(NULL可) | |
2294 | +//! @param ry 縦軸回転を受け取るポインタ(NULL可) | |
2295 | +void bullet::GetPosData(float *x, float *y, float *z, float *rx, float *ry) | |
2296 | +{ | |
2297 | + if( x != NULL ){ *x = pos_x; } | |
2298 | + if( y != NULL ){ *y = pos_y; } | |
2299 | + if( z != NULL ){ *z = pos_z; } | |
2300 | + if( rx != NULL ){ *rx = rotation_x; } | |
2301 | + if( ry != NULL ){ *ry = rotation_y; } | |
2302 | +} | |
2303 | + | |
2304 | +//! @brief 設定値を取得 | |
2305 | +//! @param _attacks 攻撃力を受け取るポインタ(NULL可) | |
2306 | +//! @param _penetration 貫通力を受け取るポインタ(NULL可) | |
2307 | +//! @param _speed 弾速を受け取るポインタ(NULL可) | |
2308 | +//! @param _teamid チーム番号を受け取るポインタ(NULL可) | |
2309 | +//! @param _humanid 人のデータ番号を受け取るポインタ(NULL可) | |
2310 | +void bullet::GetParamData(int *_attacks, int *_penetration, int *_speed, int *_teamid, int *_humanid) | |
2311 | +{ | |
2312 | + if( _attacks != NULL ){ *_attacks = attacks; } | |
2313 | + if( _penetration != NULL ){ *_penetration = penetration; } | |
2314 | + if( _speed != NULL ){ *_speed = speed; } | |
2315 | + if( _teamid != NULL ){ *_teamid = teamid; } | |
2316 | + if( _humanid != NULL ){ *_humanid = humanid; } | |
2317 | +} | |
2318 | + | |
2319 | +//! @brief 計算を実行(弾の進行・時間消滅) | |
2320 | +int bullet::RunFrame() | |
2321 | +{ | |
2322 | + //初期化されていなければ処理しない | |
2323 | + if( RenderFlag == false ){ return 0; } | |
2324 | + | |
2325 | + //消滅時間を過ぎていれば、オブジェクトを無効化 | |
2326 | + if( cnt > BULLET_DESTROYFRAME ){ | |
2327 | + RenderFlag = false; | |
2328 | + return 0; | |
2329 | + } | |
2330 | + | |
2331 | + //移動処理 | |
2332 | + pos_x += cos(rotation_x)*cos(rotation_y)*speed; | |
2333 | + pos_y += sin(rotation_y)*speed; | |
2334 | + pos_z += sin(rotation_x)*cos(rotation_y)*speed; | |
2335 | + cnt += 1; | |
2336 | + | |
2337 | + return 0; | |
2338 | +} | |
2339 | + | |
2340 | +//! @brief 描画 | |
2341 | +//! @param d3dg D3DGraphicsのポインタ | |
2342 | +void bullet::Render(class D3DGraphics *d3dg) | |
2343 | +{ | |
2344 | + //クラスが設定されていなければ失敗 | |
2345 | + if( d3dg == NULL ){ return; } | |
2346 | + | |
2347 | + //初期化されていなければ処理しない。 | |
2348 | + if( RenderFlag == false ){ return; } | |
2349 | + | |
2350 | + //弾を移動前だったら描画しない | |
2351 | + // 弾が頭から突き抜けて見える対策 | |
2352 | + if( cnt == 0 ){ return; } | |
2353 | + | |
2354 | + //描画 | |
2355 | + d3dg->SetWorldTransform(pos_x, pos_y, pos_z, (rotation_x * -1 - (float)M_PI/2), rotation_y, model_size); | |
2356 | + d3dg->RenderModel(id_model, id_texture); | |
2357 | +} | |
2358 | + | |
2359 | +//! @brief コンストラクタ | |
2360 | +grenade::grenade(int modelid, int textureid) : bullet(modelid, textureid) | |
2361 | +{ | |
2362 | + if( Param != NULL ){ | |
2363 | + WeaponParameter ParamData; | |
2364 | + if( Param->GetWeapon(ID_WEAPON_GRENADE, &ParamData) == 0 ){ | |
2365 | + model_size = ParamData.size; | |
2366 | + } | |
2367 | + } | |
2368 | +} | |
2369 | + | |
2370 | +//! @brief ディストラクタ | |
2371 | +grenade::~grenade() | |
2372 | +{} | |
2373 | + | |
2374 | +//! @brief 座標と情報を設定 | |
2375 | +//! @param speed 初速 | |
2376 | +//! @param _humanid 人のデータ番号 | |
2377 | +//! @param init オブジェクトを初期化 | |
2378 | +//! @attention 先に SetPosData() を実行してください。 | |
2379 | +void grenade::SetParamData(float speed, int _humanid, bool init) | |
2380 | +{ | |
2381 | + move_x = cos(rotation_x) * cos(rotation_y) * speed; | |
2382 | + move_y = sin(rotation_y) * speed; | |
2383 | + move_z = sin(rotation_x) * cos(rotation_y) * speed; | |
2384 | + humanid = _humanid; | |
2385 | + | |
2386 | + if( init == true ){ | |
2387 | + cnt = 0; | |
2388 | + } | |
2389 | +} | |
2390 | + | |
2391 | +//! @brief 速度を取得 | |
2392 | +//! @return 速度 | |
2393 | +float grenade::GetSpeed() | |
2394 | +{ | |
2395 | + return sqrt(move_x*move_x + move_y*move_y + move_z*move_z); | |
2396 | +} | |
2397 | + | |
2398 | +//! @brief 計算を実行(手榴弾の進行・爆発) | |
2399 | +//! @return 爆発:2 バウンド・跳ね返り:1 それ以外:0 | |
2400 | +int grenade::RunFrame(class Collision *CollD, class BlockDataInterface *inblockdata) | |
2401 | +{ | |
2402 | + //初期化されていなければ処理しない | |
2403 | + if( RenderFlag == false ){ return 0; } | |
2404 | + | |
2405 | + //時間を過ぎていれば、オブジェクトを無効化し、「爆発」として返す。 | |
2406 | + if( cnt > GRENADE_DESTROYFRAME ){ | |
2407 | + RenderFlag = false; | |
2408 | + return 2; | |
2409 | + } | |
2410 | + | |
2411 | + //静止していれば処理しない | |
2412 | + if( (move_x == 0.0f)&&(move_y == 0.0f)&&(move_z == 0.0f) ){ | |
2413 | + cnt += 1; | |
2414 | + return 0; | |
2415 | + } | |
2416 | + | |
2417 | + /* | |
2418 | + //静止に近い状態ならば、移動処理をしない。 | |
2419 | + if( (move_x*move_x + move_y*move_y + move_z*move_z) < 0.1f*0.1f ){ | |
2420 | + cnt += 1; | |
2421 | + return 0; | |
2422 | + } | |
2423 | + */ | |
2424 | + | |
2425 | + //移動速度を計算 | |
2426 | + move_x *= 0.98f; | |
2427 | + move_y = (move_y - 0.17f) * 0.98f; | |
2428 | + move_z *= 0.98f; | |
2429 | + | |
2430 | + int id, face; | |
2431 | + float Dist; | |
2432 | + float maxDist = sqrt(move_x*move_x + move_y*move_y + move_z*move_z); | |
2433 | + | |
2434 | + //マップに対して当たり判定を実行 | |
2435 | + if( CollD->CheckALLBlockIntersectRay(pos_x, pos_y, pos_z, move_x/maxDist, move_y/maxDist, move_z/maxDist, &id, &face, &Dist, maxDist) == true ){ | |
2436 | + float vx, vy, vz; | |
2437 | + | |
2438 | + //マップと衝突する座標まで移動 | |
2439 | + pos_x += move_x/maxDist * (Dist - 0.1f); | |
2440 | + pos_y += move_y/maxDist * (Dist - 0.1f); | |
2441 | + pos_z += move_z/maxDist * (Dist - 0.1f); | |
2442 | + | |
2443 | + //反射するベクトルを求める | |
2444 | + CollD->ReflectVector(inblockdata, id, face, move_x, move_y, move_z, &vx, &vy, &vz); | |
2445 | + | |
2446 | + //減速 | |
2447 | + move_x = vx * GRENADE_BOUND_ACCELERATION; | |
2448 | + move_y = vy * GRENADE_BOUND_ACCELERATION; | |
2449 | + move_z = vz * GRENADE_BOUND_ACCELERATION; | |
2450 | + | |
2451 | + cnt += 1; | |
2452 | + return 1; | |
2453 | + } | |
2454 | + | |
2455 | + //座標を移動 | |
2456 | + pos_x += move_x; | |
2457 | + pos_y += move_y; | |
2458 | + pos_z += move_z; | |
2459 | + | |
2460 | + cnt += 1; | |
2461 | + return 0; | |
2462 | +} | |
2463 | + | |
2464 | +//! @brief 描画 | |
2465 | +//! @param d3dg D3DGraphicsのポインタ | |
2466 | +void grenade::Render(class D3DGraphics *d3dg) | |
2467 | +{ | |
2468 | + //クラスが設定されていなければ失敗 | |
2469 | + if( d3dg == NULL ){ return; } | |
2470 | + | |
2471 | + //初期化されていなければ処理しない。 | |
2472 | + if( RenderFlag == false ){ return; } | |
2473 | + | |
2474 | + //描画 | |
2475 | + d3dg->SetWorldTransform(pos_x, pos_y, pos_z, (rotation_x * -1 - (float)M_PI/2), 0.0f, (float)M_PI/2, model_size); | |
2476 | + d3dg->RenderModel(id_model, id_texture); | |
2477 | +} | |
2478 | + | |
2479 | +//! @brief コンストラクタ | |
2480 | +effect::effect(float x, float y, float z, float size, float rotation, int count, int texture, int settype) | |
2481 | +{ | |
2482 | + pos_x = x; | |
2483 | + pos_y = y; | |
2484 | + pos_z = z; | |
2485 | + model_size = size; | |
2486 | + camera_rx = 0.0f; | |
2487 | + camera_ry = 0.0f; | |
2488 | + rotation_x = rotation; | |
2489 | + cnt = count; | |
2490 | + setcnt = count; | |
2491 | + id_texture = texture; | |
2492 | + type = settype; | |
2493 | + if( cnt > 0 ){ | |
2494 | + RenderFlag = true; | |
2495 | + } | |
2496 | + else{ | |
2497 | + RenderFlag = false; | |
2498 | + } | |
2499 | + alpha = 1.0f; | |
2500 | +} | |
2501 | + | |
2502 | +//! @brief ディストラクタ | |
2503 | +effect::~effect() | |
2504 | +{} | |
2505 | + | |
2506 | +//! @brief 設定値を設定 | |
2507 | +//! @param in_move_x X軸移動量 | |
2508 | +//! @param in_move_y Y軸移動量 | |
2509 | +//! @param in_move_z Z軸移動量 | |
2510 | +//! @param size 表示倍率 | |
2511 | +//! @param rotation 回転角度 | |
2512 | +//! @param count 表示フレーム数 | |
2513 | +//! @param texture テクスチャの認識番号 | |
2514 | +//! @param settype エフェクトの種類 (Effect_Type を組み合せる) | |
2515 | +//! @param init オブジェクトを初期化 | |
2516 | +void effect::SetParamData(float in_move_x, float in_move_y, float in_move_z, float size, float rotation, int count, int texture, int settype, bool init) | |
2517 | +{ | |
2518 | + move_x = in_move_x; | |
2519 | + move_y = in_move_y; | |
2520 | + move_z = in_move_z; | |
2521 | + model_size = size; | |
2522 | + rotation_texture = rotation; | |
2523 | + cnt = count; | |
2524 | + setcnt = count; | |
2525 | + id_texture = texture; | |
2526 | + type = settype; | |
2527 | + alpha = 1.0f; | |
2528 | + | |
2529 | + if( init == true ){ | |
2530 | + camera_rx = 0.0f; | |
2531 | + camera_ry = 0.0f; | |
2532 | + } | |
2533 | +} | |
2534 | + | |
2535 | +//! @brief 計算を実行(ビルボード化) | |
2536 | +//! @param in_camera_rx カメラの横軸角度 | |
2537 | +//! @param in_camera_ry カメラの縦軸角度 | |
2538 | +//! @return 処理実行:1 描画最終フレーム:2 処理なし:0 | |
2539 | +int effect::RunFrame(float in_camera_rx, float in_camera_ry) | |
2540 | +{ | |
2541 | + //初期化されていなければ処理しない | |
2542 | + if( RenderFlag == false ){ return 0; } | |
2543 | + | |
2544 | + //カウントが終了したら、処理しないように設定 | |
2545 | + if( cnt <= 0 ){ | |
2546 | + RenderFlag = false; | |
2547 | + return 2; | |
2548 | + } | |
2549 | + | |
2550 | + //カメラ座標を適用 | |
2551 | + camera_rx = in_camera_rx; | |
2552 | + camera_ry = in_camera_ry; | |
2553 | + | |
2554 | + //座標移動 | |
2555 | + pos_x += move_x; | |
2556 | + pos_y += move_y; | |
2557 | + pos_z += move_z; | |
2558 | + | |
2559 | + //特殊処理を実行 | |
2560 | + if( type & EFFECT_DISAPPEAR ){ //消す | |
2561 | + alpha -= 1.0f/setcnt; | |
2562 | + } | |
2563 | + if( type & EFFECT_MAGNIFY ){ //拡大 | |
2564 | + model_size += model_size/50; | |
2565 | + } | |
2566 | + if( type & EFFECT_ROTATION ){ //回転 | |
2567 | + if( rotation_texture > 0.0f ){ | |
2568 | + rotation_texture += (float)M_PI/180*1; | |
2569 | + } | |
2570 | + else{ | |
2571 | + rotation_texture -= (float)M_PI/180*1; | |
2572 | + } | |
2573 | + } | |
2574 | + if( type & EFFECT_FALL ){ //落下 | |
2575 | + move_y = (move_y - 0.17f) * 0.98f; | |
2576 | + } | |
2577 | + | |
2578 | + //カウントを 1 引く | |
2579 | + cnt -= 1; | |
2580 | + return 1; | |
2581 | +} | |
2582 | + | |
2583 | +//! @brief 描画 | |
2584 | +//! @param d3dg D3DGraphicsのポインタ | |
2585 | +void effect::Render(class D3DGraphics *d3dg) | |
2586 | +{ | |
2587 | + //クラスが設定されていなければ失敗 | |
2588 | + if( d3dg == NULL ){ return; } | |
2589 | + | |
2590 | + //初期化されていなければ処理しない。 | |
2591 | + if( RenderFlag == false ){ return; } | |
2592 | + | |
2593 | + //描画 | |
2594 | + d3dg->SetWorldTransformEffect(pos_x, pos_y, pos_z, camera_rx*-1, camera_ry, rotation_texture, model_size); | |
2595 | + d3dg->RenderBoard(id_texture, alpha); | |
2596 | +} | |
\ No newline at end of file |
@@ -0,0 +1,152 @@ | ||
1 | +//! @file objectmanager.h | |
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 | +#ifndef OBJECTMANAGER_H | |
33 | +#define OBJECTMANAGER_H | |
34 | + | |
35 | +#define MAX_HUMAN 96 //!< 最大人数 | |
36 | +#define MAX_WEAPON 200 //!< 武器の最大数 | |
37 | +#define MAX_SMALLOBJECT 40 //!< 小物の最大数 | |
38 | + | |
39 | +#define MAX_BULLET 128 //!< 銃弾の最大数 | |
40 | +#define MAX_GRENADE 32 //!< 手榴弾の最大数 | |
41 | +#define MAX_EFFECT 256 //!< エフェクトの最大数 | |
42 | + | |
43 | +#define WEAPONSHOT_HEIGHT (VIEW_HEIGHT) //!< 弾を発射する高さ | |
44 | + | |
45 | +#define TOTAL_WEAPON_AUTOBULLET 3 //!< 初期化時に自動的に補てんされる弾数(装弾数の何倍か) | |
46 | + | |
47 | +#define SMALLOBJECT_SCALE 0.13f //!< 小物当たり判定の倍率 | |
48 | + | |
49 | +#ifndef H_LAYERLEVEL | |
50 | + #define H_LAYERLEVEL 3 //!< Select include file. | |
51 | +#endif | |
52 | +#include "main.h" | |
53 | + | |
54 | +//! エフェクト描画計算用構造体 | |
55 | +struct effectdata{ | |
56 | + int id; //!< データ番号 | |
57 | + float dist; //!< 距離 | |
58 | +}; | |
59 | + | |
60 | +//! @brief オブジェクト管理クラス | |
61 | +//! @details 各オブジェクトの初期化・計算・描画などを行い管理します。 | |
62 | +class ObjectManager | |
63 | +{ | |
64 | + class human *HumanIndex; //!< 人オブジェクト | |
65 | + class weapon *WeaponIndex; //!< 武器オブジェクト | |
66 | + class smallobject *SmallObjectIndex; //!< 小物オブジェクト | |
67 | + class bullet *BulletIndex; //!< 弾オブジェクト | |
68 | + class grenade *GrenadeIndex; //!< 手榴弾オブジェクト | |
69 | + class effect *EffectIndex; //!< 手榴弾オブジェクト | |
70 | + | |
71 | + unsigned int framecnt; //!< フレーム数のカウント | |
72 | + | |
73 | + int *Human_ontarget; //!< 命中数 | |
74 | + int *Human_kill; //!< 倒した敵の数 | |
75 | + int *Human_headshot; //!< 敵の頭部に命中した数 | |
76 | + bool *Human_ShotFlag; //!< 発砲フラグ(マズルフラッシュ用) | |
77 | + | |
78 | + int Player_HumanID; //!< プレイヤーが操作する人オブジェクトのID | |
79 | + | |
80 | + int AddHumanIndex_TextureID; //!< 前回読み込んだテクスチャID | |
81 | + | |
82 | + ParameterInfo *GameParamInfo; //!< ゲームの設定値 | |
83 | + D3DGraphics *d3dg; //!< 描画クラス | |
84 | + ResourceManager *Resource; //!< リソース管理 | |
85 | + BlockDataInterface *BlockData; //!< ブロックデータ管理クラス | |
86 | + PointDataInterface *PointData; //!< ポイントデータ管理クラス | |
87 | + Collision *CollD; //!< 当たり判定管理クラス | |
88 | + SoundManager *GameSound; //!< ゲーム効果音管理クラス | |
89 | + MIFInterface *MIFdata; //!< MIFコントロールクラス | |
90 | + | |
91 | + int AddHumanIndex(pointdata data, pointdata infodata); | |
92 | + int AddWeaponIndex(pointdata data); | |
93 | + int AddSmallObjectIndex(pointdata data); | |
94 | + void SetHumanBlood(float x, float y, float z); | |
95 | + bool CollideHuman(human *in_humanA, human *in_humanB); | |
96 | + bool CollideBullet(bullet *in_bullet); | |
97 | + void HitBulletMap(float x, float y, float z); | |
98 | + void HitBulletHuman(int HitHuman_id, int Hit_id, float x, float y, float z, float brx, int attacks, int humanid); | |
99 | + void HitBulletSmallObject(int HitSmallObject_id, float x, float y, float z, int attacks); | |
100 | + bool GrenadeExplosion(grenade *in_grenade); | |
101 | + void DeadEffect(human *in_human); | |
102 | + void PickupWeapon(human *in_human, weapon *in_weapon); | |
103 | + void CleanupPointDataToObject(); | |
104 | + int SortEffect(float camera_x, float camera_y, float camera_z, effectdata data[]); | |
105 | + void ShotWeaponEffect(int humanid); | |
106 | + | |
107 | +public: | |
108 | + ObjectManager(); | |
109 | + ~ObjectManager(); | |
110 | + void 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); | |
111 | + int AddHumanIndex(float px, float py, float pz, float rx, int CharacterID, int TeamID, int WeaponID[]); | |
112 | + int AddVisualWeaponIndex(int WeaponID, bool loadbullet); | |
113 | + int AddSmallObjectIndex(float px, float py, float pz, float rx, int paramID, bool MapColl); | |
114 | + int 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); | |
115 | + void LoadPointData(); | |
116 | + int GetPlayerID(); | |
117 | + void SetPlayerID(int id); | |
118 | + human* GeHumanObject(int id); | |
119 | + human* GetPlayerHumanObject(); | |
120 | + weapon* GetWeaponObject(int id); | |
121 | + smallobject* GetSmallObject(int id); | |
122 | + bullet* GetBulletObject(int id); | |
123 | + bullet* GetNewBulletObject(); | |
124 | + grenade* GetNewGrenadeObject(); | |
125 | + human* SearchHuman(signed char p4); | |
126 | + smallobject* SearchSmallobject(signed char p4); | |
127 | + void MoveForward(int human_id); | |
128 | + void MoveBack(int human_id); | |
129 | + void MoveLeft(int human_id); | |
130 | + void MoveRight(int human_id); | |
131 | + void MoveWalk(int human_id); | |
132 | + void MoveJump(int human_id); | |
133 | + int ShotWeapon(int human_id); | |
134 | + void ReloadWeapon(int human_id); | |
135 | + void ChangeWeapon(int human_id, int id = -1); | |
136 | + bool DumpWeapon(int human_id); | |
137 | + void ChangeScopeMode(int human_id); | |
138 | + int ChangeShotMode(int human_id); | |
139 | + bool CheatAddBullet(int human_id); | |
140 | + bool CheatNewWeapon(int human_id, int new_weaponID); | |
141 | + bool CheckZombieAttack(human* MyHuman, human* EnemyHuman); | |
142 | + void HitZombieAttack(human* EnemyHuman); | |
143 | + bool HumanResuscitation(int id); | |
144 | + int CheckGameOverorComplete(); | |
145 | + bool GetObjectInfoTag(float camera_x, float camera_y, float camera_z, float camera_rx, float camera_ry, int *color, char *infostr); | |
146 | + int Process(int cmdF5id, float camera_rx, float camera_ry); | |
147 | + bool GetHumanShotInfo(int id, int *ontarget, int *kill, int *headshot); | |
148 | + void Render(float camera_x, float camera_y, float camera_z, int HidePlayer); | |
149 | + void Cleanup(); | |
150 | +}; | |
151 | + | |
152 | +#endif | |
\ No newline at end of file |
@@ -0,0 +1,362 @@ | ||
1 | +//! @file object.h | |
2 | +//! @brief objectクラスの宣言 | |
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 OBJECT_H | |
33 | +#define OBJECT_H | |
34 | + | |
35 | +// 注意:速度変更時は、当たり判定系の定数も要確認 | |
36 | +#define HUMAN_PROGRESSRUN_ACCELERATION 0.7f //!< 人の前進(走り)加速度 | |
37 | +#define HUMAN_SIDEWAYSRUN_ACCELERATION 0.5f //!< 人の横走り加速度 | |
38 | +#define HUMAN_REGRESSRUN_ACCELERATION 0.38f //!< 人の後退加速度 | |
39 | +//! 人が斜め前に進む加速度 | |
40 | +#define HUMAN_PROGRESSRUN_SIDEWAYSRUN_ACCELERATION ((HUMAN_PROGRESSRUN_ACCELERATION + HUMAN_SIDEWAYSRUN_ACCELERATION) / 2) | |
41 | +//! 人が斜め後ろに進む加速度 | |
42 | +#define HUMAN_REGRESSRUN_SIDEWAYSRUN_ACCELERATION (HUMAN_REGRESSRUN_ACCELERATION) | |
43 | +#define HUMAN_PROGRESSWALK_ACCELERATION 0.35f //!< 人が歩く加速度 | |
44 | +#define HUMAN_ATTENUATION 0.5f //!< 人の1フレーム当たりの減衰率 (0.0 < x < 1.0) | |
45 | + | |
46 | +#define HUMAN_JUMP_SPEED (2.2f + (HUMAN_DAMAGE_SPEED)) //!< ジャンプする速度 | |
47 | + | |
48 | +#define HUMAN_HEIGTH 20.0f //!< 人の高さ | |
49 | +#define HUMAN_DAMAGE_HEAD 2.0f //!< 弾が 頭 に当たった場合のダメージ倍率 | |
50 | +#define HUMAN_DAMAGE_UP 1.0f //!< 弾が 上半身 に当たった場合のダメージ倍率 | |
51 | +#define HUMAN_DAMAGE_LEG 0.7f //!< 弾が 下半身 に当たった場合のダメージ倍率 | |
52 | +#define HUMAN_DAMAGE_ZOMBIEU 15 //!< ゾンビの攻撃を受けた場合の最低ダメージ | |
53 | +#define HUMAN_DAMAGE_ZOMBIEA 5 //!< ゾンビの攻撃を受けた場合の追加ダメージ量 | |
54 | +#define HUMAN_DAMAGE_SPEED (0.066f + 0.132f) //!< 落下量 | |
55 | +#define HUMAN_DAMAGE_MINSPEED -3.8f //!< 落下によりダメージを受けない速度 | |
56 | +#define HUMAN_DAMAGE_MAXSPEED -7.0f //!< 最大落下速度 | |
57 | +#define HUMAN_DAMAGE_MAXFALL 120 //!< 落下による最大ダメージ | |
58 | +#define MAX_DAMAGE_GRENADE_DISTANCE 80.0f //!< 手榴弾によりダメージを受ける最大距離 | |
59 | +#define HUMAN_DAMAGE_GRENADE_HEAD 100 //!< 手榴弾による 頭 への最大ダメージ | |
60 | +#define HUMAN_DAMAGE_GRENADE_LEG 80 //!< 手榴弾による 足 への最大ダメージ | |
61 | +#define SMALLOBJECT_DAMAGE_GRENADE 80 //!< 手榴弾による 小物 への最大ダメージ | |
62 | + | |
63 | +#define WEAPONERRORRANGE_SCALE 0.25f //!< 武器の反動角度の倍率(×0.25 = ÷4) | |
64 | + | |
65 | +#define ARMRAD_NOWEAPON ((float)M_PI/2*-1 + (float)M_PI/9) //!< 手ぶら時の腕の表示角度 | |
66 | +#define ARMRAD_RELOADWEAPON ((float)M_PI/18*2 * -1) //!< リロード時の腕の表示角度 | |
67 | + | |
68 | +#define HUMAN_MAPCOLLISION_R 5.0f //!< 人とマップの当たり判定 半径 | |
69 | +#define HUMAN_MAPCOLLISION_HEIGTH 10.2f //!< 人とマップの当たり判定 高さ(注:腰程度) | |
70 | +#define HUMAN_MAPCOLLISION_SLOPEANGLE ((float)M_PI/18*5) //!< 人とマップの当たり判定 登れない斜面の角度 | |
71 | +#define HUMAN_MAPCOLLISION_SLOPEFORCE 1.0f //!< 人とマップの当たり判定 登れない斜面が人を押し出す力 | |
72 | +#define HUMAN_DEADLINE -100.0f //!< 人が死亡するY座標(デッドライン) | |
73 | + | |
74 | +#define BULLET_SPEEDSCALE 3 //!< 弾速の倍率 | |
75 | +#define BULLET_DESTROYFRAME 40 //!< 弾の消滅フレーム数 | |
76 | +#define GRENADE_DESTROYFRAME 100 //!< 手榴弾の爆発フレーム数 | |
77 | +#define GRENADE_BOUND_ACCELERATION ((0.63662f * 0.4f - 0.7f) * -1) //!< 手榴弾の反射減衰率 | |
78 | + | |
79 | +#ifndef H_LAYERLEVEL | |
80 | + #define H_LAYERLEVEL 2 //!< Select include file. | |
81 | +#endif | |
82 | +#include "main.h" | |
83 | + | |
84 | +#define HUMAN_DEADBODY_COLLISION //!< @brief 人が倒れる際にマップと当たり判定を実施するか @details 定数宣言有効:当たり判定を実施 定数宣言無効(コメント化):そのまま倒すだけ | |
85 | + | |
86 | +//! @brief オブジェクト管理クラス(基底クラス) | |
87 | +//! @details 3Dで座標管理や描画を行うオブジェクト全般を管理するクラス群の基底クラスです。 | |
88 | +class object | |
89 | +{ | |
90 | +protected: | |
91 | + class ParameterInfo *Param; //!< 設定値を管理するクラスへのポインタ | |
92 | + float pos_x; //!< X座標 | |
93 | + float pos_y; //!< Y座標 | |
94 | + float pos_z; //!< Z座標 | |
95 | + float rotation_x; //!< 回転角度 | |
96 | + float model_size; //!< 表示サイズ | |
97 | + int id_parameter; //!< データの種類 | |
98 | + int id_model; //!< モデル認識番号 | |
99 | + int id_texture; //!< テクスチャ認識番号 | |
100 | + bool RenderFlag; //!< 表示フラグ | |
101 | + | |
102 | +public: | |
103 | + object(class ParameterInfo *in_Param = NULL, float x = 0.0f, float y = 0.0f, float z = 0.0f, float rx = 0.0f, float size = 1.0f, bool flag = true); | |
104 | + ~object(); | |
105 | + virtual void SetParameterInfoClass(class ParameterInfo *in_Param); | |
106 | + virtual void SetPosData(float x, float y, float z, float rx); | |
107 | + virtual void GetPosData(float *x, float *y, float *z, float *rx); | |
108 | + virtual void SetDrawFlag(bool flag); | |
109 | + virtual bool GetDrawFlag(); | |
110 | + virtual void SetModel(int id, float size); | |
111 | + virtual void SetTexture(int id); | |
112 | + virtual int RunFrame(); | |
113 | + virtual void Render(class D3DGraphics *d3dg); | |
114 | +}; | |
115 | + | |
116 | +//! @brief 人管理クラス | |
117 | +class human : public object | |
118 | +{ | |
119 | +protected: | |
120 | + int point_dataid; //!< ポイントのデータ番号 | |
121 | + signed char point_p4; //!< ポイントの認識番号 | |
122 | + int teamid; //!< チーム番号 | |
123 | + float move_x; //!< X軸速度 | |
124 | + float move_y; //!< Y軸(落下)速度 | |
125 | + float move_z; //!< Z軸速度 | |
126 | + bool move_y_flag; //!< Y軸移動フラグ | |
127 | + float rotation_y; //!< 全体の回転角度 | |
128 | + float armrotation_y; //!< 腕の回転角度 | |
129 | + float reaction_y; //!< 腕を上げ下げする角度 | |
130 | + float legrotation_x; //!< 足の回転角度 | |
131 | + float upmodel_size; //!< 上半身表示サイズ | |
132 | + float armmodel_size; //!< 腕表示サイズ | |
133 | + float legmodel_size; //!< 足表示サイズ | |
134 | + class weapon *weapon[TOTAL_HAVEWEAPON]; //!< 武器 | |
135 | + int selectweapon; //!< 武器A/Bの選択 | |
136 | + int selectweaponcnt; //!< 武器の切り替えカウント | |
137 | + int hp; //!< 体力 | |
138 | +#ifdef HUMAN_DEADBODY_COLLISION | |
139 | + int deadstate; //!< 死体になっているか | |
140 | +#endif | |
141 | + int id_upmodel; //!< 上半身 | |
142 | + int id_armmodel[TOTAL_ARMMODE]; //!< 腕 | |
143 | + int id_legmodel; //!< 足(静止) | |
144 | + int id_walkmodel[TOTAL_WALKMODE]; //!< 足(歩く) | |
145 | + int id_runmodel[TOTAL_RUNMODE]; //!< 足(走る) | |
146 | + float move_rx; //!< 移動角度 | |
147 | + int MoveFlag; //!< 移動方向を表すフラグ | |
148 | + int MoveFlag_lt; //!< (前回の)移動方向を表すフラグ | |
149 | + int scopemode; //!< スコープ使用モード | |
150 | + bool HitFlag; //!< 被弾を表すフラグ | |
151 | + int walkcnt; //!< 歩くモーションのカウント | |
152 | + int runcnt; //!< 走るモーションのカウント | |
153 | + float totalmove; //!< 合計移動量 | |
154 | + int StateGunsightErrorRange; //!< 照準の状態誤差 | |
155 | + int ReactionGunsightErrorRange; //!< 照準の反動誤差 | |
156 | + bool Invincible; //!< 無敵フラグ | |
157 | + | |
158 | + void GunsightErrorRange(); | |
159 | + int CheckAndProcessDead(class Collision *CollD); | |
160 | + void ControlProcess(); | |
161 | + bool CheckBlockAngle(class BlockDataInterface *inblockdata, int bid, int fid, float vx, float vz); | |
162 | + bool MapCollisionDetection(class Collision *CollD, class BlockDataInterface *inblockdata, float *FallDist); | |
163 | + | |
164 | +public: | |
165 | + human(class ParameterInfo *in_Param = NULL, float x = 0.0f, float y = 0.0f, float z = 0.0f, float rx = 0.0f, int id_param = -1, int dataid = 0, signed char p4 = 0, int team = 0, bool flag = false); | |
166 | + ~human(); | |
167 | + virtual void SetParamData(int id_param, int dataid, signed char p4, int team, bool init); | |
168 | + virtual void GetParamData(int *id_param, int *dataid, signed char *p4, int *team); | |
169 | + virtual void GetMovePos(float *x, float *y, float *z); | |
170 | + virtual void SetModel(int upmodel, int armmodel[], int legmodel, int walkmodel[], int runmodel[]); | |
171 | + virtual int GetHP(); | |
172 | + virtual bool SetHP(int in_hp); | |
173 | + virtual bool GetDeadFlag(); | |
174 | + virtual void SetTeamID(int id); | |
175 | + virtual bool GetInvincibleFlag(); | |
176 | + virtual void SetInvincibleFlag(bool flag); | |
177 | + virtual void SetWeapon(class weapon *in_weapon[]); | |
178 | + virtual int PickupWeapon(class weapon *in_weapon); | |
179 | + virtual void ChangeWeapon(int id = -1); | |
180 | + virtual int GetChangeWeaponCnt(); | |
181 | + virtual void GetWeapon(int *out_selectweapon, class weapon *out_weapon[]); | |
182 | + virtual int GetMainWeaponTypeNO(); | |
183 | + virtual bool GetWeaponBlazingmode(); | |
184 | + virtual bool ShotWeapon(int *weapon_paramid, int *GunsightErrorRange); | |
185 | + virtual bool ReloadWeapon(); | |
186 | + virtual bool DumpWeapon(); | |
187 | + virtual int ChangeShotMode(); | |
188 | + virtual void SetMoveForward(); | |
189 | + virtual void SetMoveBack(); | |
190 | + virtual void SetMoveLeft(); | |
191 | + virtual void SetMoveRight(); | |
192 | + virtual void SetMoveWalk(); | |
193 | + virtual int GetMovemode(bool nowdata); | |
194 | + virtual bool SetEnableScope(); | |
195 | + virtual void SetDisableScope(); | |
196 | + virtual int GetScopeMode(); | |
197 | + virtual void GetRxRy(float *rx, float *ry); | |
198 | + virtual void SetRxRy(float rx, float ry); | |
199 | + virtual float GetDeadRy(); | |
200 | + virtual int Jump(); | |
201 | + virtual void AddPosOrder(float rx, float ry, float speed); | |
202 | + virtual void HitBulletHead(int attacks); | |
203 | + virtual void HitBulletUp(int attacks); | |
204 | + virtual void HitBulletLeg(int attacks); | |
205 | + virtual void HitZombieAttack(); | |
206 | + virtual void HitGrenadeExplosion(int attacks); | |
207 | + virtual bool CheckHit(); | |
208 | + virtual float GetTotalMove(); | |
209 | + virtual int RunFrame(class Collision *CollD, class BlockDataInterface *inblockdata, bool F5mode); | |
210 | + virtual int GetGunsightErrorRange(); | |
211 | + virtual void Render(class D3DGraphics *d3dg, class ResourceManager *Resource, bool DrawArm, bool player); | |
212 | +}; | |
213 | + | |
214 | +//! @brief 武器管理クラス | |
215 | +class weapon : public object | |
216 | +{ | |
217 | +protected: | |
218 | + float move_x; //!< X軸移動量 | |
219 | + float move_y; //!< Y軸移動量 | |
220 | + float move_z; //!< Z軸移動量 | |
221 | + bool usingflag; //!< 使用中を表すフラグ | |
222 | + int bullets; //!< 合計弾数 | |
223 | + int Loadbullets; //!< 装弾数 | |
224 | + int shotcnt; //!< 連射カウント | |
225 | + int reloadcnt; //!< リロードカウント | |
226 | + bool motionflag; //!< 座標移動中を表すフラグ | |
227 | + | |
228 | +public: | |
229 | + weapon(class ParameterInfo *in_Param = NULL, float x = 0.0f, float y = 0.0f, float z = 0.0f, float rx = 0.0f, int id_param = 0, int nbs = 0, bool flag = false); | |
230 | + ~weapon(); | |
231 | + virtual void SetPosData(float x, float y, float z, float rx); | |
232 | + virtual void SetParamData(int id_param, int lnbs, int nbs, bool init); | |
233 | + virtual void GetParamData(int *id_param, int *lnbs, int *nbs); | |
234 | + virtual bool GetUsingFlag(); | |
235 | + virtual int Pickup(); | |
236 | + virtual void Dropoff(float x, float y, float z, float rx, float speed); | |
237 | + virtual int Shot(); | |
238 | + virtual int StartReload(); | |
239 | + virtual int RunReload(); | |
240 | + virtual int GetReloadCnt(); | |
241 | + virtual bool ResetWeaponParam(class ResourceManager *Resource, int id_param, int lnbs, int nbs); | |
242 | + virtual int RunFrame(class Collision *CollD); | |
243 | + virtual void Render(class D3DGraphics *d3dg); | |
244 | +}; | |
245 | + | |
246 | +//! @brief 小物管理クラス | |
247 | +class smallobject : public object | |
248 | +{ | |
249 | +protected: | |
250 | + class MIFInterface *MIFdata; //!< 設定値を管理するクラスへのポインタ | |
251 | + float rotation_y; //!< 回転角度 | |
252 | + signed char point_p4; //!< ポイントの認識番号 | |
253 | + int hp; //!< 体力 | |
254 | + float jump_rx; //!< 飛ばす横軸角度 | |
255 | + float move_rx; //!< 飛ばす横軸移動量 | |
256 | + float add_rx; //!< 飛ばす横軸回転量 | |
257 | + float add_ry; //!< 飛ばす縦軸回転量 | |
258 | + int jump_cnt; //!< 飛ばす上昇カウント | |
259 | + | |
260 | +public: | |
261 | + smallobject(class ParameterInfo *in_Param = NULL, class MIFInterface *in_MIFdata = NULL, float x = 0.0f, float y = 0.0f, float z = 0.0f, float rx = 0.0f, int id_param = 0, signed char p4 = 0, bool flag = false); | |
262 | + ~smallobject(); | |
263 | + virtual void SetMIFInterfaceClass(class MIFInterface *in_MIFdata); | |
264 | + virtual void SetParamData(int id_param, signed char p4, bool init); | |
265 | + virtual void GetParamData(int *id_param, signed char *p4); | |
266 | + virtual int GetHP(); | |
267 | + virtual float CollisionMap(class Collision *CollD); | |
268 | + virtual void HitBullet(int attacks); | |
269 | + virtual void HitGrenadeExplosion(int attacks); | |
270 | + virtual void Destruction(); | |
271 | + virtual int RunFrame(); | |
272 | + virtual void Render(D3DGraphics *d3dg); | |
273 | +}; | |
274 | + | |
275 | +//! @brief 弾丸管理クラス | |
276 | +class bullet : public object | |
277 | +{ | |
278 | +protected: | |
279 | + float rotation_y; //!< 回転角度 | |
280 | + int attacks; //!< 攻撃力 | |
281 | + int penetration; //!< 貫通力 | |
282 | + int speed; //!< 弾速 | |
283 | + int teamid; //!< チーム番号 | |
284 | + int humanid; //!< 人のデータ番号 | |
285 | + int cnt; //!< カウント | |
286 | + | |
287 | +public: | |
288 | + bullet(int modelid = -1, int textureid = -1); | |
289 | + ~bullet(); | |
290 | + virtual void SetPosData(float x, float y, float z, float rx, float ry); | |
291 | + virtual void SetParamData(int _attacks, int _penetration, int _speed, int _teamid, int _humanid, bool init); | |
292 | + virtual void GetPosData(float *x, float *y, float *z, float *rx, float *ry); | |
293 | + virtual void GetParamData(int *_attacks, int *_penetration, int *_speed, int *_teamid, int *_humanid); | |
294 | + virtual int RunFrame(); | |
295 | + virtual void Render(class D3DGraphics *d3dg); | |
296 | +}; | |
297 | + | |
298 | +//! @brief 手榴弾管理クラス | |
299 | +class grenade : public bullet | |
300 | +{ | |
301 | + float move_x; //!< X軸移動量 | |
302 | + float move_y; //!< Y軸移動量 | |
303 | + float move_z; //!< Y軸移動量 | |
304 | + | |
305 | +public: | |
306 | + grenade(int modelid = -1, int textureid = -1); | |
307 | + ~grenade(); | |
308 | + void SetParamData(float speed, int _humanid, bool init); | |
309 | + float GetSpeed(); | |
310 | + int RunFrame(class Collision *CollD, class BlockDataInterface *inblockdata); | |
311 | + virtual void Render(D3DGraphics *d3dg); | |
312 | +}; | |
313 | + | |
314 | +//! @brief エフェクト管理クラス | |
315 | +class effect : public object | |
316 | +{ | |
317 | +protected: | |
318 | + int type; //!< 種類 | |
319 | + float camera_rx; //!< カメラ角度 | |
320 | + float camera_ry; //!< カメラ角度 | |
321 | + float move_x; //!< X軸移動量 | |
322 | + float move_y; //!< Y軸移動量 | |
323 | + float move_z; //!< Z軸移動量 | |
324 | + float rotation_texture; //!< 回転角度 | |
325 | + float alpha; //!< 透明度 | |
326 | + int cnt; //!< カウント | |
327 | + int setcnt; //!< 設定されたカウント | |
328 | + | |
329 | +public: | |
330 | + effect(float x = 0.0f, float y = 0.0f, float z = 0.0f, float size = 1.0f, float rotation = 0.0f, int count = 0, int texture = 0, int settype = 0); | |
331 | + ~effect(); | |
332 | + virtual void SetParamData(float in_move_x, float in_move_y, float in_move_z, float size, float rotation, int count, int texture, int settype, bool init); | |
333 | + virtual int RunFrame(float in_camera_rx, float in_camera_ry); | |
334 | + virtual void Render(class D3DGraphics *d3dg); | |
335 | +}; | |
336 | + | |
337 | +//! 人の足の状態を示す定数 | |
338 | +enum Human_LegState { | |
339 | + LEG_STOP = 0, | |
340 | + LEG_WALK, | |
341 | + LEG_RUN | |
342 | +}; | |
343 | + | |
344 | +//! 人の移動操作を表すフラグ | |
345 | +enum Human_MoveFlag { | |
346 | + MOVEFLAG_FORWARD = 0x01, | |
347 | + MOVEFLAG_BACK = 0x02, | |
348 | + MOVEFLAG_LEFT = 0x04, | |
349 | + MOVEFLAG_RIGHT = 0x08, | |
350 | + MOVEFLAG_WALK = 0x10, | |
351 | +}; | |
352 | + | |
353 | +//! エフェクトの種類を表す定数 | |
354 | +enum Effect_Type { | |
355 | + EFFECT_NORMAL = 0x00, //!< ノーマル | |
356 | + EFFECT_DISAPPEAR = 0x01, //!< 消す | |
357 | + EFFECT_MAGNIFY = 0x02, //!< 拡大 | |
358 | + EFFECT_ROTATION = 0x04, //!< 回転 | |
359 | + EFFECT_FALL = 0x08 //!< 落下 | |
360 | +}; | |
361 | + | |
362 | +#endif | |
\ No newline at end of file |
@@ -0,0 +1,165 @@ | ||
1 | +//! @file statemachine.cpp | |
2 | +//! @brief StateMachineクラスの定義 | |
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 "statemachine.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +StateMachine::StateMachine() | |
36 | +{ | |
37 | + NowState = STATE_CREATE_OPENING; | |
38 | + back = false; | |
39 | + f12 = false; | |
40 | +} | |
41 | + | |
42 | +//! @brief ディストラクタ | |
43 | +StateMachine::~StateMachine() | |
44 | +{} | |
45 | + | |
46 | +//! @brief 次の状態へ移行 | |
47 | +void StateMachine::NextState() | |
48 | +{ | |
49 | + switch(NowState){ | |
50 | + case STATE_CREATE_OPENING: | |
51 | + NowState = STATE_NOW_OPENING; | |
52 | + break; | |
53 | + case STATE_NOW_OPENING: | |
54 | + NowState = STATE_DESTROY_OPENING; | |
55 | + break; | |
56 | + case STATE_DESTROY_OPENING: | |
57 | + if( f12 == true ){ | |
58 | + NowState = STATE_CREATE_OPENING; | |
59 | + } | |
60 | + else{ | |
61 | + NowState = STATE_CREATE_MENU; | |
62 | + } | |
63 | + break; | |
64 | + case STATE_CREATE_MENU: | |
65 | + NowState = STATE_NOW_MENU; | |
66 | + break; | |
67 | + case STATE_NOW_MENU: | |
68 | + NowState = STATE_DESTROY_MENU; | |
69 | + break; | |
70 | + case STATE_DESTROY_MENU: | |
71 | + if( f12 == true ){ | |
72 | + NowState = STATE_CREATE_MENU; | |
73 | + } | |
74 | + else if( back == false ){ | |
75 | + NowState = STATE_CREATE_BRIEFING; | |
76 | + } | |
77 | + else{ | |
78 | + NowState = STATE_EXIT; | |
79 | + } | |
80 | + break; | |
81 | + case STATE_CREATE_BRIEFING: | |
82 | + NowState = STATE_NOW_BRIEFING; | |
83 | + break; | |
84 | + case STATE_NOW_BRIEFING: | |
85 | + NowState = STATE_DESTROY_BRIEFING; | |
86 | + break; | |
87 | + case STATE_DESTROY_BRIEFING: | |
88 | + if( f12 == true ){ | |
89 | + NowState = STATE_CREATE_BRIEFING; | |
90 | + } | |
91 | + else if( back == false ){ | |
92 | + NowState = STATE_CREATE_MAINGAME; | |
93 | + } | |
94 | + else{ | |
95 | + NowState = STATE_CREATE_MENU; | |
96 | + } | |
97 | + break; | |
98 | + case STATE_CREATE_MAINGAME: | |
99 | + NowState = STATE_NOW_MAINGAME; | |
100 | + break; | |
101 | + case STATE_NOW_MAINGAME: | |
102 | + NowState = STATE_DESTROY_MAINGAME; | |
103 | + break; | |
104 | + case STATE_DESTROY_MAINGAME: | |
105 | + if( f12 == true ){ | |
106 | + NowState = STATE_CREATE_MAINGAME; | |
107 | + } | |
108 | + else if( back == false ){ | |
109 | + NowState = STATE_CREATE_RESULT; | |
110 | + } | |
111 | + else{ | |
112 | + NowState = STATE_CREATE_MENU; | |
113 | + } | |
114 | + break; | |
115 | + case STATE_CREATE_RESULT: | |
116 | + NowState = STATE_NOW_RESULT; | |
117 | + break; | |
118 | + case STATE_NOW_RESULT: | |
119 | + NowState = STATE_DESTROY_RESULT; | |
120 | + break; | |
121 | + case STATE_DESTROY_RESULT: | |
122 | + if( f12 == true ){ | |
123 | + NowState = STATE_CREATE_RESULT; | |
124 | + } | |
125 | + else{ | |
126 | + NowState = STATE_CREATE_MENU; | |
127 | + } | |
128 | + break; | |
129 | + case STATE_EXIT: | |
130 | + NowState = STATE_EXIT; | |
131 | + break; | |
132 | + default: | |
133 | + NowState = STATE_NULL; | |
134 | + } | |
135 | +} | |
136 | + | |
137 | +//! @brief マウスクリック を受けた | |
138 | +void StateMachine::PushMouseButton() | |
139 | +{ | |
140 | + back = false; | |
141 | + f12 = false; | |
142 | + NextState(); | |
143 | +} | |
144 | + | |
145 | +//! @brief BackSpace キーを受けた | |
146 | +void StateMachine::PushBackSpaceKey() | |
147 | +{ | |
148 | + back = true; | |
149 | + f12 = false; | |
150 | + NextState(); | |
151 | +} | |
152 | + | |
153 | +//! @brief F12 キーを受けた | |
154 | +void StateMachine::PushF12Key() | |
155 | +{ | |
156 | + back = false; | |
157 | + f12 = true; | |
158 | + NextState(); | |
159 | +} | |
160 | + | |
161 | +//! @brief 現在の状態を返す | |
162 | +int StateMachine::GetState() | |
163 | +{ | |
164 | + return NowState; | |
165 | +} | |
\ No newline at end of file |
@@ -0,0 +1,105 @@ | ||
1 | +//! @file scene.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 SCENE_H | |
33 | +#define SCENE_H | |
34 | + | |
35 | +//#include "main.h" | |
36 | +// ヘッダーファイル中の下で宣言する。 | |
37 | + | |
38 | +//! @brief 画面管理クラス(基底クラス) | |
39 | +//! @details ゲームの画面を管理する最も基底のクラスです。 | |
40 | +class scene | |
41 | +{ | |
42 | +protected: | |
43 | + class StateMachine *GameState; //!< ゲーム全体の状態遷移クラス | |
44 | + class D3DGraphics *d3dg; //!< 描画クラス | |
45 | + class InputControl *inputCtrl; //!< 入力取得クラス | |
46 | + unsigned int framecnt; //!< フレーム数のカウント | |
47 | + | |
48 | +public: | |
49 | + scene(); | |
50 | + ~scene(); | |
51 | + virtual void SetClass(StateMachine *in_GameState, D3DGraphics *in_d3dg, InputControl *in_inputCtrl); | |
52 | + virtual int Create(); | |
53 | + virtual void Input(); | |
54 | + virtual void Process(); | |
55 | + virtual bool RenderMain(); | |
56 | + virtual void Destroy(); | |
57 | + float GetEffectAlpha(unsigned int tframecnt, float MaxAlpha, float timingsec, float offsetsec, bool reversal); | |
58 | + float GetEffectAlphaLoop(unsigned int tframecnt, float MaxAlpha, float timingsec, bool reversal); | |
59 | +}; | |
60 | + | |
61 | +//! @brief 2D画面管理クラス(基底クラス) | |
62 | +//! @details ゲーム画面の中で、2D描画のみを行うシーンを管理する基底のクラスです。 | |
63 | +class D2Dscene : public scene | |
64 | +{ | |
65 | +protected: | |
66 | + int gametitle; //!< ゲームタイトル画像 | |
67 | + virtual void Render2D(); | |
68 | + | |
69 | +public: | |
70 | + D2Dscene(); | |
71 | + ~D2Dscene(); | |
72 | + virtual int Create(); | |
73 | + virtual bool RenderMain(); | |
74 | + virtual void Destroy(); | |
75 | +}; | |
76 | + | |
77 | +//! @brief 3D画面管理クラス(基底クラス) | |
78 | +//! @details ゲーム画面の中で、3D描画を行うシーンを管理する基底のクラスです。 | |
79 | +class D3Dscene : public scene | |
80 | +{ | |
81 | +protected: | |
82 | + class SoundManager *GameSound; //!< ゲーム効果音管理クラス | |
83 | + float camera_x; //!< カメラ座標 | |
84 | + float camera_y; //!< カメラ座標 | |
85 | + float camera_z; //!< カメラ座標 | |
86 | + float camera_rx; //!< カメラ座標 | |
87 | + float camera_ry; //!< カメラ座標 | |
88 | + virtual void Render3D(); | |
89 | + virtual void Render2D(); | |
90 | + | |
91 | +public: | |
92 | + D3Dscene(); | |
93 | + ~D3Dscene(); | |
94 | + virtual void SetClass(StateMachine *in_GameState, D3DGraphics *in_d3dg, InputControl *in_inputCtrl, SoundManager *in_GameSound); | |
95 | + virtual void Process(); | |
96 | + virtual void Sound(); | |
97 | + virtual bool RenderMain(); | |
98 | +}; | |
99 | + | |
100 | +#ifndef H_LAYERLEVEL | |
101 | + #define H_LAYERLEVEL 3 //!< Select include file. | |
102 | +#endif | |
103 | +#include "main.h" | |
104 | + | |
105 | +#endif | |
\ No newline at end of file |
@@ -0,0 +1,584 @@ | ||
1 | +//! @file input.cpp | |
2 | +//! @brief InputControlクラスの定義 | |
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 | +//#define INPUT_DIRECTINPUT //!< @brief 入力を取得するインターフェースの選択 @details 定数宣言有効:DirectInput 定数宣言無効(コメント化):WinAPI | |
33 | + | |
34 | +#include "input.h" | |
35 | + | |
36 | +//! @brief コンストラクタ | |
37 | +InputControl::InputControl() | |
38 | +{ | |
39 | +#ifdef INPUT_DIRECTINPUT | |
40 | + pDI = NULL; | |
41 | + pDIDevice = NULL; | |
42 | + pMouse = NULL; | |
43 | +#endif | |
44 | + | |
45 | + //キーボード設定値初期化 | |
46 | + for(int i=0; i<256; i++){ | |
47 | + keys[i] = 0; | |
48 | + } | |
49 | + memcpy(keys_lt, keys, sizeof(char)*256); | |
50 | + | |
51 | + //マウスの設定値初期化 | |
52 | + mx = 0; | |
53 | + my = 0; | |
54 | + mbl = false; | |
55 | + mbr = false; | |
56 | + mbl_lt = mbl; | |
57 | + mbr_lt = mbr; | |
58 | +} | |
59 | + | |
60 | +//! @brief ディストラクタ | |
61 | +InputControl::~InputControl() | |
62 | +{ | |
63 | +#ifdef INPUT_DIRECTINPUT | |
64 | + //キーボードデバイスを開放 | |
65 | + if( pDIDevice != NULL ){ | |
66 | + pDIDevice->Unacquire(); | |
67 | + pDIDevice->Release(); | |
68 | + } | |
69 | + | |
70 | + //マウスデバイスを開放 | |
71 | + if( pMouse != NULL ){ | |
72 | + pMouse->Unacquire(); | |
73 | + pMouse->Release(); | |
74 | + } | |
75 | + | |
76 | + //DirectInputを開放 | |
77 | + if( pDI != NULL) pDI->Release(); | |
78 | +#endif | |
79 | +} | |
80 | + | |
81 | +//! @brief 初期化@n | |
82 | +//! (DirectInput) | |
83 | +//! @param in_hWnd ウィンドウハンドル | |
84 | +//! @return 成功:0 失敗:1 | |
85 | +int InputControl::InitD3Dinput(HWND in_hWnd) | |
86 | +{ | |
87 | +#ifdef INPUT_DIRECTINPUT | |
88 | + //DirectInput初期化 | |
89 | + if( FAILED( DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&pDI, NULL) ) ){ | |
90 | + return 1; | |
91 | + } | |
92 | + | |
93 | + //キーボード初期化 | |
94 | + if( FAILED( pDI->CreateDevice(GUID_SysKeyboard, &pDIDevice, NULL) ) ){ | |
95 | + return 1; | |
96 | + } | |
97 | + pDIDevice->SetDataFormat(&c_dfDIKeyboard); | |
98 | + pDIDevice->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE | DISCL_NOWINKEY); | |
99 | + | |
100 | + //マウス初期化 | |
101 | + if( FAILED( pDI->CreateDevice(GUID_SysMouse, &pMouse, NULL) ) ){ | |
102 | + return 1; | |
103 | + } | |
104 | + pMouse->SetDataFormat(&c_dfDIMouse2); | |
105 | + pMouse->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); | |
106 | + pMouse->Acquire(); | |
107 | +#endif | |
108 | + | |
109 | + //カーソルを非表示 | |
110 | + ShowCursor(false); | |
111 | + | |
112 | + //ウインドウハンドルを設定 | |
113 | + hWnd = in_hWnd; | |
114 | + | |
115 | + return 0; | |
116 | +} | |
117 | + | |
118 | +//! @brief 入力デバイスの状態を更新 | |
119 | +//! @param mousemode マウスの座標取得 絶対値(座標):false 相対値(移動量):true | |
120 | +void InputControl::GetInputState(bool mousemode) | |
121 | +{ | |
122 | +#ifdef INPUT_DIRECTINPUT | |
123 | + //キーボードデバイスが正しく使用できれば | |
124 | + if( pDIDevice != NULL ){ | |
125 | + HRESULT hr = pDIDevice->Acquire(); | |
126 | + if( (hr==DI_OK) || (hr==S_FALSE) ){ | |
127 | + //取得直前のキー情報を、前フレーム情報として記録 | |
128 | + memcpy(keys_lt, keys, sizeof(char)*256); | |
129 | + | |
130 | + //現在のキーボード入力を取得 | |
131 | + pDIDevice->GetDeviceState(sizeof(keys), &keys); | |
132 | + } | |
133 | + } | |
134 | +#else | |
135 | + //取得直前のキー情報を、前フレーム情報として記録 | |
136 | + memcpy(keys_lt, keys, sizeof(char)*256); | |
137 | + | |
138 | + //現在のキーボード入力を取得 | |
139 | + GetKeyboardState((PBYTE)&keys); | |
140 | +#endif | |
141 | + | |
142 | + POINT point; | |
143 | + | |
144 | + //位置をスクリーン座標で取得(WinAPI) | |
145 | + GetCursorPos(&point); | |
146 | + ScreenToClient(hWnd, &point); | |
147 | + | |
148 | +#ifdef INPUT_DIRECTINPUT | |
149 | + //マウスデバイスが正しく初期化されていれば | |
150 | + if( pMouse != NULL ){ | |
151 | + //マウス情報を取得(DirectInput) | |
152 | + DIMOUSESTATE2 dIMouseState={0}; | |
153 | + if( FAILED(pMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &dIMouseState ) ) ){ | |
154 | + pMouse->Acquire(); | |
155 | + } | |
156 | + | |
157 | + //マウス座標を出力 | |
158 | + if( mousemode == false ){ | |
159 | + mx = point.x; | |
160 | + my = point.y; | |
161 | + } | |
162 | + else{ | |
163 | + mx = dIMouseState.lX; | |
164 | + my = dIMouseState.lY; | |
165 | + } | |
166 | + | |
167 | + //取得直前のボタン情報を、前フレーム情報として記録 | |
168 | + mbl_lt = mbl; | |
169 | + mbr_lt = mbr; | |
170 | + | |
171 | + //マウスのボタンを取得 | |
172 | + if( dIMouseState.rgbButtons[0]&0x80 ){ mbl = true; } | |
173 | + else{ mbl = false; } | |
174 | + if( dIMouseState.rgbButtons[1]&0x80 ){ mbr = true; } | |
175 | + else{ mbr = false; } | |
176 | + } | |
177 | +#else | |
178 | + //マウス座標を出力 | |
179 | + if( mousemode == false ){ | |
180 | + mx = point.x; | |
181 | + my = point.y; | |
182 | + } | |
183 | + else{ | |
184 | + mx = point.x - point_lt.x; | |
185 | + my = point.y - point_lt.y; | |
186 | + } | |
187 | + | |
188 | + //マウス座標を前フレーム情報として記録 | |
189 | + point_lt = point; | |
190 | + | |
191 | + | |
192 | + //取得直前のボタン情報を、前フレーム情報として記録 | |
193 | + mbl_lt = mbl; | |
194 | + mbr_lt = mbr; | |
195 | + | |
196 | + //マウスのボタンを取得 | |
197 | + if( GetKeyState(VK_LBUTTON) < 0 ){ mbl = true; } | |
198 | + else{ mbl = false; } | |
199 | + if( GetKeyState(VK_RBUTTON) < 0 ){ mbr = true; } | |
200 | + else{ mbr = false; } | |
201 | +#endif | |
202 | +} | |
203 | + | |
204 | +//! @brief マウスを中心に移動 | |
205 | +void InputControl::MoveMouseCenter() | |
206 | +{ | |
207 | + POINT point; | |
208 | + | |
209 | + //ウインドウ座標の中央を求める | |
210 | + point.x = SCREEN_WIDTH/2; | |
211 | + point.y = SCREEN_HEIGHT/2; | |
212 | + | |
213 | + //前回の座標を書き換え | |
214 | + point_lt = point; | |
215 | + | |
216 | + //スクリーン座標に変換し、座標変更 | |
217 | + ClientToScreen(hWnd, &point); | |
218 | + SetCursorPos(point.x, point.y); | |
219 | +} | |
220 | + | |
221 | +//! @brief キーボードの入力をチェック(リアルタイム) | |
222 | +//! @return 押されてない:false 押されている:true | |
223 | +bool InputControl::CheckKeyNow(int id) | |
224 | +{ | |
225 | + //現在押されていれば | |
226 | + if( keys[id]&0x80 ){ return true; } | |
227 | + return false; | |
228 | +} | |
229 | + | |
230 | +//! @brief キーボードの入力をチェック(押された瞬間) | |
231 | +//! @return 押された瞬間でない:false 押された瞬間である:true | |
232 | +bool InputControl::CheckKeyDown(int id) | |
233 | +{ | |
234 | + //前回は押されておらず、現在押されていれば | |
235 | + if( ((keys_lt[id]&0x80) == 0)&&(keys[id]&0x80) ){ return true; } | |
236 | + return false; | |
237 | +} | |
238 | + | |
239 | +//! @brief キーボードの入力をチェック(離された瞬間) | |
240 | +//! @return 離された瞬間でない:false 離された瞬間である:true | |
241 | +bool InputControl::CheckKeyUp(int id) | |
242 | +{ | |
243 | + //前回を押されており、現在押されていなければ | |
244 | + if( (keys_lt[id]&0x80)&&((keys[id]&0x80) == 0) ){ return true; } | |
245 | + return false; | |
246 | +} | |
247 | + | |
248 | +//! @brief マウスの入力をチェック | |
249 | +//! @param x x軸を受け取る整数値型ポインタ | |
250 | +//! @param y y軸を受け取る整数値型ポインタ | |
251 | +//! @attention 値は直前に実行した GetInputState() への引数に影響される。 | |
252 | +void InputControl::GetMouseMovement(int *x, int *y) | |
253 | +{ | |
254 | + //マウス座標を代入 | |
255 | + *x = mx; | |
256 | + *y = my; | |
257 | +} | |
258 | + | |
259 | +//! @brief マウス・左ボタンの入力をチェック(リアルタイム) | |
260 | +//! @return 押されてない:false 押されている:true | |
261 | +bool InputControl::CheckMouseButtonNowL() | |
262 | +{ | |
263 | + //現在の情報を返す | |
264 | + return mbl; | |
265 | +} | |
266 | + | |
267 | +//! @brief マウス・左ボタンの入力をチェック(押された瞬間) | |
268 | +//! @return 押された瞬間でない:false 押された瞬間である:true | |
269 | +bool InputControl::CheckMouseButtonDownL() | |
270 | +{ | |
271 | + //前回は押されておらず、現在押されていれば | |
272 | + if( (mbl_lt == false)&&(mbl == true) ){ return true; } | |
273 | + return false; | |
274 | +} | |
275 | + | |
276 | +//! @brief マウス・左ボタンの入力をチェック(離された瞬間) | |
277 | +//! @return 離された瞬間でない:false 離された瞬間である:true | |
278 | +bool InputControl::CheckMouseButtonUpL() | |
279 | +{ | |
280 | + //前回を押されており、現在押されていなければ | |
281 | + if( (mbl_lt == true)&&(mbl == false) ){ return true; } | |
282 | + return false; | |
283 | +} | |
284 | + | |
285 | +//! @brief マウス・右ボタンの入力をチェック(リアルタイム) | |
286 | +//! @return 押されてない:false 押されている:true | |
287 | +bool InputControl::CheckMouseButtonNowR() | |
288 | +{ | |
289 | + //現在の情報を返す | |
290 | + return mbr; | |
291 | +} | |
292 | + | |
293 | +//! @brief マウス・右ボタンの入力をチェック(押された瞬間) | |
294 | +//! @return 押された瞬間でない:false 押された瞬間である:true | |
295 | +bool InputControl::CheckMouseButtonDownR() | |
296 | +{ | |
297 | + //前回は押されておらず、現在押されていれば | |
298 | + if( (mbr_lt == false)&&(mbr == true) ){ return true; } | |
299 | + return false; | |
300 | +} | |
301 | + | |
302 | +//! @brief マウス・右ボタンの入力をチェック(離された瞬間) | |
303 | +//! @return 離された瞬間でない:false 離された瞬間である:true | |
304 | +bool InputControl::CheckMouseButtonUpR() | |
305 | +{ | |
306 | + //前回を押されており、現在押されていなければ | |
307 | + if( (mbr_lt == true)&&(mbr == false) ){ return true; } | |
308 | + return false; | |
309 | +} | |
310 | + | |
311 | +//! @brief オリジナルキーコードをDirectInputキーコードへ変換 | |
312 | +//! @param code オリジナルキーコード | |
313 | +//! @return 1以上:DirectInputキーコード -1以下:特殊 0:失敗 | |
314 | +//! @attention 以下、特殊な戻り値の場合―<br>-1:MOUSE L -2:MOUSE R -3:DIK_LSHIFT / DIK_RSHIFT -4:DIK_LCONTROL / DIK_RCONTROL | |
315 | +int OriginalkeycodeToDinputdef(int code) | |
316 | +{ | |
317 | + int out = 0; | |
318 | + | |
319 | +#ifdef INPUT_DIRECTINPUT | |
320 | + switch(code){ | |
321 | + case 0x00: out = DIK_UP; break; | |
322 | + case 0x01: out = DIK_DOWN; break; | |
323 | + case 0x02: out = DIK_LEFT; break; | |
324 | + case 0x03: out = DIK_RIGHT; break; | |
325 | + case 0x04: out = DIK_NUMPAD0; break; | |
326 | + case 0x05: out = DIK_NUMPAD1; break; | |
327 | + case 0x06: out = DIK_NUMPAD2; break; | |
328 | + case 0x07: out = DIK_NUMPAD3; break; | |
329 | + case 0x08: out = DIK_NUMPAD4; break; | |
330 | + case 0x09: out = DIK_NUMPAD5; break; | |
331 | + case 0x0A: out = DIK_NUMPAD6; break; | |
332 | + case 0x0B: out = DIK_NUMPAD7; break; | |
333 | + case 0x0C: out = DIK_NUMPAD8; break; | |
334 | + case 0x0D: out = DIK_NUMPAD9; break; | |
335 | + case 0x0E: out = DIK_BACK; break; | |
336 | + case 0x0F: out = DIK_RETURN; break; | |
337 | + | |
338 | + case 0x10: out = DIK_TAB; break; | |
339 | + case 0x11: out = DIK_SPACE; break; | |
340 | + case 0x12: out = -1; break; //MOUSE L | |
341 | + case 0x13: out = -2; break; //MOUSE R | |
342 | + case 0x14: out = -3; break; //DIK_LSHIFT / DIK_RSHIFT | |
343 | + case 0x15: out = -4; break; //DIK_LCONTROL / DIK_RCONTROL | |
344 | + case 0x16: out = DIK_0; break; | |
345 | + case 0x17: out = DIK_1; break; | |
346 | + case 0x18: out = DIK_2; break; | |
347 | + case 0x19: out = DIK_3; break; | |
348 | + case 0x1A: out = DIK_4; break; | |
349 | + case 0x1B: out = DIK_5; break; | |
350 | + case 0x1C: out = DIK_6; break; | |
351 | + case 0x1D: out = DIK_7; break; | |
352 | + case 0x1E: out = DIK_8; break; | |
353 | + case 0x1F: out = DIK_9; break; | |
354 | + | |
355 | + case 0x20: out = DIK_A; break; | |
356 | + case 0x21: out = DIK_B; break; | |
357 | + case 0x22: out = DIK_C; break; | |
358 | + case 0x23: out = DIK_D; break; | |
359 | + case 0x24: out = DIK_E; break; | |
360 | + case 0x25: out = DIK_F; break; | |
361 | + case 0x26: out = DIK_G; break; | |
362 | + case 0x27: out = DIK_H; break; | |
363 | + case 0x28: out = DIK_I; break; | |
364 | + case 0x29: out = DIK_J; break; | |
365 | + case 0x2A: out = DIK_K; break; | |
366 | + case 0x2B: out = DIK_L; break; | |
367 | + case 0x2C: out = DIK_M; break; | |
368 | + case 0x2D: out = DIK_N; break; | |
369 | + case 0x2E: out = DIK_O; break; | |
370 | + case 0x2F: out = DIK_P; break; | |
371 | + | |
372 | + case 0x30: out = DIK_Q; break; | |
373 | + case 0x31: out = DIK_R; break; | |
374 | + case 0x32: out = DIK_S; break; | |
375 | + case 0x33: out = DIK_T; break; | |
376 | + case 0x34: out = DIK_U; break; | |
377 | + case 0x35: out = DIK_V; break; | |
378 | + case 0x36: out = DIK_W; break; | |
379 | + case 0x37: out = DIK_X; break; | |
380 | + case 0x38: out = DIK_Y; break; | |
381 | + case 0x39: out = DIK_Z; break; | |
382 | + case 0x3A: out = DIK_SLASH; break; | |
383 | + case 0x3B: out = DIK_COLON; break; | |
384 | + case 0x3C: out = DIK_SEMICOLON; break; | |
385 | + case 0x3D: out = DIK_MINUS; break; | |
386 | + case 0x3E: out = DIK_AT; break; | |
387 | + case 0x3F: out = DIK_LBRACKET; break; | |
388 | + | |
389 | + case 0x40: out = DIK_RBRACKET; break; | |
390 | + case 0x41: out = DIK_BACKSLASH; break; | |
391 | + case 0x42: out = DIK_YEN; break; | |
392 | + case 0x43: out = DIK_COMMA; break; | |
393 | + case 0x44: out = DIK_PERIOD; break; | |
394 | + case 0x45: out = DIK_EQUALS; break; | |
395 | + case 0x46: out = DIK_NUMPADSTAR; break; | |
396 | + case 0x47: out = DIK_NUMPADSLASH; break; | |
397 | + case 0x48: out = DIK_NUMPADPLUS; break; | |
398 | + case 0x49: out = DIK_NUMPADMINUS; break; | |
399 | + case 0x4A: out = DIK_NUMPADPERIOD; break; | |
400 | + | |
401 | + default : out = 0; | |
402 | + } | |
403 | +#else | |
404 | + switch(code){ | |
405 | + case 0x00: out = VK_UP; break; | |
406 | + case 0x01: out = VK_DOWN; break; | |
407 | + case 0x02: out = VK_LEFT; break; | |
408 | + case 0x03: out = VK_RIGHT; break; | |
409 | + case 0x04: out = VK_NUMPAD0; break; | |
410 | + case 0x05: out = VK_NUMPAD1; break; | |
411 | + case 0x06: out = VK_NUMPAD2; break; | |
412 | + case 0x07: out = VK_NUMPAD3; break; | |
413 | + case 0x08: out = VK_NUMPAD4; break; | |
414 | + case 0x09: out = VK_NUMPAD5; break; | |
415 | + case 0x0A: out = VK_NUMPAD6; break; | |
416 | + case 0x0B: out = VK_NUMPAD7; break; | |
417 | + case 0x0C: out = VK_NUMPAD8; break; | |
418 | + case 0x0D: out = VK_NUMPAD9; break; | |
419 | + case 0x0E: out = VK_BACK; break; | |
420 | + case 0x0F: out = VK_RETURN; break; | |
421 | + | |
422 | + case 0x10: out = VK_TAB; break; | |
423 | + case 0x11: out = VK_SPACE; break; | |
424 | + case 0x12: out = -1; break; //MOUSE L | |
425 | + case 0x13: out = -2; break; //MOUSE R | |
426 | + case 0x14: out = VK_SHIFT; break; | |
427 | + case 0x15: out = VK_CONTROL; break; | |
428 | + case 0x16: out = '0'; break; | |
429 | + case 0x17: out = '1'; break; | |
430 | + case 0x18: out = '2'; break; | |
431 | + case 0x19: out = '3'; break; | |
432 | + case 0x1A: out = '4'; break; | |
433 | + case 0x1B: out = '5'; break; | |
434 | + case 0x1C: out = '6'; break; | |
435 | + case 0x1D: out = '7'; break; | |
436 | + case 0x1E: out = '8'; break; | |
437 | + case 0x1F: out = '9'; break; | |
438 | + | |
439 | + case 0x20: out = 'A'; break; | |
440 | + case 0x21: out = 'B'; break; | |
441 | + case 0x22: out = 'C'; break; | |
442 | + case 0x23: out = 'D'; break; | |
443 | + case 0x24: out = 'E'; break; | |
444 | + case 0x25: out = 'F'; break; | |
445 | + case 0x26: out = 'G'; break; | |
446 | + case 0x27: out = 'H'; break; | |
447 | + case 0x28: out = 'I'; break; | |
448 | + case 0x29: out = 'J'; break; | |
449 | + case 0x2A: out = 'K'; break; | |
450 | + case 0x2B: out = 'L'; break; | |
451 | + case 0x2C: out = 'M'; break; | |
452 | + case 0x2D: out = 'N'; break; | |
453 | + case 0x2E: out = 'O'; break; | |
454 | + case 0x2F: out = 'P'; break; | |
455 | + | |
456 | + case 0x30: out = 'Q'; break; | |
457 | + case 0x31: out = 'R'; break; | |
458 | + case 0x32: out = 'S'; break; | |
459 | + case 0x33: out = 'T'; break; | |
460 | + case 0x34: out = 'U'; break; | |
461 | + case 0x35: out = 'V'; break; | |
462 | + case 0x36: out = 'W'; break; | |
463 | + case 0x37: out = 'X'; break; | |
464 | + case 0x38: out = 'Y'; break; | |
465 | + case 0x39: out = 'Z'; break; | |
466 | + case 0x3A: out = VK_DIVIDE; break; | |
467 | + case 0x3B: out = VK_OEM_1; break; | |
468 | + case 0x3C: out = VK_OEM_PLUS; break; | |
469 | + case 0x3D: out = VK_OEM_MINUS; break; | |
470 | + case 0x3E: out = VK_OEM_3; break; | |
471 | + case 0x3F: out = VK_OEM_4; break; | |
472 | + | |
473 | + case 0x40: out = VK_OEM_6; break; | |
474 | + case 0x41: out = VK_OEM_102; break; | |
475 | + case 0x42: out = VK_OEM_5; break; | |
476 | + case 0x43: out = VK_OEM_COMMA; break; | |
477 | + case 0x44: out = VK_OEM_PERIOD; break; | |
478 | + case 0x45: out = VK_OEM_7; break; | |
479 | + case 0x46: out = VK_MULTIPLY ; break; | |
480 | + case 0x47: out = VK_DIVIDE; break; | |
481 | + case 0x48: out = VK_ADD; break; | |
482 | + case 0x49: out = VK_SUBTRACT; break; | |
483 | + case 0x4A: out = VK_DECIMAL; break; | |
484 | + | |
485 | + default : out = 0; | |
486 | + } | |
487 | +#endif | |
488 | + | |
489 | + return out; | |
490 | +} | |
491 | + | |
492 | +//! @brief 左右キーのキーコード取得 | |
493 | +//! @param id Shiftキー:0 Ctrlキー:1 | |
494 | +//! @param *CodeL 左側キーのキーコードを受け取るポインタ | |
495 | +//! @param *CodeR 右側キーのキーコードを受け取るポインタ | |
496 | +//! @return 成功:ture 失敗:false | |
497 | +bool GetDoubleKeyCode(int id, int *CodeL, int *CodeR) | |
498 | +{ | |
499 | +#ifdef INPUT_DIRECTINPUT | |
500 | + if( id == 0 ){ | |
501 | + *CodeL = DIK_LSHIFT; | |
502 | + *CodeR = DIK_RSHIFT; | |
503 | + return true; | |
504 | + } | |
505 | + if( id == 1 ){ | |
506 | + *CodeL = DIK_LCONTROL; | |
507 | + *CodeR = DIK_RCONTROL; | |
508 | + return true; | |
509 | + } | |
510 | +#endif | |
511 | + | |
512 | + //エラー | |
513 | + *CodeL = 0x00; | |
514 | + *CodeR = 0x00; | |
515 | + return false; | |
516 | +} | |
517 | + | |
518 | +//! @brief Escキーのキーコード取得 | |
519 | +//! @return キーコード | |
520 | +int GetEscKeycode() | |
521 | +{ | |
522 | +#ifdef INPUT_DIRECTINPUT | |
523 | + return DIK_ESCAPE; | |
524 | +#else | |
525 | + return VK_ESCAPE; | |
526 | +#endif | |
527 | +} | |
528 | + | |
529 | +//! @brief Homeキーのキーコード取得 | |
530 | +//! @return キーコード | |
531 | +int GetHomeKeycode() | |
532 | +{ | |
533 | +#ifdef INPUT_DIRECTINPUT | |
534 | + return DIK_HOME; | |
535 | +#else | |
536 | + return VK_HOME; | |
537 | +#endif | |
538 | +} | |
539 | + | |
540 | +//! @brief ファンクションキー(F1〜F12)のキーコードを取得 | |
541 | +//! @param key 番号(1〜12) | |
542 | +//! @return キーコード | |
543 | +int GetFunctionKeycode(int key) | |
544 | +{ | |
545 | + int out = 0; | |
546 | + | |
547 | +#ifdef INPUT_DIRECTINPUT | |
548 | + switch(key){ | |
549 | + case 1: out = DIK_F1; break; | |
550 | + case 2: out = DIK_F2; break; | |
551 | + case 3: out = DIK_F3; break; | |
552 | + case 4: out = DIK_F4; break; | |
553 | + case 5: out = DIK_F5; break; | |
554 | + case 6: out = DIK_F6; break; | |
555 | + case 7: out = DIK_F7; break; | |
556 | + case 8: out = DIK_F8; break; | |
557 | + case 9: out = DIK_F9; break; | |
558 | + case 10: out = DIK_F10; break; | |
559 | + case 11: out = DIK_F11; break; | |
560 | + case 12: out = DIK_F12; break; | |
561 | + | |
562 | + default : out = 0; | |
563 | + } | |
564 | +#else | |
565 | + switch(key){ | |
566 | + case 1: out = VK_F1; break; | |
567 | + case 2: out = VK_F2; break; | |
568 | + case 3: out = VK_F3; break; | |
569 | + case 4: out = VK_F4; break; | |
570 | + case 5: out = VK_F5; break; | |
571 | + case 6: out = VK_F6; break; | |
572 | + case 7: out = VK_F7; break; | |
573 | + case 8: out = VK_F8; break; | |
574 | + case 9: out = VK_F9; break; | |
575 | + case 10: out = VK_F10; break; | |
576 | + case 11: out = VK_F11; break; | |
577 | + case 12: out = VK_F12; break; | |
578 | + | |
579 | + default : out = 0; | |
580 | + } | |
581 | +#endif | |
582 | + | |
583 | + return out; | |
584 | +} | |
\ No newline at end of file |
@@ -0,0 +1,200 @@ | ||
1 | +//! @file config.cpp | |
2 | +//! @brief configクラスの定義 | |
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 "config.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +Config::Config() | |
36 | +{ | |
37 | + //各種メンバー変数初期化 | |
38 | + for(int i=0; i<TOTAL_ControlKey; i++){ | |
39 | + Keycode[i] = 0; | |
40 | + } | |
41 | + MouseSensitivity = 0; | |
42 | + FullscreenFlag = false; | |
43 | + SoundFlag = false; | |
44 | + BloodFlag = false; | |
45 | + Brightness = 0; | |
46 | + InvertMouseFlag = false; | |
47 | + FrameskipFlag = false; | |
48 | + AnotherGunsightFlag = false; | |
49 | + strcpy(PlayerName, ""); | |
50 | +} | |
51 | + | |
52 | +//! @brief ディストラクタ | |
53 | +Config::~Config() | |
54 | +{} | |
55 | + | |
56 | +//! @brief 設定ファイルを読み込む | |
57 | +//! @param fname ファイル名 | |
58 | +//! @return 成功:0 失敗:1 | |
59 | +int Config::LoadFile(char *fname) | |
60 | +{ | |
61 | + FILE *fp; | |
62 | + char buf; | |
63 | + | |
64 | + //ファイルを開く | |
65 | + fp = fopen(fname, "rb"); | |
66 | + if( fp == NULL ){ | |
67 | + return 1; | |
68 | + } | |
69 | + | |
70 | + //キーコードを取得 | |
71 | + for(int i=0; i<TOTAL_ControlKey; i++){ | |
72 | + fread(&buf, 1, 1, fp); | |
73 | + Keycode[i] = buf; | |
74 | + } | |
75 | + | |
76 | + //マウス感度 | |
77 | + fread(&buf, 1, 1, fp); | |
78 | + MouseSensitivity = buf; | |
79 | + | |
80 | + //フルスクリーン有効 | |
81 | + fread(&buf, 1, 1, fp); | |
82 | + if( buf == 0x00 ){ FullscreenFlag = false; } | |
83 | + else{ FullscreenFlag = true; } | |
84 | + | |
85 | + //効果音有効 | |
86 | + fread(&buf, 1, 1, fp); | |
87 | + if( buf == 0x00 ){ SoundFlag = false; } | |
88 | + else{ SoundFlag = true; } | |
89 | + | |
90 | + //出血有効 | |
91 | + fread(&buf, 1, 1, fp); | |
92 | + if( buf == 0x00 ){ BloodFlag = false; } | |
93 | + else{ BloodFlag = true; } | |
94 | + | |
95 | + //画面の明るさ | |
96 | + fread(&buf, 1, 1, fp); | |
97 | + Brightness = buf; | |
98 | + | |
99 | + //マウス反転 | |
100 | + fread(&buf, 1, 1, fp); | |
101 | + if( buf == 0x00 ){ InvertMouseFlag = false; } | |
102 | + else{ InvertMouseFlag = true; } | |
103 | + | |
104 | + //フレームスキップ | |
105 | + fread(&buf, 1, 1, fp); | |
106 | + if( buf == 0x00 ){ FrameskipFlag = false; } | |
107 | + else{ FrameskipFlag = true; } | |
108 | + | |
109 | + //別の標準を使用 | |
110 | + fread(&buf, 1, 1, fp); | |
111 | + if( buf == 0x00 ){ AnotherGunsightFlag = false; } | |
112 | + else{ AnotherGunsightFlag = true; } | |
113 | + | |
114 | + //プレイヤー名 | |
115 | + fread(PlayerName, 1, MAX_PLAYERNAME, fp); | |
116 | + | |
117 | + //ファイルハンドルを閉じる | |
118 | + fclose(fp); | |
119 | + return 0; | |
120 | +} | |
121 | + | |
122 | +//! @brief オリジナルキーコードを取得 | |
123 | +//! @param id 定数 | |
124 | +//! @return オリジナルキーコード | |
125 | +int Config::GetKeycode(int id) | |
126 | +{ | |
127 | + if( (id < 0)||((TOTAL_ControlKey -1) < id) ){ return 0; } | |
128 | + | |
129 | + return Keycode[id]; | |
130 | +} | |
131 | + | |
132 | +//! @brief マウス感度取得 | |
133 | +//! @return 生の値 | |
134 | +int Config::GetMouseSensitivity() | |
135 | +{ | |
136 | + return MouseSensitivity; | |
137 | +} | |
138 | + | |
139 | +//! @brief 画面表示モード取得 | |
140 | +//! @return ウィンドウ:false フルスクリーン:true | |
141 | +bool Config::GetFullscreenFlag() | |
142 | +{ | |
143 | + return FullscreenFlag; | |
144 | +} | |
145 | + | |
146 | +//! @brief 効果音設定取得 | |
147 | +//! @return 無効:false 有効:true | |
148 | +bool Config::GetSoundFlag() | |
149 | +{ | |
150 | + return SoundFlag; | |
151 | +} | |
152 | + | |
153 | +//! @brief 出血設定取得 | |
154 | +//! @return 無効:false 有効:true | |
155 | +bool Config::GetBloodFlag() | |
156 | +{ | |
157 | + return BloodFlag; | |
158 | +} | |
159 | + | |
160 | +//! @brief 画面の明るさ設定取得 | |
161 | +//! @return 生の値 | |
162 | +int Config::GetBrightness() | |
163 | +{ | |
164 | + return Brightness; | |
165 | +} | |
166 | + | |
167 | +//! @brief マウス反転設定取得 | |
168 | +//! @return 無効:false 有効:true | |
169 | +bool Config::GetInvertMouseFlag() | |
170 | +{ | |
171 | + return InvertMouseFlag; | |
172 | +} | |
173 | + | |
174 | +//! @brief フレームスキップ設定取得 | |
175 | +//! @return 無効:false 有効:true | |
176 | +bool Config::GetFrameskipFlag() | |
177 | +{ | |
178 | + return FrameskipFlag; | |
179 | +} | |
180 | + | |
181 | +//! @brief 別の照準を使用設定取得 | |
182 | +//! @return 無効:false 有効:true | |
183 | +bool Config::GetAnotherGunsightFlag() | |
184 | +{ | |
185 | + return AnotherGunsightFlag; | |
186 | +} | |
187 | + | |
188 | +//! @brief プレイヤー名取得 | |
189 | +//! @param out_str 受け取る文字列型ポインタ | |
190 | +//! @return プレイヤー名文字数 | |
191 | +int Config::GetPlayerName(char *out_str) | |
192 | +{ | |
193 | + if( out_str == NULL ){ return 0; } | |
194 | + | |
195 | + //ポインタにコピーする | |
196 | + strcpy(out_str, PlayerName); | |
197 | + | |
198 | + //文字数を返す | |
199 | + return strlen(PlayerName); | |
200 | +} |
@@ -0,0 +1,1031 @@ | ||
1 | +//! @file datafile.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 "datafile.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +DataInterface::DataInterface() | |
36 | +{ | |
37 | + datas = 0; | |
38 | +} | |
39 | + | |
40 | +//! @brief ディストラクタ | |
41 | +DataInterface::~DataInterface() | |
42 | +{} | |
43 | + | |
44 | +//! @brief データファイルを読みこむ | |
45 | +//! @param fname ファイル名 | |
46 | +//! @return 成功:0 失敗:1 | |
47 | +int DataInterface::LoadFiledata(char *fname) | |
48 | +{ | |
49 | + return 0; | |
50 | +} | |
51 | + | |
52 | +//! @brief 合計データ数の取得 | |
53 | +//! @return 合計データ数 | |
54 | +int DataInterface::GetTotaldatas() | |
55 | +{ | |
56 | + return datas; | |
57 | +} | |
58 | + | |
59 | +//! @brief データを取得 | |
60 | +//! @param out_data 受け取るポインタ | |
61 | +//! @param id 認識番号 | |
62 | +//! @return 成功:0 失敗:0以外 | |
63 | +int DataInterface::Getdata(void *out_data, int id) | |
64 | +{ | |
65 | + return 0; | |
66 | +} | |
67 | + | |
68 | +//! @brief コンストラクタ | |
69 | +BlockDataInterface::BlockDataInterface() | |
70 | +{ | |
71 | + //blockdata構造体初期化 | |
72 | + data = new blockdata[MAX_BLOCKS]; | |
73 | + | |
74 | + //テクスチャ設定初期化 | |
75 | + for(int i=0; i<TOTAL_BLOCKTEXTURE; i++){ | |
76 | + strcpy(texture[i], ""); | |
77 | + } | |
78 | +} | |
79 | + | |
80 | +//! @brief ディストラクタ | |
81 | +BlockDataInterface::~BlockDataInterface() | |
82 | +{ | |
83 | + //blockdata構造体解放 | |
84 | + if( data != NULL ) delete [] data; | |
85 | +} | |
86 | + | |
87 | +//! @brief ブロックデータファイルを読みこむ | |
88 | +//! @param fname ファイル名 | |
89 | +//! @return 成功:0 失敗:1 | |
90 | +int BlockDataInterface::LoadFiledata(char *fname) | |
91 | +{ | |
92 | + FILE *fp; | |
93 | + unsigned char bdata_header[2]; | |
94 | + float bdata_main[80]; | |
95 | + char bdata_mainb[30]; | |
96 | + | |
97 | + //ファイルを読み込む | |
98 | + fp = fopen(fname, "rb"); | |
99 | + if( fp == NULL ){ | |
100 | + return 1; | |
101 | + } | |
102 | + | |
103 | + //テクスチャを取得 | |
104 | + for(int i=0; i<TOTAL_BLOCKTEXTURE; i++){ | |
105 | + fread(texture[i], 1, 31, fp ); | |
106 | + } | |
107 | + | |
108 | + //データ数を取得 | |
109 | + fread( bdata_header, 1, 2, fp ); | |
110 | + datas = (int)bdata_header[1]*256 + bdata_header[0]; | |
111 | + if( datas > MAX_BLOCKS ){ | |
112 | + datas = MAX_BLOCKS; | |
113 | + } | |
114 | + | |
115 | + //ブロックデータ数分取得 | |
116 | + for(int i=0; i<datas; i++){ | |
117 | + //ブロックのを頂点情報と面情報を取得 | |
118 | + fread( bdata_main, 4, 24+48, fp ); | |
119 | + fread( bdata_mainb, 1, 28, fp ); | |
120 | + | |
121 | + //データ番号を設定 | |
122 | + data[i].id = i; | |
123 | + | |
124 | + //ブロックの頂点情報に設定 | |
125 | + for(int j=0; j<8; j++){ | |
126 | + data[i].x[j] = bdata_main[j]; | |
127 | + data[i].y[j] = bdata_main[j+8]; | |
128 | + data[i].z[j] = bdata_main[j+16]; | |
129 | + } | |
130 | + | |
131 | + //ブロックの面情報を設定 | |
132 | + for(int j=0; j<6; j++){ | |
133 | + data[i].material[j].textureID = (int)bdata_mainb[j*4]; | |
134 | + data[i].material[j].u[0] = bdata_main[j*4+24]; | |
135 | + data[i].material[j].v[0] = bdata_main[j*4+48]; | |
136 | + data[i].material[j].u[1] = bdata_main[j*4+25]; | |
137 | + data[i].material[j].v[1] = bdata_main[j*4+49]; | |
138 | + data[i].material[j].u[2] = bdata_main[j*4+26]; | |
139 | + data[i].material[j].v[2] = bdata_main[j*4+50]; | |
140 | + data[i].material[j].u[3] = bdata_main[j*4+27]; | |
141 | + data[i].material[j].v[3] = bdata_main[j*4+51]; | |
142 | + } | |
143 | + } | |
144 | + | |
145 | + //ファイルハンドルを解放 | |
146 | + fclose( fp ); | |
147 | + | |
148 | + return 0; | |
149 | +} | |
150 | + | |
151 | +//! @brief ブロックデータの法線・影を算出する | |
152 | +//! @param screen ブロックを暗くする | |
153 | +//! @attention LoadBlockdata()関数で読みこんだ後、一度だけ実行。 | |
154 | +void BlockDataInterface::CalculationBlockdata(bool screen) | |
155 | +{ | |
156 | + int vID[4]; | |
157 | + int uvID[4]; | |
158 | + float g; | |
159 | + float xs, ys, zs; | |
160 | + float lx, ly, lz; | |
161 | + float rx, ry, rz, a; | |
162 | + | |
163 | + //光源の角度を設定 | |
164 | + lx = cos(LIGHT_RX); | |
165 | + ly = sin(LIGHT_RY); | |
166 | + lz = sin(LIGHT_RX); | |
167 | + | |
168 | + //各ブロックの面情報分処理する | |
169 | + for(int i=0; i<datas; i++){ | |
170 | + for(int j=0; j<6; j++){ | |
171 | + | |
172 | + //ブロック頂点データの関連付けを取得 | |
173 | + blockdataface(j, vID, uvID); | |
174 | + | |
175 | + //面の法線(ベクトル)と、その長さを求める | |
176 | + xs = ((data[i].y[ vID[3] ] - data[i].y[ vID[2] ]) * (data[i].z[ vID[0] ] - data[i].z[ vID[2] ])) - ((data[i].y[ vID[0] ] - data[i].y[ vID[2] ]) * (data[i].z[ vID[3] ] - data[i].z[ vID[2] ])); | |
177 | + ys = ((data[i].z[ vID[3] ] - data[i].z[ vID[2] ]) * (data[i].x[ vID[0] ] - data[i].x[ vID[2] ])) - ((data[i].z[ vID[0] ] - data[i].z[ vID[2] ]) * (data[i].x[ vID[3] ] - data[i].x[ vID[2] ])); | |
178 | + zs = ((data[i].x[ vID[3] ] - data[i].x[ vID[2] ]) * (data[i].y[ vID[0] ] - data[i].y[ vID[2] ])) - ((data[i].x[ vID[0] ] - data[i].x[ vID[2] ]) * (data[i].y[ vID[3] ] - data[i].y[ vID[2] ])); | |
179 | + g = (float)sqrt(xs * xs + ys * ys + zs * zs); | |
180 | + | |
181 | + //もし法線がおかしければ、もう一方の三角形で計算をやり直す | |
182 | + if( g == 0.0f ){ | |
183 | + xs = ((data[i].y[ vID[1] ] - data[i].y[ vID[0] ]) * (data[i].z[ vID[2] ] - data[i].z[ vID[0] ])) - ((data[i].y[ vID[2] ] - data[i].y[ vID[0] ]) * (data[i].z[ vID[1] ] - data[i].z[ vID[0] ])); | |
184 | + ys = ((data[i].z[ vID[1] ] - data[i].z[ vID[0] ]) * (data[i].x[ vID[2] ] - data[i].x[ vID[0] ])) - ((data[i].z[ vID[2] ] - data[i].z[ vID[0] ]) * (data[i].x[ vID[1] ] - data[i].x[ vID[0] ])); | |
185 | + zs = ((data[i].x[ vID[1] ] - data[i].x[ vID[0] ]) * (data[i].y[ vID[2] ] - data[i].y[ vID[0] ])) - ((data[i].x[ vID[2] ] - data[i].x[ vID[0] ]) * (data[i].y[ vID[1] ] - data[i].y[ vID[0] ])); | |
186 | + g = (float)sqrt(xs * xs + ys * ys + zs * zs); | |
187 | + } | |
188 | + | |
189 | + //法線(ベクトル)を正規化 | |
190 | + data[i].material[j].vx = xs / g; | |
191 | + data[i].material[j].vy = ys / g; | |
192 | + data[i].material[j].vz = zs / g; | |
193 | + | |
194 | + //面の明るさを求める | |
195 | + rx = data[i].material[j].vx + lx; | |
196 | + ry = data[i].material[j].vy + ly; | |
197 | + rz = data[i].material[j].vz + lz; | |
198 | + //a = sqrt(fabs(rx*rx + ry*ry + rz*rz)) / 2.0f; | |
199 | + //data[i].material[j].shadow = a/2 + 0.5f; | |
200 | + a = sqrt(rx*rx + ry*ry + rz*rz) / 3.0f; | |
201 | + data[i].material[j].shadow = a/2; | |
202 | + if( screen == false ){ | |
203 | + data[i].material[j].shadow += 0.5f; | |
204 | + } | |
205 | + else{ | |
206 | + data[i].material[j].shadow += 0.2f; | |
207 | + } | |
208 | + } | |
209 | + } | |
210 | +} | |
211 | + | |
212 | +//! @brief ブロックデータに設定されたテクスチャのファイル名を取得 | |
213 | +//! @param fname ファイル名を受け取る文字列型ポインタ | |
214 | +//! @param id テクスチャ番号 | |
215 | +//! @return 成功:0 失敗:0以外 | |
216 | +int BlockDataInterface::GetTexture(char *fname, int id) | |
217 | +{ | |
218 | + if( data == NULL ){ return 1; } | |
219 | + if( (id < 0)||((TOTAL_BLOCKTEXTURE -1) < id) ){ return 2; } | |
220 | + | |
221 | + //ポインタにテクスチャ名をコピー | |
222 | + strcpy(fname, texture[id]); | |
223 | + | |
224 | + return 0; | |
225 | +} | |
226 | + | |
227 | +//! @brief ブロックデータを取得 | |
228 | +//! @param out_data 受け取るblockdata型ポインタ | |
229 | +//! @param id 認識番号 | |
230 | +//! @return 成功:0 失敗:0以外 | |
231 | +int BlockDataInterface::Getdata(blockdata *out_data, int id) | |
232 | +{ | |
233 | + if( data == NULL ){ return 1; } | |
234 | + if( (id < 0)||((datas -1) < id) ){ return 2; } | |
235 | + | |
236 | + //ブロックデータを取得 | |
237 | + memcpy(out_data, &(data[id]), sizeof(blockdata)); | |
238 | + | |
239 | + return 0; | |
240 | +} | |
241 | + | |
242 | +//! @brief ブロック頂点データの関連付けを取得 | |
243 | +// | |
244 | +// 3 ・----・2 | |
245 | +// /| /| | |
246 | +// / | / | | |
247 | +// 0 ・----・1 | | |
248 | +// |7 ・-| --・6 | |
249 | +// | / | / | |
250 | +// | / | / | |
251 | +// 4 ・----・5 | |
252 | +// | |
253 | +// C-----D | |
254 | +// | | | |
255 | +// | | | |
256 | +// B-----A | |
257 | +// | |
258 | +// 上[0](ABCD) = (1032) | |
259 | +// 下[1] = (6745) | |
260 | +// 前[2] = (5401) | |
261 | +// 右[3] = (6512) | |
262 | +// 奥[4] = (7623) | |
263 | +// 左[5] = (4730) | |
264 | +bool blockdataface(int faceID, int* vID, int* uvID) | |
265 | +{ | |
266 | + if( faceID == 0 ){ | |
267 | + if( vID != NULL ){ | |
268 | + vID[0] = 1; vID[1] = 0; vID[2] = 3; vID[3] = 2; | |
269 | + } | |
270 | + if( uvID != NULL ){ | |
271 | + uvID[0] = 2; uvID[1] = 3; uvID[2] = 0; uvID[3] = 1; | |
272 | + } | |
273 | + return TRUE; | |
274 | + } | |
275 | + if( faceID == 1 ){ | |
276 | + if( vID != NULL ){ | |
277 | + vID[0] = 6; vID[1] = 7; vID[2] = 4; vID[3] = 5; | |
278 | + } | |
279 | + if( uvID != NULL ){ | |
280 | + uvID[0] = 2; uvID[1] = 3; uvID[2] = 0; uvID[3] = 1; | |
281 | + } | |
282 | + return TRUE; | |
283 | + } | |
284 | + if( faceID == 2 ){ | |
285 | + if( vID != NULL ){ | |
286 | + vID[0] = 5; vID[1] = 4; vID[2] = 0; vID[3] = 1; | |
287 | + } | |
288 | + if( uvID != NULL ){ | |
289 | + uvID[0] = 2; uvID[1] = 3; uvID[2] = 0; uvID[3] = 1; | |
290 | + } | |
291 | + return TRUE; | |
292 | + } | |
293 | + if( faceID == 3 ){ | |
294 | + if( vID != NULL ){ | |
295 | + vID[0] = 6; vID[1] = 5; vID[2] = 1; vID[3] = 2; | |
296 | + } | |
297 | + if( uvID != NULL ){ | |
298 | + uvID[0] = 2; uvID[1] = 3; uvID[2] = 0; uvID[3] = 1; | |
299 | + } | |
300 | + return TRUE; | |
301 | + } | |
302 | + if( faceID == 4 ){ | |
303 | + if( vID != NULL ){ | |
304 | + vID[0] = 7; vID[1] = 6; vID[2] = 2; vID[3] = 3; | |
305 | + } | |
306 | + if( uvID != NULL ){ | |
307 | + uvID[0] = 2; uvID[1] = 3; uvID[2] = 0; uvID[3] = 1; | |
308 | + } | |
309 | + return TRUE; | |
310 | + } | |
311 | + if( faceID == 5 ){ | |
312 | + if( vID != NULL ){ | |
313 | + vID[0] = 4; vID[1] = 7; vID[2] = 3; vID[3] = 0; | |
314 | + } | |
315 | + if( uvID != NULL ){ | |
316 | + uvID[0] = 2; uvID[1] = 3; uvID[2] = 0; uvID[3] = 1; | |
317 | + } | |
318 | + return TRUE; | |
319 | + } | |
320 | + return FALSE; | |
321 | +} | |
322 | + | |
323 | +//! @brief コンストラクタ | |
324 | +PointDataInterface::PointDataInterface() | |
325 | +{ | |
326 | + //pointdata構造体初期化 | |
327 | + data = new pointdata[MAX_POINTS]; | |
328 | + | |
329 | + //イベントメッセージ初期化 | |
330 | + for(int i=0; i<MAX_POINTMESSAGES; i++){ | |
331 | + text[i] = new char[MAX_POINTMESSAGEBYTE]; | |
332 | + } | |
333 | +} | |
334 | + | |
335 | +//! @brief ディストラクタ | |
336 | +PointDataInterface::~PointDataInterface() | |
337 | +{ | |
338 | + //pointdata構造体解放 | |
339 | + if( data != NULL ) delete [] data; | |
340 | + | |
341 | + //イベントメッセージ解放 | |
342 | + for(int i=0; i<MAX_POINTMESSAGES; i++){ | |
343 | + if( text[i] != NULL ) delete [] text[i]; | |
344 | + } | |
345 | +} | |
346 | + | |
347 | +//! @brief ポイントデータファイルを読みこむ | |
348 | +//! @param fname ファイル名 | |
349 | +//! @return 成功:0 失敗:1 | |
350 | +int PointDataInterface::LoadFiledata(char *fname) | |
351 | +{ | |
352 | + FILE *fp; | |
353 | + unsigned char pdata_header[2]; | |
354 | + float pdata_mainf[200][4]; | |
355 | + char pdata_mainc[200][4]; | |
356 | + char fname2[MAX_PATH]; | |
357 | + | |
358 | + //ファイルを読み込む | |
359 | + fp = fopen( fname, "rb" ); | |
360 | + if( fp == NULL ){ | |
361 | + return 1; | |
362 | + } | |
363 | + | |
364 | + //データ数を取得 | |
365 | + fread( pdata_header, 1, 2, fp ); | |
366 | + datas = (int)pdata_header[1]*256 + pdata_header[0]; | |
367 | + if( datas > MAX_POINTS ){ | |
368 | + datas = MAX_POINTS; | |
369 | + } | |
370 | + | |
371 | + //ポイントデータ数分処理する | |
372 | + for(int i=0; i<datas; i++){ | |
373 | + //データ番号設定 | |
374 | + data[i].id = i; | |
375 | + | |
376 | + //座標データ取得 | |
377 | + fread( pdata_mainf[i], 4, 4, fp ); | |
378 | + data[i].x = pdata_mainf[i][0]; | |
379 | + data[i].y = pdata_mainf[i][1]; | |
380 | + data[i].z = pdata_mainf[i][2]; | |
381 | + data[i].r = pdata_mainf[i][3]; | |
382 | + | |
383 | + //パラメータ取得 | |
384 | + fread( pdata_mainc[i], 1, 4, fp ); | |
385 | + data[i].p1 = pdata_mainc[i][0]; | |
386 | + data[i].p2 = pdata_mainc[i][1]; | |
387 | + data[i].p3 = pdata_mainc[i][2]; | |
388 | + data[i].p4 = pdata_mainc[i][3]; | |
389 | + } | |
390 | + | |
391 | + //ファイルポインタを閉じる | |
392 | + fclose( fp ); | |
393 | + | |
394 | + //「同ファイル名.msg」を生成 | |
395 | + strcpy(fname2, fname); | |
396 | + //PathRemoveExtension(fname2); | |
397 | + for(int i=strlen(fname2)-1; i>0; i--){ | |
398 | + if( fname2[i] == '.' ){ | |
399 | + fname2[i] = 0x00; | |
400 | + break; | |
401 | + } | |
402 | + } | |
403 | + strcat(fname2, ".msg"); | |
404 | + | |
405 | + //ファイルを読み込み | |
406 | + fp = fopen( fname2, "r" ); | |
407 | + if( fp != NULL ){ | |
408 | + //メッセージデータを取得 | |
409 | + for(int i=0; i<MAX_POINTMESSAGES; i++){ | |
410 | + if( fgets(text[i], MAX_POINTMESSAGEBYTE, fp) == NULL ){ break; } | |
411 | + | |
412 | + //'\r'があれば'\n'に置き換える | |
413 | + for(int j=0; j<MAX_POINTMESSAGEBYTE; j++){ | |
414 | + if( text[i][j] == '\r' ){ text[i][j] = '\n'; } | |
415 | + } | |
416 | + } | |
417 | + | |
418 | + //ファイルポインタを開放 | |
419 | + fclose( fp ); | |
420 | + } | |
421 | + | |
422 | + return 0; | |
423 | +} | |
424 | + | |
425 | +//! @brief ポイントデータを取得 | |
426 | +//! @param out_data 受け取るpointdata型ポインタ | |
427 | +//! @param id 認識番号 | |
428 | +//! @return 成功:0 失敗:0以外 | |
429 | +int PointDataInterface::Getdata(pointdata *out_data, int id) | |
430 | +{ | |
431 | + if( data == NULL ){ return 1; } | |
432 | + if( (id < 0)||((datas -1) < id) ){ return 2; } | |
433 | + | |
434 | + //データをポインタにコピー | |
435 | + memcpy(out_data, &(data[id]), sizeof(pointdata)); | |
436 | + | |
437 | + return 0; | |
438 | +} | |
439 | + | |
440 | +//! @brief ポイントのパラメーターを書き換え | |
441 | +//! @param id 認識番号 | |
442 | +//! @param p1 第1パラメータ | |
443 | +//! @param p2 第2パラメータ | |
444 | +//! @param p3 第3パラメータ | |
445 | +//! @param p4 第4パラメータ | |
446 | +//! @return 成功:0 失敗:0以外 | |
447 | +//! @warning AIが使用するパス(p1:3 or p1:8)以外への使用は、保証されておらず推奨しません。 | |
448 | +int PointDataInterface::SetParam(int id, signed char p1, signed char p2, signed char p3, signed char p4) | |
449 | +{ | |
450 | + if( data == NULL ){ return 1; } | |
451 | + if( (id < 0)||((datas -1) < id) ){ return 2; } | |
452 | + | |
453 | + //パラメータを上書き | |
454 | + data[id].p1 = p1; | |
455 | + data[id].p2 = p2; | |
456 | + data[id].p3 = p3; | |
457 | + data[id].p4 = p4; | |
458 | + | |
459 | + return 0; | |
460 | +} | |
461 | + | |
462 | +//! @brief メッセージ(1行)を取得 | |
463 | +//! @param str 文字列を受け取るポインタ | |
464 | +//! @param id 認識番号 | |
465 | +//! @return 成功:0 失敗:1 | |
466 | +int PointDataInterface::GetMessageText(char *str, int id) | |
467 | +{ | |
468 | + if( (id < 0)||((MAX_POINTMESSAGES -1) < id) ){ return 1; } | |
469 | + | |
470 | + //ポインタにメッセージをコピー | |
471 | + strcpy(str, text[id]); | |
472 | + return 0; | |
473 | +} | |
474 | + | |
475 | +//! @brief ポイントデータを検索 | |
476 | +//! @param id 最初に該当したデータ番号を受け取るポインタ (NULL 可) | |
477 | +//! @param pmask パラメータのマスク | |
478 | +//! @param p1 第1パラメータ | |
479 | +//! @param p2 第2パラメータ | |
480 | +//! @param p3 第3パラメータ | |
481 | +//! @param p4 第4パラメータ | |
482 | +//! @param offset 検索を開始するデータ | |
483 | +//! @return 該当ポイント数 | |
484 | +//! @note パラメータのマスクは、p1〜p4の検索対象を指定します。 | |
485 | +//! @note 1〜4ビット目までを使用し、p1:1ビット目、p2:2ビット目、p3:3ビット目、p4:4ビット目 をそれぞれ意味します。 | |
486 | +//! @note 検索の対象ビット:1 対象外のビット:0 に設定してください。 なお、7〜5ビット目は無視されます。 | |
487 | +//! @code | |
488 | +//! //16進数で記述の場合― | |
489 | +//! 0x02 // p2のみを検索対象にする | |
490 | +//! 0x05 // p1とp3を検索対象にする | |
491 | +//! 0xF1 // p1のみを検索対象にする (7〜5ビット目は無視) | |
492 | +//! @endcode | |
493 | +int PointDataInterface::SearchPointdata(int* id, unsigned char pmask, signed char p1, signed char p2, signed char p3, signed char p4, int offset) | |
494 | +{ | |
495 | + int cnt = 0; | |
496 | + | |
497 | + if( offset < 0 ){ offset = 0; } | |
498 | + if( offset >= datas ){ offset = datas; } | |
499 | + | |
500 | + //オフセット値からデータ数分処理 | |
501 | + for(int i=offset; i<datas; i++){ | |
502 | + | |
503 | + if( ((pmask&0x01) == 0)||(p1 == data[i].p1) ){ //マスクで指定されていないか、p1が一致 | |
504 | + if( ((pmask&0x02) == 0)||(p2 == data[i].p2) ){ //マスクで指定されていないか、p2が一致 | |
505 | + if( ((pmask&0x04) == 0)||(p3 == data[i].p3) ){ //マスクで指定されていないか、p3が一致 | |
506 | + if( ((pmask&0x08) == 0)||(p4 == data[i].p4) ){ //マスクで指定されていないか、p4が一致 | |
507 | + | |
508 | + if( (cnt == 0)&&(id != NULL) ){ //最初に該当し、idがNULLでない。 | |
509 | + *id = i; | |
510 | + } | |
511 | + | |
512 | + //検索該当数を+1 | |
513 | + cnt += 1; | |
514 | + | |
515 | + } | |
516 | + } | |
517 | + } | |
518 | + } | |
519 | + | |
520 | + } | |
521 | + | |
522 | + //検索該当数を返す | |
523 | + return cnt; | |
524 | +} | |
525 | + | |
526 | +//! @brief ポイントデータを検索 | |
527 | +//! @param out_data 最初に該当したデータを受け取るpointdata型ポインタ (NULL 可) | |
528 | +//! @param pmask パラメータのマスク | |
529 | +//! @param p1 第1パラメータ | |
530 | +//! @param p2 第2パラメータ | |
531 | +//! @param p3 第3パラメータ | |
532 | +//! @param p4 第4パラメータ | |
533 | +//! @param offset 検索を開始するデータ | |
534 | +//! @return 該当ポイント数 | |
535 | +//! @attention この関数の詳しい説明は、同オーバーロード関数をご覧ください。 | |
536 | +int PointDataInterface::SearchPointdata(pointdata *out_data, unsigned char pmask, signed char p1, signed char p2, signed char p3, signed char p4, int offset) | |
537 | +{ | |
538 | + int id, total; | |
539 | + | |
540 | + //同条件でポイントを検索 | |
541 | + total = SearchPointdata(&id, pmask, p1, p2, p3, p4, offset); | |
542 | + | |
543 | + //該当すればデータを取得 | |
544 | + if( total > 0 ){ | |
545 | + Getdata(out_data, id); | |
546 | + } | |
547 | + | |
548 | + //検索該当数を返す | |
549 | + return total; | |
550 | +} | |
551 | + | |
552 | +//! @brief コンストラクタ | |
553 | +MIFInterface::MIFInterface() | |
554 | +{ | |
555 | + datas = 0; | |
556 | + | |
557 | + mif = false; | |
558 | + strcpy(mission_name, ""); | |
559 | + strcpy(mission_fullname, ""); | |
560 | + strcpy(blockfile_path, ""); | |
561 | + strcpy(pointfile_path, ""); | |
562 | + skynumber = 0; | |
563 | + strcpy(picturefileA_path, "!"); | |
564 | + strcpy(picturefileB_path, "!"); | |
565 | + strcpy(addsmallobject_path, ""); | |
566 | + strcpy(briefingtext, ""); | |
567 | + collision = false; | |
568 | + screen = false; | |
569 | + strcpy(addsmallobject_modelpath, ""); | |
570 | + strcpy(addsmallobject_texturepath, ""); | |
571 | + addsmallobject_decide = 0; | |
572 | + addsmallobject_hp = 0; | |
573 | + strcpy(addsmallobject_soundpath, ""); | |
574 | + addsmallobject_jump = 0; | |
575 | +} | |
576 | + | |
577 | +//! @brief ディストラクタ | |
578 | +MIFInterface::~MIFInterface() | |
579 | +{} | |
580 | + | |
581 | +//! @brief データファイルを読みこむ | |
582 | +//! @param fname ファイル名 | |
583 | +//! @return 成功:0 失敗:1 | |
584 | +int MIFInterface::LoadFiledata(char *fname) | |
585 | +{ | |
586 | + char str[64]; | |
587 | + | |
588 | + mif = false; | |
589 | + | |
590 | + //拡張子が.mifならば | |
591 | + //if( strcmp(PathFindExtension(fname), ".mif") == 0 ){ | |
592 | + // //MIFフラグを有効に | |
593 | + // mif = true; | |
594 | + //} | |
595 | + for(int i=strlen(fname)-1; i>0; i--){ | |
596 | + if( fname[i] == '.' ){ | |
597 | + if( strcmp(&(fname[i]), ".mif") == 0 ){ | |
598 | + //MIFフラグを有効に | |
599 | + mif = true; | |
600 | + } | |
601 | + break; | |
602 | + } | |
603 | + } | |
604 | + | |
605 | + FILE *fp; | |
606 | + | |
607 | + //ファイルを開く | |
608 | + fp = fopen( fname, "r" ); | |
609 | + if( fp == NULL ){ | |
610 | + //briefing data open failed | |
611 | + return 1; | |
612 | + } | |
613 | + | |
614 | + if( mif == true ){ | |
615 | + //ミッション識別名 | |
616 | + fgets(mission_name, 24, fp); | |
617 | + DeleteLinefeed(mission_name); | |
618 | + | |
619 | + //ミッション正式名称 | |
620 | + fgets(mission_fullname, 64, fp); | |
621 | + DeleteLinefeed(mission_fullname); | |
622 | + | |
623 | + //ブロックデータファイル | |
624 | + fgets(blockfile_path, _MAX_PATH, fp); | |
625 | + DeleteLinefeed(blockfile_path); | |
626 | + | |
627 | + //ポイントデータファイル | |
628 | + fgets(pointfile_path, _MAX_PATH, fp); | |
629 | + DeleteLinefeed(pointfile_path); | |
630 | + | |
631 | + //背景空の番号 | |
632 | + fgets(str, 16, fp); | |
633 | + DeleteLinefeed(str); | |
634 | + skynumber = atoi(str); | |
635 | + | |
636 | + //あたり判定・画面設定の取得 | |
637 | + fgets(str, 16, fp); | |
638 | + DeleteLinefeed(str); | |
639 | + if( strcmp(str, "1") == 0 ){ | |
640 | + collision = true; | |
641 | + screen = false; | |
642 | + } | |
643 | + else if( strcmp(str, "2") == 0 ){ | |
644 | + collision = false; | |
645 | + screen = true; | |
646 | + } | |
647 | + else if( strcmp(str, "3") == 0 ){ | |
648 | + collision = true; | |
649 | + screen = true; | |
650 | + } | |
651 | + else{ // == "0" | |
652 | + collision = false; | |
653 | + screen = false; | |
654 | + } | |
655 | + | |
656 | + //追加小物情報ファイル取得 | |
657 | + fgets(addsmallobject_path, _MAX_PATH, fp); | |
658 | + DeleteLinefeed(addsmallobject_path); | |
659 | + | |
660 | + //画像Aを取得 | |
661 | + fgets(picturefileA_path, _MAX_PATH, fp); | |
662 | + DeleteLinefeed(picturefileA_path); | |
663 | + | |
664 | + //画像Bを取得 | |
665 | + fgets(picturefileB_path, _MAX_PATH, fp); | |
666 | + DeleteLinefeed(picturefileB_path); | |
667 | + } | |
668 | + else{ | |
669 | + //画像Aを取得 | |
670 | + fgets(str, 64, fp); | |
671 | + DeleteLinefeed(str); | |
672 | + if( strcmp(str, "!") == 0 ){ | |
673 | + strcpy(picturefileA_path, "!"); | |
674 | + } | |
675 | + else{ | |
676 | + //「data\\briefing\\ 〜 .bmp」を生成 | |
677 | + strcpy(picturefileA_path, "data\\briefing\\"); | |
678 | + strcat(picturefileA_path, str); | |
679 | + strcat(picturefileA_path, ".bmp"); | |
680 | + } | |
681 | + | |
682 | + //画像Bを取得 | |
683 | + fgets(str, 64, fp); | |
684 | + DeleteLinefeed(str); | |
685 | + if( strcmp(str, "!") == 0 ){ | |
686 | + strcpy(picturefileB_path, "!"); | |
687 | + } | |
688 | + else{ | |
689 | + //「data\\briefing\\ 〜 .bmp」を生成 | |
690 | + strcpy(picturefileB_path, "data\\briefing\\"); | |
691 | + strcat(picturefileB_path, str); | |
692 | + strcat(picturefileB_path, ".bmp"); | |
693 | + } | |
694 | + | |
695 | + //背景空の番号 | |
696 | + fgets(str, 16, fp); | |
697 | + DeleteLinefeed(str); | |
698 | + skynumber = atoi(str); | |
699 | + | |
700 | + //取得できない値の初期化 | |
701 | + strcpy(mission_name, ""); | |
702 | + strcpy(mission_fullname, ""); | |
703 | + strcpy(blockfile_path, ""); | |
704 | + strcpy(pointfile_path, ""); | |
705 | + strcpy(addsmallobject_path, ""); | |
706 | + collision = false; | |
707 | + screen = false; | |
708 | + } | |
709 | + | |
710 | + //ブリーフィングテキストを取得 | |
711 | + strcpy(briefingtext, ""); | |
712 | + for(int i=0; i<17; i++ ){ | |
713 | + if( fgets(str, 50, fp) == NULL ){ break; } | |
714 | + strcat(briefingtext, str); | |
715 | + datas += 1; | |
716 | + } | |
717 | + | |
718 | + //ファイルハンドルを開放 | |
719 | + fclose( fp ); | |
720 | + | |
721 | + | |
722 | + //追加小物情報を初期値へ | |
723 | + strcpy(addsmallobject_modelpath, ""); | |
724 | + strcpy(addsmallobject_texturepath, ""); | |
725 | + addsmallobject_decide = 0; | |
726 | + addsmallobject_hp = 0; | |
727 | + strcpy(addsmallobject_soundpath, ""); | |
728 | + addsmallobject_jump = 0; | |
729 | + | |
730 | + //何かしらの追加小物情報ファイルが指定されていれば | |
731 | + if( (strcmp(addsmallobject_path, "") != 0)&&(strcmp(addsmallobject_path, "!") != 0) ){ | |
732 | + //ファイルを開く | |
733 | + fp = fopen( addsmallobject_path, "r" ); | |
734 | + if( fp != NULL ){ | |
735 | + //モデルデータパス | |
736 | + fgets(addsmallobject_modelpath, _MAX_PATH, fp); | |
737 | + DeleteLinefeed(addsmallobject_modelpath); | |
738 | + | |
739 | + //テクスチャパス | |
740 | + fgets(addsmallobject_texturepath, _MAX_PATH, fp); | |
741 | + DeleteLinefeed(addsmallobject_texturepath); | |
742 | + | |
743 | + //当たり判定の大きさ | |
744 | + fgets(str, 16, fp); | |
745 | + DeleteLinefeed(str); | |
746 | + addsmallobject_decide = atoi(str); | |
747 | + | |
748 | + //耐久力 | |
749 | + fgets(str, 16, fp); | |
750 | + DeleteLinefeed(str); | |
751 | + addsmallobject_hp = atoi(str); | |
752 | + | |
753 | + //サウンドデータパス | |
754 | + fgets(addsmallobject_soundpath, _MAX_PATH, fp); | |
755 | + DeleteLinefeed(addsmallobject_soundpath); | |
756 | + | |
757 | + //飛び具合 | |
758 | + fgets(str, 16, fp); | |
759 | + DeleteLinefeed(str); | |
760 | + addsmallobject_jump = atoi(str); | |
761 | + | |
762 | + //ファイルハンドルを開放 | |
763 | + fclose( fp ); | |
764 | + } | |
765 | + } | |
766 | + | |
767 | + return 0; | |
768 | +} | |
769 | + | |
770 | +//! @brief 読み込んだデータファイルの形式を取得 | |
771 | +//! @return 標準形式:false MIF形式:true | |
772 | +//! @attention ファイルを正常に読み込んだ後に実行してください。 | |
773 | +bool MIFInterface::GetFiletype() | |
774 | +{ | |
775 | + return mif; | |
776 | +} | |
777 | + | |
778 | +//! @brief ミッション識別名を取得 | |
779 | +//! @return 識別名のポインタ(最大:24) | |
780 | +char* MIFInterface::GetMissionName() | |
781 | +{ | |
782 | + return mission_name; | |
783 | +} | |
784 | + | |
785 | +//! @brief ミッション正式名称を取得 | |
786 | +//! @return 正式名称のポインタ(最大:64) | |
787 | +char* MIFInterface::GetMissionFullname() | |
788 | +{ | |
789 | + return mission_fullname; | |
790 | +} | |
791 | + | |
792 | +//! @brief ブロックデータとポイントデータのパスを取得 | |
793 | +//! @param *blockfile ブロックデータを受け取るポインタ | |
794 | +//! @param *pointfile ポイントデータを受け取るポインタ | |
795 | +void MIFInterface::GetDatafilePath(char *blockfile, char *pointfile) | |
796 | +{ | |
797 | + strcpy(blockfile, blockfile_path); | |
798 | + strcpy(pointfile, pointfile_path); | |
799 | +} | |
800 | + | |
801 | +//! @brief 背景空を取得 | |
802 | +//! @return 空の番号(0〜5) | |
803 | +//! @attention 番号 0 は「背景なし」を意味します。 | |
804 | +int MIFInterface::GetSkynumber() | |
805 | +{ | |
806 | + return skynumber; | |
807 | +} | |
808 | + | |
809 | +//! @brief ブリーフィング画像ファイルのパスを取得 | |
810 | +//! @param *picturefileA 画像ファイルAのパスを受け取るポインタ | |
811 | +//! @param *picturefileB 画像ファイルBのパスを受け取るポインタ | |
812 | +//! @attention 設定されていない場合は「!」が返されます。 | |
813 | +//! @attention 画像を1枚しか使用しない場合、画像ファイルBは「!」を返します。 | |
814 | +void MIFInterface::GetPicturefilePath(char *picturefileA, char *picturefileB) | |
815 | +{ | |
816 | + strcpy(picturefileA, picturefileA_path); | |
817 | + strcpy(picturefileB, picturefileB_path); | |
818 | +} | |
819 | + | |
820 | +//! @brief ブリーフィング文章(本文)を取得 | |
821 | +//! @return 文章のポインタ(最大:816) | |
822 | +//! @attention 改行コードも含めて、最大17行分が一度に返されます。 | |
823 | +//! @attention 行数は GetTotaldatas() で取得できます。 | |
824 | +char* MIFInterface::GetBriefingText() | |
825 | +{ | |
826 | + return briefingtext; | |
827 | +} | |
828 | + | |
829 | +//! @brief 追加のあたり判定を示すフラグを取得 | |
830 | +//! @return 有効:true 無効:false | |
831 | +bool MIFInterface::GetCollisionFlag() | |
832 | +{ | |
833 | + return collision; | |
834 | +} | |
835 | + | |
836 | +//! @brief 画面を暗くを示すフラグを取得 | |
837 | +//! @return 有効:true 無効:false | |
838 | +bool MIFInterface::GetScreenFlag() | |
839 | +{ | |
840 | + return screen; | |
841 | +} | |
842 | + | |
843 | +//! @brief 追加小物のモデルデータパスを取得 | |
844 | +//! @return モデルデータパスのポインタ(最大:_MAX_PATH) | |
845 | +char* MIFInterface::GetAddSmallobjectModelPath() | |
846 | +{ | |
847 | + return addsmallobject_modelpath; | |
848 | +} | |
849 | + | |
850 | +//! @brief 追加小物のテクスチャパスを取得 | |
851 | +//! @return テクスチャパスのポインタ(最大:_MAX_PATH) | |
852 | +char* MIFInterface::GetAddSmallobjectTexturePath() | |
853 | +{ | |
854 | + return addsmallobject_texturepath; | |
855 | +} | |
856 | + | |
857 | +//! @brief 追加小物の当たり判定の大きさを取得 | |
858 | +//! @return 当たり判定の大きさ | |
859 | +int MIFInterface::GetAddSmallobjectDecide() | |
860 | +{ | |
861 | + return addsmallobject_decide; | |
862 | +} | |
863 | + | |
864 | +//! @brief 追加小物の耐久力を取得 | |
865 | +//! @return 耐久力 | |
866 | +int MIFInterface::GetAddSmallobjectHP() | |
867 | +{ | |
868 | + return addsmallobject_hp; | |
869 | +} | |
870 | + | |
871 | +//! @brief 追加小物のサウンドデータパスを取得 | |
872 | +//! @return サウンドデータパスのポインタ(最大:_MAX_PATH) | |
873 | +char* MIFInterface::GetAddSmallobjectSoundPath() | |
874 | +{ | |
875 | + return addsmallobject_soundpath; | |
876 | +} | |
877 | + | |
878 | +//! @brief 追加小物の飛び具合を取得 | |
879 | +//! @return 飛び具合 | |
880 | +int MIFInterface::GetAddSmallobjectJump() | |
881 | +{ | |
882 | + return addsmallobject_jump; | |
883 | +} | |
884 | + | |
885 | +//! @brief コンストラクタ | |
886 | +AddonList::AddonList() | |
887 | +{ | |
888 | + datas = 0; | |
889 | + | |
890 | + for(int i=0; i<MAX_ADDONLIST; i++){ | |
891 | + strcpy(filename[i], ""); | |
892 | + strcpy(mission_name[i], ""); | |
893 | + } | |
894 | +} | |
895 | + | |
896 | +//! @brief ディストラクタ | |
897 | +AddonList::~AddonList() | |
898 | +{} | |
899 | + | |
900 | +//! @brief .mifファイルを取得 | |
901 | +void AddonList::GetMIFlist(char *dir) | |
902 | +{ | |
903 | + char SearchDIR[_MAX_PATH]; | |
904 | + HANDLE hFind; | |
905 | + WIN32_FIND_DATA FindFileData; | |
906 | + | |
907 | + //.mifの検索条件を生成 | |
908 | + strcpy(SearchDIR, dir); | |
909 | + strcat(SearchDIR, "\\*.mif"); | |
910 | + | |
911 | + //検索 | |
912 | + hFind = FindFirstFile(SearchDIR, &FindFileData); | |
913 | + if( hFind != INVALID_HANDLE_VALUE ){ | |
914 | + strcpy(filename[0], FindFileData.cFileName); | |
915 | + datas += 1; | |
916 | + | |
917 | + while( FindNextFile(hFind, &FindFileData) == TRUE ){ | |
918 | + strcpy(filename[datas], FindFileData.cFileName); | |
919 | + datas += 1; | |
920 | + } | |
921 | + } | |
922 | + FindClose(hFind); | |
923 | +} | |
924 | + | |
925 | +//! @brief ミッション名を取得 | |
926 | +void AddonList::GetMissionName(char *dir) | |
927 | +{ | |
928 | + char str[_MAX_PATH]; | |
929 | + MIFInterface mifdata; | |
930 | + | |
931 | + for(int i=0; i<datas; i++){ | |
932 | + //ファイル名を生成 | |
933 | + strcpy(str, dir); | |
934 | + strcat(str, "\\"); | |
935 | + strcat(str, filename[i]); | |
936 | + | |
937 | + //MIFInterfaceで読み込む | |
938 | + mifdata.LoadFiledata(str); | |
939 | + | |
940 | + //ミッション名を取得 | |
941 | + strcpy(mission_name[i], mifdata.GetMissionName()); | |
942 | + } | |
943 | +} | |
944 | + | |
945 | +//! @brief ミッション名をソートする | |
946 | +void AddonList::Sort() | |
947 | +{ | |
948 | + char mission_name_c[MAX_ADDONLIST][24]; | |
949 | + char temp[_MAX_PATH]; | |
950 | + int cmp; | |
951 | + | |
952 | + //ミッション名を一度小文字に変換する | |
953 | + for(int i=0; i<datas; i++){ | |
954 | + for(int j=0; j<(int)strlen(mission_name[i]); j++){ | |
955 | + mission_name_c[i][j] = (char)tolower(mission_name[i][j]); | |
956 | + } | |
957 | + mission_name_c[i][strlen(mission_name[i])] = 0x00; | |
958 | + } | |
959 | + | |
960 | + //低速なバブルソート (^^; | |
961 | + for(int i=0; i<datas-1; i++){ | |
962 | + for(int j=i+1; j<datas; j++){ | |
963 | + cmp = strcmp(mission_name_c[i], mission_name_c[j]); | |
964 | + if(cmp > 0){ | |
965 | + strcpy(temp, mission_name_c[i]); | |
966 | + strcpy(mission_name_c[i], mission_name_c[j]); | |
967 | + strcpy(mission_name_c[j], temp); | |
968 | + | |
969 | + strcpy(temp, mission_name[i]); | |
970 | + strcpy(mission_name[i], mission_name[j]); | |
971 | + strcpy(mission_name[j], temp); | |
972 | + | |
973 | + strcpy(temp, filename[i]); | |
974 | + strcpy(filename[i], filename[j]); | |
975 | + strcpy(filename[j], temp); | |
976 | + } | |
977 | + } | |
978 | + } | |
979 | + | |
980 | +} | |
981 | + | |
982 | +//! @brief ADDONリストを取得する | |
983 | +//! @param dir ADDON(.mif)が入ったディレクトリ (標準:"addon\\") | |
984 | +//! @return addonの総数 | |
985 | +int AddonList::LoadFiledata(char *dir) | |
986 | +{ | |
987 | + datas = 0; | |
988 | + | |
989 | + //.mifファイルを取得 | |
990 | + GetMIFlist(dir); | |
991 | + | |
992 | + //ミッション名を取得 | |
993 | + GetMissionName(dir); | |
994 | + | |
995 | + //ミッション名をソートする | |
996 | + Sort(); | |
997 | + | |
998 | + return datas; | |
999 | +} | |
1000 | + | |
1001 | +//! @brief ミッション名を取得 | |
1002 | +//! @param id 認識番号 | |
1003 | +//! @return ミッション名 | |
1004 | +char* AddonList::GetMissionName(int id) | |
1005 | +{ | |
1006 | + return mission_name[id]; | |
1007 | +} | |
1008 | + | |
1009 | +//! @brief ファイル名を取得 | |
1010 | +//! @param id 認識番号 | |
1011 | +//! @return ファイル名 | |
1012 | +char* AddonList::GetFileName(int id) | |
1013 | +{ | |
1014 | + return filename[id]; | |
1015 | +} | |
1016 | + | |
1017 | + | |
1018 | +//! @brief fgets()用 改行コードを取り除く | |
1019 | +//! @param str 文字列 | |
1020 | +//! @return 成功:0 失敗:1 | |
1021 | +int DeleteLinefeed(char str[]) | |
1022 | +{ | |
1023 | + char *pstr; | |
1024 | + | |
1025 | + pstr = strchr(str, '\n'); | |
1026 | + if( pstr ){ | |
1027 | + *pstr = '\0'; | |
1028 | + return 0; | |
1029 | + } | |
1030 | + return 1; | |
1031 | +} |
@@ -0,0 +1,732 @@ | ||
1 | +//! @file resource.cpp | |
2 | +//! @brief ResourceManagerクラスの定義 | |
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 "resource.h" | |
33 | + | |
34 | +//! @brief コンストラクタ | |
35 | +ResourceManager::ResourceManager() | |
36 | +{ | |
37 | + ParamInfo = NULL; | |
38 | + d3dg = NULL; | |
39 | + SoundCtrl = NULL; | |
40 | + | |
41 | + for(int i=0; i<TOTAL_UPMODE; i++){ | |
42 | + human_upmodel[i] = -1; | |
43 | + } | |
44 | + for(int i=0; i<TOTAL_ARMMODE; i++){ | |
45 | + human_armmodel[i] = -1; | |
46 | + } | |
47 | + human_legmodel = -1; | |
48 | + for(int i=0; i<TOTAL_WALKMODE; i++){ | |
49 | + human_walkmodel[i] = -1; | |
50 | + } | |
51 | + for(int i=0; i<TOTAL_RUNMODE; i++){ | |
52 | + human_runmodel[i] = -1; | |
53 | + } | |
54 | + for(int i=0; i<MAX_LOADHUMANTEXTURE; i++){ | |
55 | + human_texture_Param[i] = -1; | |
56 | + human_texture_d3dg[i] = -1; | |
57 | + } | |
58 | + for(int i=0; i<TOTAL_PARAMETERINFO_WEAPON; i++){ | |
59 | + weapon_model[i] = -1; | |
60 | + weapon_texture[i] = -1; | |
61 | + weapon_sound[i] = -1; | |
62 | + } | |
63 | + for(int i=0; i<TOTAL_PARAMETERINFO_SMALLOBJECT+1; i++){ | |
64 | + smallobject_model[i] = -1; | |
65 | + smallobject_texture[i] = -1; | |
66 | + smallobject_sound[i] = -1; | |
67 | + } | |
68 | + | |
69 | + scopetexture = -1; | |
70 | + skymodel = -1; | |
71 | + skytexture = -1; | |
72 | + bulletmodel = -1; | |
73 | + bullettexture = -1; | |
74 | + bullet_hitsoundA = -1; | |
75 | + bullet_hitsoundB = -1; | |
76 | + bullet_humanhitsound = -1; | |
77 | + bullet_passingsound = -1; | |
78 | + grenade_bang = -1; | |
79 | + grenade_cco = -1; | |
80 | + effecttexture_blood = -1; | |
81 | + effecttexture_mflash = -1; | |
82 | + effecttexture_smoke = -1; | |
83 | + effecttexture_yakkyou = -1; | |
84 | +} | |
85 | + | |
86 | +//! @brief ディストラクタ | |
87 | +ResourceManager::~ResourceManager() | |
88 | +{ | |
89 | + CleanupHumanModel(); | |
90 | + CleanupHumanTexture(); | |
91 | + CleanupWeaponModelTexture(); | |
92 | + CleanupSmallObjectModelTexture(); | |
93 | + | |
94 | + CleanupScopeTexture(); | |
95 | + CleanupSkyModelTexture(); | |
96 | + CleanupBulletModelTexture(); | |
97 | + CleanupEffectTexture(); | |
98 | +} | |
99 | + | |
100 | +//! @brief 参照するParameterInfoクラスを設定 | |
101 | +//! @param *_ParamInfo ParameterInfoクラスのポインタ | |
102 | +//! @attention この関数で設定を行わないと、クラス自体が正しく機能しません。 | |
103 | +void ResourceManager::SetParameterInfo(ParameterInfo *_ParamInfo) | |
104 | +{ | |
105 | + ParamInfo = _ParamInfo; | |
106 | +} | |
107 | + | |
108 | +//! @brief 参照するD3DGraphicsクラスを設定 | |
109 | +//! @param *_d3dg D3DGraphicsクラスのポインタ | |
110 | +//! @attention この関数で設定を行わないと、クラス自体が正しく機能しません。 | |
111 | +void ResourceManager::SetD3DGraphics(D3DGraphics *_d3dg) | |
112 | +{ | |
113 | + d3dg = _d3dg; | |
114 | +} | |
115 | + | |
116 | +//! @brief 参照するSoundControlクラスを設定 | |
117 | +//! @param *_SoundCtrl SoundControlクラスのポインタ | |
118 | +//! @attention この関数で設定を行わないと、クラス自体が正しく機能しません。 | |
119 | +void ResourceManager::SetSoundControl(SoundControl *_SoundCtrl) | |
120 | +{ | |
121 | + SoundCtrl = _SoundCtrl; | |
122 | +} | |
123 | + | |
124 | +//! @brief 人のモデルを読み込み | |
125 | +//! @return 成功:0 失敗:1 | |
126 | +int ResourceManager::LoadHumanModel() | |
127 | +{ | |
128 | + if( d3dg == NULL ){ return 1; } | |
129 | + | |
130 | + human_upmodel[0] = d3dg->LoadModel("data\\model\\up0.x"); | |
131 | + human_upmodel[1] = d3dg->LoadModel("data\\model\\up1.x"); | |
132 | + human_upmodel[2] = d3dg->LoadModel("data\\model\\up2.x"); | |
133 | + human_upmodel[3] = d3dg->LoadModel("data\\model\\up3.x"); | |
134 | + human_upmodel[4] = d3dg->LoadModel("data\\model\\up4.x"); | |
135 | + human_upmodel[5] = d3dg->LoadModel("data\\model\\up5.x"); | |
136 | + human_armmodel[0] = d3dg->LoadModel("data\\model\\arm00.x"); | |
137 | + human_armmodel[1] = d3dg->LoadModel("data\\model\\arm01.x"); | |
138 | + human_armmodel[2] = d3dg->LoadModel("data\\model\\arm02.x"); | |
139 | + human_legmodel = d3dg->LoadModel("data\\model\\leg.x"); | |
140 | + human_walkmodel[0] = d3dg->LoadModel("data\\model\\walk01.x"); | |
141 | + human_walkmodel[2] = d3dg->LoadModel("data\\model\\walk02.x"); | |
142 | + human_walkmodel[4] = d3dg->LoadModel("data\\model\\walk03.x"); | |
143 | + human_walkmodel[6] = d3dg->LoadModel("data\\model\\walk04.x"); | |
144 | + human_runmodel[0] = d3dg->LoadModel("data\\model\\run01.x"); | |
145 | + human_runmodel[2] = d3dg->LoadModel("data\\model\\run02.x"); | |
146 | + human_runmodel[4] = d3dg->LoadModel("data\\model\\run03.x"); | |
147 | + human_runmodel[6] = d3dg->LoadModel("data\\model\\run04.x"); | |
148 | + human_runmodel[8] = d3dg->LoadModel("data\\model\\run05.x"); | |
149 | + human_runmodel[10] = d3dg->LoadModel("data\\model\\run06.x"); | |
150 | + | |
151 | + if( 1 ){ | |
152 | + //モーフィング処理を実行する | |
153 | + human_walkmodel[1] = d3dg->MorphingModel(human_walkmodel[0], human_walkmodel[2]); | |
154 | + human_walkmodel[3] = d3dg->MorphingModel(human_walkmodel[2], human_walkmodel[4]); | |
155 | + human_walkmodel[5] = d3dg->MorphingModel(human_walkmodel[4], human_walkmodel[6]); | |
156 | + human_walkmodel[7] = d3dg->MorphingModel(human_walkmodel[6], human_walkmodel[0]); | |
157 | + human_runmodel[1] = d3dg->MorphingModel(human_runmodel[0], human_runmodel[2]); | |
158 | + human_runmodel[3] = d3dg->MorphingModel(human_runmodel[2], human_runmodel[4]); | |
159 | + human_runmodel[5] = d3dg->MorphingModel(human_runmodel[4], human_runmodel[6]); | |
160 | + human_runmodel[7] = d3dg->MorphingModel(human_runmodel[6], human_runmodel[8]); | |
161 | + human_runmodel[9] = d3dg->MorphingModel(human_runmodel[8], human_runmodel[10]); | |
162 | + human_runmodel[11] = d3dg->MorphingModel(human_runmodel[10], human_runmodel[0]); | |
163 | + } | |
164 | + else{ | |
165 | + //モーフィング処理を実行しない | |
166 | + human_walkmodel[1] = human_walkmodel[0]; | |
167 | + human_walkmodel[3] = human_walkmodel[2]; | |
168 | + human_walkmodel[5] = human_walkmodel[4]; | |
169 | + human_walkmodel[7] = human_walkmodel[6]; | |
170 | + human_runmodel[1] = human_runmodel[0]; | |
171 | + human_runmodel[3] = human_runmodel[2]; | |
172 | + human_runmodel[5] = human_runmodel[4]; | |
173 | + human_runmodel[7] = human_runmodel[6]; | |
174 | + human_runmodel[9] = human_runmodel[8]; | |
175 | + human_runmodel[11] = human_runmodel[10]; | |
176 | + } | |
177 | + | |
178 | + return 0; | |
179 | +} | |
180 | + | |
181 | +//! @brief 人のモデル認識番号を取得 | |
182 | +//! @param out_upmodel[] 上半身のモデル (配列数:TOTAL_UPMODE) | |
183 | +//! @param out_armmodel[] 腕のモデル (配列数:TOTAL_ARMMODE) | |
184 | +//! @param *legmodel 足(静止状態)のモデルのポインタ | |
185 | +//! @param out_walkmodel[] 足(歩き)のモデル (配列数:TOTAL_WALKMODE) | |
186 | +//! @param out_runmodel[] 足(走り)のモデル (配列数:TOTAL_RUNMODE) | |
187 | +void ResourceManager::GetHumanModel(int out_upmodel[], int out_armmodel[], int *legmodel, int out_walkmodel[], int out_runmodel[]) | |
188 | +{ | |
189 | + for(int i=0; i<TOTAL_UPMODE; i++){ | |
190 | + out_upmodel[i] = human_upmodel[i]; | |
191 | + } | |
192 | + for(int i=0; i<TOTAL_ARMMODE; i++){ | |
193 | + out_armmodel[i] = human_armmodel[i]; | |
194 | + } | |
195 | + *legmodel = human_legmodel; | |
196 | + for(int i=0; i<TOTAL_WALKMODE; i++){ | |
197 | + out_walkmodel[i] = human_walkmodel[i]; | |
198 | + } | |
199 | + for(int i=0; i<TOTAL_RUNMODE; i++){ | |
200 | + out_runmodel[i] = human_runmodel[i]; | |
201 | + } | |
202 | +} | |
203 | + | |
204 | +//! @brief 人のモデルを解放 | |
205 | +void ResourceManager::CleanupHumanModel() | |
206 | +{ | |
207 | + if( d3dg == NULL ){ return; } | |
208 | + | |
209 | + for(int i=0; i<TOTAL_UPMODE; i++){ | |
210 | + d3dg->CleanupModel(human_upmodel[i]); | |
211 | + human_upmodel[i] = -1; | |
212 | + } | |
213 | + for(int i=0; i<TOTAL_ARMMODE; i++){ | |
214 | + d3dg->CleanupModel(human_armmodel[i]); | |
215 | + human_armmod |
Part of diff was cut off due to size limit. Use your local client to view the full diff.