root/lang/d/koke/trunk/gamecore.d @ 9337

Revision 9337, 17.6 kB (checked in by omega, 5 years ago)
Line 
1/********************************************************************************/
2/*      gamecore.d                                                                                                                                      */
3/*------------------------------------------------------------------------------*/
4/*      製作              ( ゜ワ゜)ノ / 松久貫太                                                                  */
5/*      製作開始    2008/01/03                                                                                                              */
6/*      MAIL            omega@personal.email.ne.jp                                                                              */
7/*      URL             http://nagoya.cool.ne.jp/o_mega                                                                         */
8/*                                                                                                                                                              */
9/*      このソースは「やわらかライセンス」の元で配布されています。                                   */
10/*-更新履歴---------------------------------------------------------------------*/
11/*      2008/01/04                                                                                                                                      */
12/*-その他-----------------------------------------------------------------------*/
13/*      なし                                                                                                                                              */
14/********************************************************************************/
15
16private import state;
17private import hell2;
18private import boot;
19private import actor;
20private import vector;
21private import keypad;
22private import clickable;
23
24import config;
25
26private import character;
27private import map;
28
29private import std.math;
30
31/********************************************************************************/
32
33ConfigParser configparser = null;
34const static string CONFIG_PATH = "config.ini";
35
36/* GameMain *********************************************************************/
37/*      ゲーム本体の状態                                                                                                                        */
38/********************************************************************************/
39
40class GameMain : GameState
41{
42public:
43        int timer;                                              // 汎用タイマー
44        Map map;                                                // マップ
45        CharacterPool charpool;                 // キャラクタプール
46       
47        ClickablePool menu;                             // ツールメニュー(右下の大きいやつ
48        ClickablePool chart_switch;             // チャートのON/OFFスイッチ(右上
49        ClickablePool economy_switch;   // エコノミーのON/OFFスイッチ(右上
50        ClickablePool speed_switch;             // 速度スイッチ(右上
51       
52        int cursor_x;                                   // マウス直下の座標x(マップチップ座標系)
53        int cursor_y;                                   // マウス直下の座標y(マップチップ座標系)
54        int mouse_x;                                    // マウス座標x(スクリーン座標系)
55        int mouse_y;                                    // マウス座標y(スクリーン座標系)
56       
57        Keypad keypad;                                  // キーボード/ゲームパッド取得用
58       
59        double view_point_x;                    // 視点x(スクリーン座標系)
60        double view_point_y;                    // 視点y(スクリーン座標系)
61       
62        Character target;                               // 注目しているキャラクタ(キャラクタ情報ウインドウ用)
63       
64        PlayChart chart;                                // チャート
65       
66        int message_timer;                              // システムメッセージ表示用タイマ
67        string message;                                 // システムメッセージ
68       
69        int mray_timer;                                 // 運営レーザー用タイマ
70       
71        int shake_power;                                // 画面ゆれ強度
72       
73        static const int CONFIG_RELOAD_CHECK_INTERVAL = 40 * 5;                 // コンフィグ再読み込み確認
74        static const int CONFIG_RELOAD_SHOW_INTERVAL = 40 * 3;                  // 「コンフィグ読み込んだ」表示時間
75       
76        // 運営レーザー用タイマー数値
77        static const int MRAY_TIMER_FIRST_WAIT = 40;                            // 待ち
78        static const int MRAY_TIMER_SECOND_TARGET = 80;                         // ターゲット
79       
80        this()
81        {
82                // 各種初期化
83                timer = 0;
84                configparser = new ConfigParser();
85                configparser.load(CONFIG_PATH);
86                message_timer = 0;
87                message = "";
88               
89                mray_timer = 0;
90                shake_power = 0;
91               
92                int mapw = configparser.getint("MAP_WIDTH");
93                int maph = configparser.getint("MAP_HEIGHT");
94                map = new Map(this , mapw , maph);
95                charpool = new CharacterPool(this , 512 , mapw , maph);
96               
97                view_point_x = getScreenWidth() / 2 - map.toViewX(mapw / 2 , maph / 2);
98                view_point_y = getScreenHeight() / 2 - map.toViewY(mapw / 2 , maph / 2);
99               
100                keypad = new Keypad();
101               
102                chart = new PlayChart(this);
103               
104                target = null;
105               
106                // 画面下・ツールメニュー
107                menu = new ClickablePool(false /* 非選択状態は選べない */);
108                menu.add("del" , new Vec3(getScreenWidth() - ImageButton.BUTTON_WIDTH*4
109                        , getScreenHeight() - ImageButton.BUTTON_HEIGHT ,0)
110                        , ImageButton.TYPE.DEL);
111                menu.add("herbicide" , new Vec3(getScreenWidth() - ImageButton.BUTTON_WIDTH*3
112                        , getScreenHeight() - ImageButton.BUTTON_HEIGHT ,0)
113                        , ImageButton.TYPE.HERBICIDE);
114                menu.add("manage_ray" , new Vec3(getScreenWidth() - ImageButton.BUTTON_WIDTH*2
115                        , getScreenHeight() - ImageButton.BUTTON_HEIGHT ,0)
116                        , ImageButton.TYPE.MANAGE_RAY);
117                menu.add("call_nico" , new Vec3(getScreenWidth() - ImageButton.BUTTON_WIDTH*1
118                        , getScreenHeight() - ImageButton.BUTTON_HEIGHT ,0)
119                        , ImageButton.TYPE.CALL_NICO);
120                menu.add("up" , new Vec3(getScreenWidth() - ImageButton.BUTTON_WIDTH*2
121                        , getScreenHeight() - ImageButton.BUTTON_HEIGHT * 2 ,0)
122                        , ImageButton.TYPE.UP);
123                menu.add("fence" , new Vec3(getScreenWidth() - ImageButton.BUTTON_WIDTH*1
124                        , getScreenHeight() - ImageButton.BUTTON_HEIGHT * 2 ,0)
125                        , ImageButton.TYPE.FENCE);
126               
127                // 画面上・チャートスイッチ
128                chart_switch = new ClickablePool();
129                chart_switch.add("on" , new Vec3(getScreenWidth() - 64*2 , 0 ,0)
130                        , ImageButton.TYPE.CHART);
131               
132                // 画面上・エコノミースイッチ
133                economy_switch = new ClickablePool();
134                economy_switch.add("on" , new Vec3(getScreenWidth() - 64 , 0 ,0)
135                        , ImageButton.TYPE.ECONOMY);
136               
137                // 画面上・速度調整スイッチ
138                speed_switch = new ClickablePool(false /* 非選択状態は選べない */);
139                speed_switch.add("play" , new Vec3(getScreenWidth() - 32*3 , 16 ,0)
140                        , ImageButton.TYPE.PLAY);
141                speed_switch.add("stop" , new Vec3(getScreenWidth() - 32*4 , 16 ,0)
142                        , ImageButton.TYPE.STOP);
143                speed_switch.add("ksk" , new Vec3(getScreenWidth() - 32*2 , 16 ,0)
144                        , ImageButton.TYPE.KSK);
145                speed_switch.add("danger" , new Vec3(getScreenWidth() - 32*1 , 16 ,0)
146                        , ImageButton.TYPE.DANGER);
147        }
148       
149        void move()
150        {
151                // マップ及びキャラクタ系移動処理
152                int loop = 0;
153                if(speed_switch.getSelected() == "stop") loop = 0;
154                if(speed_switch.getSelected() == "play") loop = 1;
155                if(speed_switch.getSelected() == "ksk") loop = 5;
156                if(speed_switch.getSelected() == "danger") loop = 25;
157               
158                if(loop > 0){
159                        for(int t=0;t<loop;t++){
160                                timer++;
161                                if(timer % (40 * 5) == 0) chart.addChart(charpool , map);
162                                map.update();
163                                charpool.move();
164                        }
165                }else{
166                        charpool.updateBacket();
167                }
168               
169               
170                // マウス座標取得
171                int o_cursor_x = cursor_x , o_cursor_y = cursor_y;
172                mouse_x = Hell_getMouseX();
173                mouse_y = Hell_getMouseY();
174                cursor_x = map.toMapX(mouse_x,mouse_y);
175                cursor_y = map.toMapY(mouse_x,mouse_y);
176               
177                // メニューとか処理
178                menu.getMouseClick();
179                chart_switch.getMouseClick();
180                economy_switch.getMouseClick();
181                speed_switch.getMouseClick();
182               
183                string menucmd = menu.getSelected();
184               
185                if((Hell_isPressMouse() & 0x01) && onMouseMap()){
186                        // マップをいじる操作とかいろいろ(左クリック系
187                        switch(menucmd){
188                        case "del":
189                                // 削除 コマンド
190                                map.set(cursor_x , cursor_y , MapChip.TYPE.NONE);
191                                break;
192                               
193                        case "herbicide":
194                                // 除草剤 コマンド
195                                for(int x=-4;x<5;x++){
196                                        for(int y=-4;y<5;y++){
197                                                map.setGrass(cursor_x + x, cursor_y + y , 0);
198                                        }
199                                }
200                                break;
201                       
202                        case "manage_ray":
203                                // 運営レーザー コマンド
204                                mray_timer++;
205                                if(mray_timer > MRAY_TIMER_SECOND_TARGET && mray_timer % 3 == 0){
206                                        shake_power = 16;
207                                        Character c = charpool.set( new Vec3(cursor_x , cursor_y , 0) , Character.TYPE.EXPLODE); /* 一次的な対応 */
208                                        if(c){
209                                                c.destroyMap(cursor_x , cursor_y , Hell_randInt(0,5) , true);
210                                                c.setMotion(Character.MOTION.VANISH);
211                                        }
212                                }
213                                break;
214                               
215                        case "call_nico":
216                                if(!(Hell_isPushMouse() & 0x01)) break;
217                                // ニコ厨を呼ぶ コマンド
218                                if(map.inRange(cursor_x,cursor_y)){
219                                        Character c = charpool.set( new Vec3( cursor_x,cursor_y , 0)
220                                                , Character.TYPE.NICOCHU);
221                                        if(c) c.selectNewDirection();
222                                }else{
223                                        charpool.entryFromMapBorder(Character.TYPE.NICOCHU);
224                                }
225                                break;
226                       
227                        case "up":
228                                // うp コマンド
229                                map.set(cursor_x , cursor_y , MapChip.TYPE.MOVIE);
230                                break;
231                       
232                        case "fence":
233                                // 仕切り コマンド
234                                map.set(cursor_x , cursor_y , MapChip.TYPE.FENCE);
235                                break;
236                               
237                        default:
238                                Hell_write("Unknown menu command");
239                                break;
240                        }
241                }else{
242                        mray_timer = 0;
243                        if(shake_power > 0)shake_power--;
244                }
245                // 右クリック
246                if(Hell_isPushMouse() & 0x04){
247                        // 移動
248                        view_point_x = -(Hell_getMouseX() - getScreenWidth() / 2) + map.draw_ofs_x;
249                        view_point_y = -(Hell_getMouseY() - getScreenHeight() / 2) + map.draw_ofs_y;
250                }
251               
252                // ゲームパッドorキーボードでソワカちゃん出現&消える
253                if(keypad.isPushCancel()){
254                        if(charpool.count(Character.TYPE.VC_MK) < 1){
255                                if(map.inRange(cursor_x,cursor_y)){
256                                        charpool.set( new Vec3( cursor_x,cursor_y , 0)
257                                                        , Character.TYPE.VC_MK);
258                                }
259                        }else{
260                                charpool.removeCharacter(Character.TYPE.VC_MK);
261                        }
262                }
263               
264                // 視点移動
265                map.draw_ofs_x = map.draw_ofs_x * 0.9 + view_point_x * 0.1;
266                map.draw_ofs_y = map.draw_ofs_y * 0.9 + view_point_y * 0.1;
267               
268               
269                // カーソルが動いていたら、詳細表示するキャラクタ座標を更新する
270                if(cursor_x != o_cursor_x || cursor_y != o_cursor_y){
271                        Character c[] = charpool.getCharacterAtMap(cursor_x , cursor_y);
272                        if(c && c[0]){
273                                target = c[0];
274                        }
275                }
276               
277                // configが古い場合はロードしなおす
278                static int config_reload = 0;
279                config_reload++;
280                if(config_reload > CONFIG_RELOAD_CHECK_INTERVAL  && !configparser.isLatest()){
281                        configparser.update();
282                        config_reload = 0;
283                        message_timer = CONFIG_RELOAD_SHOW_INTERVAL;
284                        message = "CONFIG RELOAD";
285                }
286                if(message_timer > 0) message_timer--;
287        }
288       
289        void draw()
290        {
291                // エコノミー時は3フレに1回しか描かない
292                static int economy_timer = 0;
293                if(economy_switch.getSelected() != "" && (economy_timer++) % 3 != 0) return;
294               
295                // 作画開始
296                Hell_begin();
297                resetPerspective();
298                Hell_setAlpha(HELL_ALPHA_NORMAL);
299               
300                // 画面ゆれ
301                double shake_x = 0 , shake_y = 0;
302                if(shake_power > 0){
303                        shake_x = Hell_randInt(-shake_power , shake_power);
304                        shake_y = Hell_randInt(-shake_power , shake_power)/2;
305                }
306                map.draw_ofs_x += shake_x;
307                map.draw_ofs_y += shake_y;
308               
309                map.draw();
310               
311                // カーソル
312                if(onMouseMap()){
313                        MapChip.drawCursor(map.toViewX(cursor_x,cursor_y)
314                                , map.toViewY(cursor_x,cursor_y)
315                                , (timer / 5) % 4);
316                               
317                        // マップ情報ウインドウ   
318                        Hell_drawRect(mouse_x + 8 , mouse_y - 40 , 8 * 12 , 8 * 7 , 0,0, 255,255,255,192);
319                        Hell_drawFont("X:" ~ std.string.toString(cursor_x) , mouse_x + 16 , mouse_y - 32);
320                        Hell_drawFont("Y:" ~ std.string.toString(cursor_y) , mouse_x + 16 , mouse_y - 24);
321                       
322                        if(map.inRange(cursor_x,cursor_y)){
323                                MapChip m = map.toMap(cursor_x,cursor_y);
324                                Hell_drawFont("G:" ~ std.string.toString(cast(int)m.grass) , mouse_x + 16 , mouse_y - 16);
325                                Hell_drawFont("GL:" ~ std.string.toString(cast(int)m.getGrassLevel()) , mouse_x + 16 , mouse_y - 8);
326                                Hell_drawFont("TYPE:" ~ MapChip.name[m.type] , mouse_x + 16 , mouse_y - 0);
327                        }
328                       
329                        // キャラクタ情報ウインドウ
330                        if(target && target.exist) target.drawStatus();
331                }
332               
333                // 運営レーザー
334                if(mray_timer > 0 && map.inRange(cursor_x,cursor_y)){
335                        static const int CHIP_CENTER_OFFSET_X = 16;
336                        static const int CHIP_CENTER_OFFSET_Y = 24;
337                       
338                        double mx = map.toViewX(cursor_x,cursor_y);
339                        double my = map.toViewY(cursor_x,cursor_y);
340                        if(mray_timer < MRAY_TIMER_FIRST_WAIT){
341                                int alpha = 255 * mray_timer / MRAY_TIMER_FIRST_WAIT;
342                                Hell_drawRect(cast(int)mx - 2 + CHIP_CENTER_OFFSET_X , 0
343                                                        , 5, cast(int)my + CHIP_CENTER_OFFSET_Y , 0
344                                                        , 0 , 255,160,32,alpha / 4);
345                                Hell_drawRect(cast(int)mx + CHIP_CENTER_OFFSET_X , 0
346                                                        , 1, cast(int)my + CHIP_CENTER_OFFSET_Y , 0
347                                                        , 0 , 255,160,32,alpha);
348                        }else if(mray_timer < MRAY_TIMER_SECOND_TARGET){
349                                Hell_drawRect(cast(int)mx - 2 + CHIP_CENTER_OFFSET_X , 0
350                                                        , 5, cast(int)my + CHIP_CENTER_OFFSET_Y , 0
351                                                        , 0 , 255,160,32,64);
352                                Hell_drawRect(cast(int)mx + CHIP_CENTER_OFFSET_X , 0
353                                                        , 1, cast(int)my + CHIP_CENTER_OFFSET_Y , 0
354                                                        , 0 , 255,160,32);
355                                                       
356                                for(double rr=1;rr<3;rr++){
357                                        for(double t=0;t<PI*2;t+=PI/8){
358                                                double tr = cast(double)(MRAY_TIMER_SECOND_TARGET - mray_timer) / (MRAY_TIMER_SECOND_TARGET - MRAY_TIMER_FIRST_WAIT);
359                                                double vx1 = 8.0 * rr*rr * std.math.sin(t+PI/8) * tr + cursor_x;
360                                                double vy1 = 8.0 * rr*rr * std.math.cos(t+PI/8) * tr + cursor_y;
361                                                double vx2 = 8.0 * rr*rr * std.math.sin(t) * tr + cursor_x;
362                                                double vy2 = 8.0 * rr*rr * std.math.cos(t) * tr + cursor_y;
363                                               
364                                                Hell_drawLine(  map.toViewX(vx1,vy1) + CHIP_CENTER_OFFSET_X , map.toViewY(vx1,vy1) + CHIP_CENTER_OFFSET_Y
365                                                                        ,       map.toViewX(vx2,vy2) + CHIP_CENTER_OFFSET_X , map.toViewY(vx2,vy2) + CHIP_CENTER_OFFSET_Y
366                                                                        , 8 ,255,196,32,92);
367                                                Hell_drawLine(  map.toViewX(vx1,vy1) + CHIP_CENTER_OFFSET_X , map.toViewY(vx1,vy1) + CHIP_CENTER_OFFSET_Y
368                                                                        ,       map.toViewX(vx2,vy2) + CHIP_CENTER_OFFSET_X , map.toViewY(vx2,vy2) + CHIP_CENTER_OFFSET_Y
369                                                                        , 1 ,255,196,32,196);
370                                        }
371                                }
372                        }else{
373                                for(int t=0;t<32;t++){
374                                        int w = Hell_randInt(1,16);
375                                        if(t > 24){
376                                                Hell_drawRect(cast(int)mx + Hell_randInt(-8,8) - w/2 + CHIP_CENTER_OFFSET_X , 0
377                                                                        , w , cast(int)my + CHIP_CENTER_OFFSET_Y + Hell_randInt(-8,8)
378                                                                        , 0 , 0,
379                                                                        255,255,255,128);
380                                        }else if(t > 8){
381                                                Hell_drawRect(cast(int)mx + Hell_randInt(-16,16) - w/2 + CHIP_CENTER_OFFSET_X , 0
382                                                                        , w , cast(int)my + CHIP_CENTER_OFFSET_Y + Hell_randInt(-8,8)
383                                                                        , 0 , 0,
384                                                                        255,255,32,128);
385                                        }else{
386                                                Hell_drawRect(cast(int)mx + Hell_randInt(-32,32) - w/2 + CHIP_CENTER_OFFSET_X , 0
387                                                                        , w , cast(int)my + CHIP_CENTER_OFFSET_Y + Hell_randInt(-8,8)
388                                                                        , 0 , 0,
389                                                                        255,160,32,128);
390                                        }
391                                }
392                        }
393                        Hell_drawFont("T:" ~ std.string.toString(mray_timer) , mouse_x - 32 , mouse_y - 0);
394                }
395               
396                // 種類別キャラクタ数表示(左上)
397                for(int t=0;t<Character.TYPE.MAX;t++){
398                        if(t == Character.TYPE.NONE) continue;
399                       
400                        Hell_drawFont(Character.type_name[t] ~ ":" ~ std.string.toString(charpool.count(cast(Character.TYPE)t)) , 8 , 8 * t);
401                }
402               
403                // メニュー類(右下/右上)
404                menu.draw();
405                chart_switch.draw();
406                economy_switch.draw();
407                speed_switch.draw();
408               
409                // チャート
410                if(chart_switch.getSelected() != "") chart.draw();
411               
412                // message
413                if(message_timer > 0 && timer % 11 < 10){
414                Hell_drawFont(message , (getScreenWidth() - 8 * message.length)/ 2 , getScreenHeight() / 2
415                                        , 1 , 255,128,0);
416                }
417               
418                // 画面ゆれ・ズレ分を元に戻す
419                map.draw_ofs_x -= shake_x;
420                map.draw_ofs_y -= shake_y;
421               
422        // 左下:時刻描画
423        int step      = timer/40;
424        string hour   = zfill(std.string.toString(step / 60 % 12), 2);
425        string minute = zfill(std.string.toString(step % 60), 2);
426        string ampm   = "AM";
427        if(step / 60 % 24 > 11) ampm = "PM";
428
429        Hell_drawFont(ampm ~ " " ~ hour ~ ":" ~ minute,
430                      8,
431                      getScreenHeight() - 40,
432                      2,
433                      255, 255, 255
434                      );
435                     
436                // fps/cpu
437                Hell_drawFPS( 8 , getScreenHeight() - 24 );
438//              Hell_update();
439        }
440       
441        // カーソルがマップを指しているか(メニュー等に指していないか
442        bool onMouseMap(){
443                if(menu.getMouseOver() == "" && economy_switch.getMouseOver() == ""
444                        && chart_switch.getMouseOver() == "" && speed_switch.getMouseOver() == "") return true;
445               
446                return false;
447        }
448       
449        // 画面サイズ取得
450        int getScreenWidth(){return boot.g_width;}
451        int getScreenHeight(){return boot.g_height;}
452       
453        string zfill(string str , int n){
454                for(int t=str.length;t<n;t++){
455                        str = "0" ~ str;
456                }
457                return str;
458        }
459}
460
461
462/********************************************************************************/
463/*      チャート                                                                                                                                    */
464/********************************************************************************/
465
466class PlayChart{
467        class Log{
468                double[] param;
469               
470                this(int n){
471                        param = new double[n];
472                }
473               
474                void set(int t,double p){
475                        param[t] = p;
476                }
477               
478                int length(){return param.length;}
479                double getMax(){
480                        double result = 0;
481                        foreach(p;param) if(p > result) result = p;
482                        return result;
483                }
484        }
485       
486        Log[] logs;
487        GameMain gamemain;
488       
489        static const int LOG_MAX = 160;
490        static const int LOG_VIEW_WIDTH = 4;
491       
492        this(GameMain gamemain){
493                logs = new Log[ LOG_MAX ];
494                foreach(inout l;logs) l = null;
495                this.gamemain = gamemain;
496        }
497       
498        // チャートを更新する
499        void addChart(CharacterPool cp , Map map){
500                for(int t=0;t<logs.length-1;t++){
501                        logs[t] = logs[t + 1];
502                }
503               
504                Log newline = new Log(Character.TYPE.MAX + 1);
505                for(int t=0;t<newline.length();t++){
506                        if(t == Character.TYPE.NONE) continue;
507                       
508                        if(t < Character.TYPE.MAX){
509                                newline.set(t , cp.count(cast(Character.TYPE)t));
510                        }else{
511                                newline.set(t , map.count(MapChip.TYPE.MOVIE));
512                        }
513                }
514               
515                logs[length - 1] = newline;
516        }
517       
518        // 作画
519        void draw(){
520                // キャラクタごとのカラー(Character.TYPE参照)
521                //                                              NONE  NICO SOWA  RAY   EXPL  UPNS  ARAS   MOVIE
522                static const int r[] = [  0 ,   0 ,   0 ,   0 ,   0 ,   0 , 255 , 192 ];
523                static const int g[] = [  0 , 255 ,   0 ,   0 ,   0 ,   0 ,   0 , 192 ];
524                static const int b[] = [  0 ,   0 ,   0 ,   0 ,   0 , 255 ,   0 , 192 ];
525               
526                if(!logs[length - 1]) return;
527               
528                float scale = 2;
529                while(gamemain.getScreenHeight() - 80 - logs[length - 1].getMax() * scale < 80){
530                        scale /= 2.0;
531                }
532               
533                for(int t=0;t<logs.length - 1;t++){
534                        if(logs[t] && logs[t+1]){
535                                for(int e;e < logs[t].param.length ; e++){
536                                        if(r[e] == 0 && g[e] == 0 && b[e] == 0) continue;
537                                       
538                                        Hell_drawLine(t * LOG_VIEW_WIDTH , gamemain.getScreenHeight() - 80 - logs[t].param[e] * scale
539                                                        , (t+1) * LOG_VIEW_WIDTH , gamemain.getScreenHeight() - 80 - logs[t+1].param[e] * scale
540                                                        , 2 , r[e] , g[e] , b[e]);
541                                }
542                        }
543                }
544        }
545}
Note: See TracBrowser for help on using the browser.