質問編集履歴

2

コードの追加

2021/02/16 07:20

投稿

sinigami
sinigami

スコア6

test CHANGED
File without changes
test CHANGED
@@ -58,50 +58,690 @@
58
58
 
59
59
  };
60
60
 
61
+
62
+
63
+ struct MUGIC_DATA
64
+
65
+ {
66
+
67
+ double bpm = 120; // BPMが指定されていなければ120に設定
68
+
69
+ double offset = 0; // ノーツが出現する時間が指定されていなければ
70
+
71
+ char song_name[MAX_READ] = "shinigamitowaltz.mp3"; // 曲名
72
+
73
+ char music_file_path[MAX_READ]; // ファイルのパス名
74
+
75
+ double perfect_times[LANE_NUM][NOTE_NUM] = { 0 }; // 判定ラインにノーツが到達する時刻
76
+
77
+ int perfect_time_size[LANE_NUM] = { 0 }; // 初期化処理の0と入ってくる0とを区別する
78
+
79
+ };
80
+
81
+
82
+
83
+ // #STARTより上の情報を読み込む
84
+
85
+ bool loadHumenOptions(MUGIC_DATA* music_data, FILE* fp)
86
+
87
+ {
88
+
89
+ char str[MAX_READ], *next_token = NULL, tstr[MAX_READ];
90
+
91
+ while ((fgets(str, MAX_READ, fp)) != NULL)
92
+
93
+ {
94
+
95
+ strncpy_s(tstr, MAX_READ, str, 6);
96
+
97
+ if (strcmp(tstr, "#START") == 0)
98
+
99
+ {
100
+
101
+ return true;
102
+
103
+ }
104
+
105
+
106
+
107
+ char* first = strtok_s(str, ":", &next_token);
108
+
109
+ if (first == NULL) continue;
110
+
111
+
112
+
113
+ if (strcmp(first, "BPM") == 0) // BPM読み込み
114
+
115
+ {
116
+
117
+ char* second = strtok_s(NULL, ":", &next_token);
118
+
119
+ music_data->bpm = atof(second);
120
+
121
+ }
122
+
123
+ else if (strcmp(first, "OFFSET") == 0) // OFFSET読み込み
124
+
125
+ {
126
+
127
+ char* second = strtok_s(NULL, ":", &next_token);
128
+
129
+ music_data->offset = atof(second);
130
+
131
+ }
132
+
133
+ else if (strcmp(first, "TITLE") == 0) // TITLE読み込み
134
+
135
+ {
136
+
137
+ char* second = strtok_s(NULL, "\n", &next_token);
138
+
139
+ strcpy_s(music_data->song_name, second);
140
+
141
+ }
142
+
143
+ else if (strcmp(first, "WAVE") == 0) // WAVE読み込み
144
+
145
+ {
146
+
147
+ char* second = strtok_s(NULL, "\n", &next_token);
148
+
149
+ strcpy_s(music_data->music_file_path, second);
150
+
151
+ }
152
+
153
+ }
154
+
155
+ return false;
156
+
157
+ }
158
+
159
+
160
+
161
+ // 譜面データを読み込む
162
+
163
+ void loadHumen(MUGIC_DATA* music_data, FILE* fp)
164
+
165
+ {
166
+
167
+ char line[MAX_READ], *next_token = NULL, delim[4] = ", \n";
168
+
169
+
170
+
171
+ for (int col = 0; col < LANE_NUM; col++)
172
+
173
+ {
174
+
175
+ music_data->perfect_time_size[col] = 0;
176
+
177
+ }
178
+
179
+
180
+
181
+ for (int row = 0; (fgets(line, MAX_READ, fp)) != NULL; row++)
182
+
183
+ {
184
+
185
+ char* str = strtok_s(line, delim, &next_token);
186
+
187
+ if (str == NULL) continue;
188
+
189
+
190
+
191
+ for (int col = 0; str != NULL; col++)
192
+
193
+ {
194
+
195
+ int length = strlen(str);
196
+
197
+ for (int i = 0; i < length; i++)
198
+
199
+ {
200
+
201
+ if ('1' <= str[i] && str[i] <= '9')
202
+
203
+ {
204
+
205
+ music_data->perfect_times[col][music_data->perfect_time_size[col]++] =
206
+
207
+ 60.0 * 4 * (row + (double)i / length) / music_data->bpm - music_data->offset;
208
+
209
+ }
210
+
211
+ }
212
+
213
+ str = strtok_s(NULL, delim, &next_token);
214
+
215
+ }
216
+
217
+ }
218
+
219
+ }
220
+
221
+
222
+
223
+ // 譜面データファイルのopen/closeをする処理
224
+
225
+ bool loadHumenData(MUGIC_DATA* music_data, const char* file_name)
226
+
227
+ {
228
+
229
+ FILE* fp;
230
+
231
+
232
+
233
+ if ((fopen_s(&fp, file_name, "r")) != 0 || fp == 0)
234
+
235
+ { // "fpが0である可能性があります"というエラー対策
236
+
237
+ return false; // boolはC++
238
+
239
+ }
240
+
241
+
242
+
243
+ bool loadable = loadHumenOptions(music_data, fp);
244
+
245
+
246
+
247
+ if (loadable) loadHumen(music_data, fp);
248
+
249
+
250
+
251
+ fclose(fp);
252
+
253
+ return true;
254
+
255
+ }
256
+
257
+
258
+
259
+ // ノーツの構造体
260
+
261
+ struct NOTE
262
+
263
+ {
264
+
265
+ bool flag = false;
266
+
267
+ float x = 0.0f;
268
+
269
+ float y = 0.0f;
270
+
271
+ };
272
+
273
+
274
+
275
+ // ノーツ初期化処理
276
+
277
+ void initNotes(int perfect_time_size[LANE_NUM], NOTE notes[LANE_NUM][NOTE_NUM])
278
+
279
+ {
280
+
281
+ for (int col = 0; col < LANE_NUM; col++)
282
+
283
+ {
284
+
285
+ int lane_length = perfect_time_size[col];
286
+
287
+
288
+
289
+ for (int row = 0; row < lane_length; row++)
290
+
291
+ {
292
+
293
+ notes[col][row].flag = true;
294
+
295
+ notes[col][row].x = 200.0f + 150.0f * col;
296
+
297
+ }
298
+
299
+ }
300
+
301
+ }
302
+
303
+
304
+
305
+ // ノーツ更新処理
306
+
307
+ void updateNotes(double current_time, double perfect_times[LANE_NUM][NOTE_NUM], NOTE notes[LANE_NUM][NOTE_NUM])
308
+
309
+ {
310
+
311
+ // ノーツ座標更新
312
+
313
+ for (int col = 0; col < LANE_NUM; col++)
314
+
315
+ {
316
+
317
+ for (int row = 0; row < NOTE_NUM; row++)
318
+
319
+ {
320
+
321
+ if (notes[col][row].flag)
322
+
323
+ notes[col][row].y = JUDGE_Y * (float)(current_time - perfect_times[col][row]) / 2 + JUDGE_Y;
324
+
325
+ }
326
+
327
+ }
328
+
329
+
330
+
331
+ // 画面外かつ判定範囲外に出たノーツを削除
332
+
333
+ for (int col = 0; col < LANE_NUM; col++)
334
+
335
+ {
336
+
337
+ for (int row = 0; row < NOTE_NUM; row++)
338
+
339
+ {
340
+
341
+ if (notes[col][row].flag
342
+
343
+ && WIN_H + NOTE_HEIGHT < notes[col][row].y
344
+
345
+ && 0.3 < current_time - perfect_times[col][row])
346
+
347
+ {
348
+
349
+ notes[col][row].flag = false; // ノーツを削除
350
+
351
+ }
352
+
353
+ }
354
+
355
+ }
356
+
357
+ }
358
+
359
+
360
+
361
+ // ノーツ判定処理
362
+
363
+ void judgeNotes(double current_time, double perfect_times[LANE_NUM][NOTE_NUM], NOTE notes[LANE_NUM][NOTE_NUM], char buf[256])
364
+
365
+ {
366
+
367
+ // レーンに対応するキーが押されていて、かつ判定範囲内であればノーツを削除
368
+
369
+ for (int col = 0; col < LANE_NUM; col++)
370
+
371
+ {
372
+
373
+ for (int row = 0; row < NOTE_NUM; row++)
374
+
375
+ {
376
+
377
+ if (buf[KEYS[col]] == 1 // KEYS[4] = E,F,J,Iが押されている
378
+
379
+ && notes[col][row].flag // ノーツが存在している
380
+
381
+ && -0.03 < current_time - perfect_times[col][row] // -0.03...判定線より上の判定時間
382
+
383
+ && current_time - perfect_times[col][row] < 0.03) // 0.03...判定線より下の判定時間
384
+
385
+ {
386
+
387
+ notes[col][row].flag = false; // ノーツを削除
388
+
389
+ }
390
+
391
+ }
392
+
393
+ }
394
+
395
+ }
396
+
397
+
398
+
399
+ // ノーツ描画処理
400
+
401
+ void drawNotes(NOTE notes[LANE_NUM][NOTE_NUM])
402
+
403
+ {
404
+
405
+ for (int col = 0; col < LANE_NUM; col++)
406
+
407
+ {
408
+
409
+ for (int row = 0; row < NOTE_NUM; row++)
410
+
411
+ {
412
+
413
+ if (notes[col][row].flag) // ノーツが存在している
414
+
415
+ {
416
+
417
+ DrawBoxAA(notes[col][row].x,
418
+
419
+ notes[col][row].y - NOTE_HEIGHT / 4, // / 2,
420
+
421
+ notes[col][row].x + NOTE_WIDTH,
422
+
423
+ notes[col][row].y + NOTE_HEIGHT / 4, // / 2,
424
+
425
+ GetColor(255, 0, 0), // ノーツの色指定(Red,Green,Blue : 0~255)
426
+
427
+ TRUE);
428
+
429
+ //DrawCircleAA(notes[col][row].x, // 円の中心座標x
430
+
431
+ // notes[col][row].y - NOTE_HEIGHT / 2, // 円の中心座標y
432
+
433
+ // 20, // 円の半径(大きさ)
434
+
435
+ // 20, // 円の角の数(多いほど滑らかな円になるが処理が重くなる)
436
+
437
+ // GetColor(255, 0, 0), // ノーツの色指定(Red,Green,Blue : 0~255)
438
+
439
+ // TRUE); // 円の内部まで塗りつぶすか(TRUEで塗りつぶし)
440
+
441
+ }
442
+
443
+ }
444
+
445
+ }
446
+
447
+ }
448
+
449
+
450
+
451
+ // 処理を変更したい場合、WINAPIも変更する
452
+
453
+ // 上で行った処理を呼び出す
454
+
455
+ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
456
+
457
+ {
458
+
459
+
460
+
461
+ MUGIC_DATA music_data;
462
+
463
+ NOTE notes[LANE_NUM][NOTE_NUM];
464
+
465
+ char buf[256]; //キー押下状態格納用配列
466
+
467
+
468
+
469
+ SetMainWindowText("KeyBorder"); //ウインドウのタイトルを設定
470
+
471
+ ChangeWindowMode(TRUE); //ウィンドウモードで起動
472
+
473
+ SetGraphMode(WIN_W, WIN_H, 32); //画面の解像度指定
474
+
475
+ SetWindowSizeChangeEnableFlag(FALSE); //画面サイズ変更不可
476
+
477
+ if (DxLib_Init() == -1) { return -1; } //DxLib初期化処理
478
+
479
+ SetDrawScreen(DX_SCREEN_BACK); //描画先を裏画面に設定
480
+
481
+
482
+
483
+ loadHumenData(&music_data, "test.txt"); // 譜面データ読み込み
484
+
485
+
486
+
487
+ initNotes(music_data.perfect_time_size, notes); // ノーツ初期化処理
488
+
489
+
490
+
491
+ int bgmHandle = LoadSoundMem(music_data.music_file_path);
492
+
493
+ PlaySoundMem(bgmHandle, DX_PLAYTYPE_BACK);
494
+
495
+
496
+
497
+ LONGLONG start_count = GetNowHiPerformanceCount();
498
+
499
+
500
+
501
+ //while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
502
+
503
+ while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0)
504
+
505
+ {
506
+
507
+
508
+
509
+ GetHitKeyStateAll(buf);
510
+
511
+ if (buf[KEY_INPUT_ESCAPE] == 1) // ESACAPEキーが押された時
512
+
513
+ {
514
+
515
+ break; // 終了
516
+
517
+ }
518
+
519
+
520
+
521
+ LONGLONG now_count = GetNowHiPerformanceCount();
522
+
523
+ double current_time = (now_count - start_count) / 1000000.0;
524
+
525
+
526
+
527
+ // ノーツの更新処理
528
+
529
+ updateNotes(current_time,
530
+
531
+ music_data.perfect_times,
532
+
533
+ notes);
534
+
535
+
536
+
537
+ // ノーツの判定処理
538
+
539
+ judgeNotes(current_time,
540
+
541
+ music_data.perfect_times,
542
+
543
+ notes, buf);
544
+
545
+
546
+
547
+ // 判定線表示
548
+
549
+ DrawLine(
550
+
551
+ 0,
552
+
553
+ JUDGE_Y,
554
+
555
+ WIN_W,
556
+
557
+ JUDGE_Y,
558
+
559
+ GetColor(0, 0, 255) // 判定線のRGB指定
560
+
561
+ );
562
+
563
+
564
+
565
+ // 境界線表示
566
+
567
+ // 1レーン目
568
+
569
+ DrawLine(
570
+
571
+ 200, // 第一X(右)方向座標 X方向への境界線表示位置1
572
+
573
+ 0, // 第一Y(上)方向座標 Y方向への境界線表示位置1
574
+
575
+ 200, // 第二X(右)方向座標 X方向への境界線表示位置2
576
+
577
+ 500, // 第二Y(上)方向座標 Y方向への境界線表示位置2
578
+
579
+ GetColor(0, 255, 0) // 境界線のRGB指定
580
+
581
+ );
582
+
583
+
584
+
585
+ DrawLine(
586
+
587
+ 270, // 第一X(右)方向座標 X方向への境界線表示位置1
588
+
589
+ 0, // 第一Y(上)方向座標 Y方向への境界線表示位置1
590
+
591
+ 270, // 第二X(右)方向座標 X方向への境界線表示位置2
592
+
593
+ 500, // 第二Y(上)方向座標 Y方向への境界線表示位置2
594
+
595
+ GetColor(0, 255, 0) // 境界線のRGB指定
596
+
597
+ );
598
+
599
+
600
+
601
+ // 2レーン目
602
+
603
+ DrawLine(
604
+
605
+ 350, // 第一X(右)方向座標 X方向への境界線表示位置1
606
+
607
+ 0, // 第一Y(上)方向座標 Y方向への境界線表示位置1
608
+
609
+ 350, // 第二X(右)方向座標 X方向への境界線表示位置2
610
+
611
+ 500, // 第二Y(上)方向座標 Y方向への境界線表示位置2
612
+
613
+ GetColor(0, 255, 0) // 境界線のRGB指定
614
+
615
+ );
616
+
617
+
618
+
619
+ DrawLine(
620
+
621
+ 420, // 第一X(右)方向座標 X方向への境界線表示位置1
622
+
623
+ 0, // 第一Y(上)方向座標 Y方向への境界線表示位置1
624
+
625
+ 420, // 第二X(右)方向座標 X方向への境界線表示位置2
626
+
627
+ 500, // 第二Y(上)方向座標 Y方向への境界線表示位置2
628
+
629
+ GetColor(0, 255, 0) // 境界線のRGB指定
630
+
631
+ );
632
+
633
+
634
+
635
+ // 3レーン目
636
+
637
+ DrawLine(
638
+
639
+ 500, // 第一X(右)方向座標 X方向への境界線表示位置1
640
+
641
+ 0, // 第一Y(上)方向座標 Y方向への境界線表示位置1
642
+
643
+ 500, // 第二X(右)方向座標 X方向への境界線表示位置2
644
+
645
+ 500, // 第二Y(上)方向座標 Y方向への境界線表示位置2
646
+
647
+ GetColor(0, 255, 0) // 境界線のRGB指定
648
+
649
+ );
650
+
651
+
652
+
653
+ DrawLine(
654
+
655
+ 570, // 第一X(右)方向座標 X方向への境界線表示位置1
656
+
657
+ 0, // 第一Y(上)方向座標 Y方向への境界線表示位置1
658
+
659
+ 570, // 第二X(右)方向座標 X方向への境界線表示位置2
660
+
661
+ 500, // 第二Y(上)方向座標 Y方向への境界線表示位置2
662
+
663
+ GetColor(0, 255, 0) // 境界線のRGB指定
664
+
665
+ );
666
+
667
+
668
+
669
+ // 4レーン目
670
+
671
+ DrawLine(
672
+
673
+ 650, // 第一X(右)方向座標 X方向への境界線表示位置1
674
+
675
+ 0, // 第一Y(上)方向座標 Y方向への境界線表示位置1
676
+
677
+ 650, // 第二X(右)方向座標 X方向への境界線表示位置2
678
+
679
+ 500, // 第二Y(上)方向座標 Y方向への境界線表示位置2
680
+
681
+ GetColor(0, 255, 0) // 境界線のRGB指定
682
+
683
+ );
684
+
685
+
686
+
687
+ DrawLine(
688
+
689
+ 720, // 第一X(右)方向座標 X方向への境界線表示位置1
690
+
691
+ 0, // 第一Y(上)方向座標 Y方向への境界線表示位置1
692
+
693
+ 720, // 第二X(右)方向座標 X方向への境界線表示位置2
694
+
695
+ 500, // 第二Y(上)方向座標 Y方向への境界線表示位置2
696
+
697
+ GetColor(0, 255, 0) // 境界線のRGB指定
698
+
699
+ );
700
+
701
+
702
+
703
+ DrawFormatString(
704
+
705
+ 10,
706
+
707
+ 10,
708
+
709
+ GetColor(255, 255, 255),
710
+
711
+ "t:%f\nbpm:%f\noffset:%f\n%s\n%s",
712
+
713
+ current_time,
714
+
715
+ music_data.bpm,
716
+
717
+ music_data.offset,
718
+
719
+ music_data.song_name,
720
+
721
+ music_data.music_file_path
722
+
723
+ );
724
+
725
+
726
+
727
+ // ノーツの表示
728
+
729
+ drawNotes(notes);
730
+
731
+ }
732
+
733
+ DxLib_End(); //DxLibの終了処理
734
+
735
+ return 0; //正常終了
736
+
737
+ }
738
+
739
+ ```
740
+
741
+
742
+
61
743
  ----------------------------------------------
62
744
 
63
- // ノーツ判定処理
64
-
65
- void judgeNotes(double current_time, double perfect_times[LANE_NUM][NOTE_NUM], NOTE notes[LANE_NUM][NOTE_NUM], char buf[256])
66
-
67
- {
68
-
69
- // レーンに対応するキーが押されていて、かつ判定範囲内であればノーツを削除
70
-
71
- for (int col = 0; col < LANE_NUM; col++)
72
-
73
- {
74
-
75
- for (int row = 0; row < NOTE_NUM; row++)
76
-
77
- {
78
-
79
- if (buf[KEYS[col]] == 1 // KEYS[4] = E,F,J,Iが押されている
80
-
81
- && notes[col][row].flag // ノーツが存在している
82
-
83
- && -0.01 < current_time - perfect_times[col][row] // -0.01...判定線より上の判定時間
84
-
85
- && current_time - perfect_times[col][row] < 0.01) // 0.01...判定線より下の判定時間
86
-
87
- {
88
-
89
- notes[col][row].flag = false; // ノーツを削除
90
-
91
- }
92
-
93
- }
94
-
95
- }
96
-
97
- }
98
-
99
- ```
100
-
101
-
102
-
103
- ----------------------------------------------
104
-
105
745
  ### 試したこと
106
746
 
107
747
 

1

コードの挿入で見やすく改善

2021/02/16 07:20

投稿

sinigami
sinigami

スコア6

test CHANGED
File without changes
test CHANGED
@@ -15,6 +15,8 @@
15
15
 
16
16
 
17
17
  ### 該当のソースコード
18
+
19
+ ```
18
20
 
19
21
  C++, dx.lib
20
22
 
@@ -94,6 +96,10 @@
94
96
 
95
97
  }
96
98
 
99
+ ```
100
+
101
+
102
+
97
103
  ----------------------------------------------
98
104
 
99
105
  ### 試したこと