ModelingDebug/ModelingMusic/MusicFrom.cs

429 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using NAudio.Wave;
/// <summary>
/// The <c>ModelingMusic</c> namespace contains classes and methods for modeling and manipulating musical data.
/// </summary>
namespace Debug.ModelingMusic;
public class MusicFrom
{
// 导入kernel32.dll中的SetConsoleMode函数
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
// 导入kernel32.dll中的GetStdHandle函数
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
// 定义控制台模式常量
private const uint ENABLE_ECHO_INPUT = 0x0004;
private const uint ENABLE_LINE_INPUT = 0x0002;
private const uint ENABLE_PROCESSED_INPUT = 0x0001;
// 导入kernel32.dll中的GetConsoleMode函数
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
// 定义标准输入句柄
private const int STD_INPUT_HANDLE = -10;
private long time = 0;
int MaxX = 0;
int MaxY = 0;
public MusicFrom()
{
setCharArry();
MaxY = Program.chars.GetLength(0);
MaxX = Program.chars.GetLength(1);
new Thread(PrintCharArray).Start();
new Thread(KeyboardMapping).Start();
new Thread(Run).Start();
// 恢复控制台输入模式
// mode |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
// SetConsoleMode(hStdin, mode);
}
public void Run()
{
Thread.Sleep(500);
while (Program.IsWhile)
{
// 随机数
int random = Program.random.Next(0, 7);
switch (random)
{
case 0:
DownKey('D', 3);
break;
case 1:
DownKey('F', 10);
break;
case 2:
DownKey('G', 17);
break;
case 3:
DownKey('M', 24);
break;
case 4:
DownKey('J', 31);
break;
case 5:
DownKey('K', 38);
break;
case 6:
DownKey('L', 45);
break;
default:
break;
}
Thread.Sleep(1000);
}
}
class ZIFUKEY
{
public char key;
public bool isDown;//是否被按下
}
public void DownKey(char key, int x)
{
new Thread(() =>
{
var zIFUKEY = new ZIFUKEY() { key = key, isDown = false };
for (int i = 0; i < MaxY; i++)
{
Program.chars[i, x].Char = zIFUKEY.key;
Thread.Sleep(260);
Program.chars[i, x].Char = ' ';
if (zIFUKEY.isDown)
{
break;
}
}
}).Start();
}
readonly char[] jianpan = ['D', 'F', 'G', ' ', 'J', 'K', 'L'];
public void PrintCharArray()
{
// 获取标准输入句柄
IntPtr hStdin = GetStdHandle(STD_INPUT_HANDLE);
// 获取当前控制台输入模式
uint mode;
if (!GetConsoleMode(hStdin, out mode))
{
Console.WriteLine("无法获取控制台输入模式");
return;
}
// 禁用回显和行输入
mode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
if (!SetConsoleMode(hStdin, mode))
{
Console.WriteLine("无法设置控制台输入模式");
return;
}
var stopwatch = new Stopwatch();
int frameCount = 0;
double totalTime = 0;
int i; int j;
// 获取字符数组的行数和列数
var a = Program.chars.GetLength(0);
var b = Program.chars.GetLength(1);
var buffer = new StringBuilder();
while (Program.IsWhile)
{
stopwatch.Restart();
Console.SetCursorPosition(0, 0);// 设定光标位置
Console.Clear();
buffer.Clear();
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
buffer.Append(Program.chars[i, j].Char);
time++;
if (time > 100000)
{
GC.Collect(); time = 0;
}
}
buffer.AppendLine();
}
Console.ForegroundColor = ConsoleColor.DarkBlue;
Console.Write(buffer.ToString());
buffer.Clear();
for (i = 0; i < b; i++)
{
buffer.Append('-');
}
// 打印ASDF HJKL
buffer.AppendLine();
Console.Write(buffer);
buffer.Clear();
// int totalLength = 50;
int totalAs = jianpan.Length;
int spaceBetweenAs = (b - totalAs) / (totalAs - 1);
for (i = 0; i < totalAs; i++)
{
buffer.Clear();
// if (isDown[3] && i == 3)
// {
// // 显示空格键
// // ConsoleKey.Spacebar
// buffer.Append("Spacebar");
// continue;
// }
for (j = 0; j < spaceBetweenAs / 2; j++)
{
buffer.Append(' ');
}
buffer.Append(jianpan[i]);
if (isDown[i])
{
Console.ForegroundColor = ConsoleColor.Red; // 设置颜色为红色
}
else
{
Console.ForegroundColor = ConsoleColor.Blue; // 设置颜色为白色
}
for (j = 0; j < spaceBetweenAs / 2; j++)
{
buffer.Append(' ');
}
Console.Write(buffer);
}
// 停止计时并计算本帧的处理时间
stopwatch.Stop();
double elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
totalTime += elapsedMilliseconds;
frameCount++;
// 计算帧率
double fps = frameCount / (totalTime / 1000.0);
// Console.ResetColor();
Console.ForegroundColor = ConsoleColor.White;
buffer.Clear();
buffer.Append($" {fps:0} FPS ");
Console.WriteLine(buffer);
buffer.Clear();
buffer.Append($" {score.ToString("D10")} ");
Console.SetCursorPosition(49, 0);
Console.Write(buffer);
// 保持每秒约16.67ms即大约60 FPS的间隔
// Thread.Sleep(Math.Max(0, 60 - (int)elapsedMilliseconds));
//这样闪烁不会太严重
Thread.Sleep(50);
}
// 恢复控制台输入模式
mode |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
SetConsoleMode(hStdin, mode);
}
private void setCharArry()
{
for (int i = 0; i < Program.chars.GetLength(0); i++)
{
for (int j = 0; j < Program.chars.GetLength(1); j++)
{
Program.chars[i, j] = new Point(); // 初始化每个元素
}
}
}
//分数long 000000000
private long score = 0;
readonly bool[] isDown = new bool[7];
// 导入user32.dll中的GetAsyncKeyState函数
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern short GetAsyncKeyState(int vkey);
// 定义虚拟键码
const int VK_D = 0x44; // D键
const int VK_F = 0x46; // F键
const int VK_G = 0x47; // G键
const int VK_J = 0x4A; // J键
const int VK_K = 0x4B; // K键
const int VK_L = 0x4C; // L键
const int VK_SPACE = 0x20; // 空格键
const int VK_ENTER = 0x0D; // Enter键
const int VK_ESCAPE = 0x1B; // ESC键
/// <summary>
/// 键盘监听方法
/// </summary>
public void KeyboardMapping()
{
// 创建一个字典来跟踪每个按键的前一次状态
var keyStates = new Dictionary<int, bool>
{
{ VK_D, false },
{ VK_F, false },
{ VK_G, false },
{ VK_J, false },
{ VK_K, false },
{ VK_L, false },
{ VK_SPACE, false },
{ VK_ENTER, false },
{ VK_ESCAPE, false }
};
while (true)
{
// ConsoleKeyInfo keyInfo = Console.ReadKey(true); // true表示不显示输入的字符
// 检查并处理所有监控的按键状态变化
foreach (var kvp in keyStates)
{
int vkey = kvp.Key;
bool wasPressed = kvp.Value;
// 检查当前按键的状态
short keyState = GetAsyncKeyState(vkey);
bool isKeyPressed = (keyState & 0x8000) != 0;
if (isKeyPressed && !wasPressed)
{
// 按下时触发
HandleKeyPress(vkey);
}
else if (!isKeyPressed && wasPressed)
{
// 松开时触发
HandleKeyRelease(vkey);
}
// 更新按键状态
keyStates[vkey] = isKeyPressed;
}
// 避免CPU占用过高
Thread.Sleep(50);
}
}
void HandleKeyPress(int vkey)
{
switch (vkey)
{
case VK_ESCAPE:
if (Program.IsWhile)
{
Program.IsWhile = false;
Console.SetCursorPosition(60, 5);
Console.Write("暂停状态 再次按下ESC退出游戏/按回车键继续");
}
else
{
Console.Clear();
Environment.Exit(0);
}
// 处理ESC键被按下的逻辑
break;
case VK_ENTER:
if (!Program.IsWhile)
{
Program.IsWhile = true;
new Thread(PrintCharArray).Start();
}
// 处理Enter键被按下的逻辑
break;
case VK_D:
isDown[0] = true;
// 处理D键被按下的逻辑
if (Program.chars[8, 3].Char == 'D' || Program.chars[9, 3].Char == 'D')
{
score += 100;
}
break;
case VK_F:
isDown[1] = true;
// 处理F键被按下的逻辑
if (Program.chars[8, 10].Char == 'F' || Program.chars[9, 10].Char == 'F')
{
score += 100;
}
break;
case VK_G:
isDown[2] = true;
// 处理G键被按下的逻辑
if (Program.chars[8, 17].Char == 'G' || Program.chars[9, 17].Char == 'G')
{
score += 100;
}
break;
case VK_SPACE:
isDown[3] = true;
// 处理空格键被按下的逻辑
break;
case VK_J:
isDown[4] = true;
// 处理J键被按下的逻辑
if (Program.chars[8, 31].Char == 'J' || Program.chars[9, 31].Char == 'J')
{
score += 100;
}
break;
case VK_K:
isDown[5] = true;
// 处理K键被按下的逻辑
if (Program.chars[8, 38].Char == 'K' || Program.chars[9, 38].Char == 'K')
{
score += 100;
}
break;
case VK_L:
isDown[6] = true;
// 处理L键被按下的逻辑
if (Program.chars[8, 45].Char == 'L' || Program.chars[9, 45].Char == 'L')
{
score += 100;
}
break;
}
}
void HandleKeyRelease(int vkey)
{
switch (vkey)
{
case VK_D:
isDown[0] = false;
// 处理D键被释放的逻辑
break;
case VK_F:
isDown[1] = false;
// 处理F键被释放的逻辑
break;
case VK_G:
isDown[2] = false;
// 处理G键被释放的逻辑
break;
case VK_SPACE:
isDown[3] = false;
// 处理空格键被释放的逻辑
break;
case VK_J:
isDown[4] = false;
// 处理J键被释放的逻辑
break;
case VK_K:
isDown[5] = false;
// 处理K键被释放的逻辑
break;
case VK_L:
isDown[6] = false;
// 处理L键被释放的逻辑
break;
}
}
}