• R/O
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#objective-cqt誰得cocoawindowspythonphprubygameguibathyscaphec翻訳omegat計画中(planning stage)frameworktwittertestdombtronvb.netdirectxarduinopreviewerゲームエンジン

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


Commit MetaInfo

Revision45 (tree)
Time2015-02-20 01:15:15
Authorxops-mikan

Log Message

Version:1.010

Change Summary

Incremental Difference

--- tags/v1.010-20150220/main.h (nonexistent)
+++ tags/v1.010-20150220/main.h (revision 45)
@@ -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
--- tags/v1.010-20150220/ai.cpp (nonexistent)
+++ tags/v1.010-20150220/ai.cpp (revision 45)
@@ -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(&paramid, 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(&paramid, 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, &paramdata) == 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, &paramdata) == 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(&paramid, &target_pointid, NULL, NULL);
1757+ Param->GetHuman(paramid, &paramdata);
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
--- tags/v1.010-20150220/objectmanager.cpp (nonexistent)
+++ tags/v1.010-20150220/objectmanager.cpp (revision 45)
@@ -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(&paramid, 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
--- tags/v1.010-20150220/d3dgraphics.cpp (nonexistent)
+++ tags/v1.010-20150220/d3dgraphics.cpp (revision 45)
@@ -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
--- tags/v1.010-20150220/d3dgraphics.h (nonexistent)
+++ tags/v1.010-20150220/d3dgraphics.h (revision 45)
@@ -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
--- tags/v1.010-20150220/scene.cpp (nonexistent)
+++ tags/v1.010-20150220/scene.cpp (revision 45)
@@ -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
--- tags/v1.010-20150220/gamemain.cpp (nonexistent)
+++ tags/v1.010-20150220/gamemain.cpp (revision 45)
</
@@ -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(&param, &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+