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

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