fork download
  1. // console2.cpp --- 仮想コンソール2
  2. #include "DxLib.h" // DXライブラリ
  3. #include <string> // for std::string
  4. #include <cassert> // for assert
  5.  
  6. #define CHAR_HEIGHT 32 // 文字の高さ
  7. #define CHAR_WIDTH (CHAR_HEIGHT / 2) // 半角文字の幅
  8. #define COLUMNS 40 // 列の個数
  9. #define ROWS 15 // 行の個数
  10. #define CONSOLE_WIDTH (COLUMNS * CHAR_WIDTH) // コンソールの幅
  11. #define CONSOLE_HEIGHT (ROWS * CHAR_HEIGHT) // コンソールの高さ
  12. #define BLINK_RATE 200 // 点滅間隔(ミリ秒)
  13. #define PROMPT "C:\\> " // プロンプト
  14.  
  15. char gp_buf[ROWS][COLUMNS]; // 仮想コンソール
  16. int gp_cx = 0, gp_cy = 0; // キャレット位置(文字単位)
  17. int gp_px = 0, gp_py = 0; // キャレットを動かせる限界位置
  18. int gp_font; // フォントハンドル
  19. bool gp_blink = false; // キャレットの点滅用フラグ
  20. bool gp_exit_flag = false; // 終了フラグ
  21.  
  22. std::string gp_output; // コンソール出力文字列
  23.  
  24. // 仮想コンソールを描画する。
  25. void gp_DrawConsole(void)
  26. {
  27. char str[2]; // 文字列を格納する文字配列。
  28. str[1] = 0; // strがゼロ終端になるようにする。
  29.  
  30. // それぞれの行について
  31. for (int y = 0; y < ROWS; ++y)
  32. {
  33. // それぞれの列について
  34. for (int x = 0; x < COLUMNS; ++x)
  35. {
  36. // 文字を取り出す。strはゼロ終端のC文字列になる。
  37. str[0] = gp_buf[y][x];
  38. assert(str[1] == 0);
  39.  
  40. // 指定されたフォントを使って指定位置へ描画する。
  41. DrawStringToHandle(x * CHAR_WIDTH, y * CHAR_HEIGHT,
  42. str, 0xFFFFFF, gp_font);
  43.  
  44. // もしキャレット位置であり、点灯状態であれば、
  45. if (gp_cx == x && gp_cy == y && gp_blink)
  46. {
  47. // キャレットを描画する。
  48. str[0] = '_';
  49. assert(str[1] == 0);
  50. DrawStringToHandle(x * CHAR_WIDTH, y * CHAR_HEIGHT,
  51. str, 0xFF9999, gp_font);
  52. }
  53. }
  54. }
  55. }
  56.  
  57. // 背景を描画する。
  58. void gp_DrawBackground(void)
  59. {
  60. // 三角形を描く。
  61. DrawLine(CONSOLE_WIDTH / 2, 0, 0, CONSOLE_HEIGHT, 0x666666);
  62. DrawLine(0, CONSOLE_HEIGHT, CONSOLE_WIDTH, CONSOLE_HEIGHT / 2, 0x666666);
  63. DrawLine(CONSOLE_WIDTH, CONSOLE_HEIGHT / 2, CONSOLE_WIDTH / 2, 0, 0x666666);
  64. }
  65.  
  66. // 上にスクロールする。
  67. void gp_ScrollUp(void)
  68. {
  69. // gp_bufの(ROWS - 1)個の行をずらす。
  70. memmove(gp_buf[0], gp_buf[1], COLUMNS * (ROWS - 1));
  71.  
  72. // 最後の行を空白にする。
  73. memset(gp_buf[ROWS - 1], ' ', COLUMNS);
  74.  
  75. // キャレットを動かせる限界位置を修正する。
  76. if (gp_py > 0)
  77. --gp_py;
  78. else
  79. gp_px = 0;
  80. }
  81.  
  82. // コンソール画面での位置関係を判定する。(x0, y0)≦(x1, y1)
  83. bool LessOrEqual(int x0, int y0, int x1, int y1)
  84. {
  85. if (y0 > y1)
  86. return false;
  87. if (y0 < y1)
  88. return true;
  89. if (x0 <= x1)
  90. return true;
  91. return false;
  92. }
  93.  
  94. // 入力行を取得する。
  95. std::string gp_GetLine(void)
  96. {
  97. int x, y;
  98. std::string str;
  99.  
  100. // (gp_cx, gp_cy)≦(gp_px, gp_py)ならば空文字列を返す。
  101. if (LessOrEqual(gp_cx, gp_cy, gp_px, gp_py))
  102. return str; // 空文字列
  103.  
  104. // (gp_px, gp_py)~(gp_cx, gp_cy)の文字列を取得する。
  105. x = gp_px;
  106. y = gp_py;
  107. while (x != gp_cx || y != gp_cy)
  108. {
  109. // 文字をstrに追加する。
  110. str += gp_buf[y][x];
  111.  
  112. // 次の文字位置まで移動する。
  113. ++x;
  114. if (x >= COLUMNS)
  115. {
  116. x = 0;
  117. ++y;
  118. if (y >= ROWS)
  119. break;
  120. }
  121. }
  122.  
  123. return str; // 成功。取得した文字列。
  124. }
  125.  
  126. // キャレットを一文字左に移動。
  127. void gp_MoveLeft(void)
  128. {
  129. // (gp_cx, gp_cy)≦(0,0) ならば何もしない。
  130. if (LessOrEqual(gp_cx, gp_cy, 0, 0))
  131. return;
  132.  
  133. // (gp_cx, gp_cy)≦(gp_px, gp_py)ならば何もしない。
  134. if (LessOrEqual(gp_cx, gp_cy, gp_px, gp_py))
  135. return;
  136.  
  137. // 左へ移動。
  138. --gp_cx;
  139. if (gp_cx >= 0)
  140. return;
  141.  
  142. // 画面の左端を超えた。修正。
  143. gp_cx = COLUMNS - 1;
  144. --gp_cy;
  145. }
  146.  
  147. // キャレットを一文字右に移動。
  148. void gp_MoveRight(void)
  149. {
  150. // 右へ。
  151. ++gp_cx;
  152. if (gp_cx < COLUMNS)
  153. return;
  154.  
  155. // 画面の右端を超えた。修正。
  156. gp_cx = 0;
  157. ++gp_cy;
  158. if (gp_cy < ROWS)
  159. return;
  160.  
  161. // 画面の右下端を超えた。修正。
  162. --gp_cy;
  163. // 上にスクロールする。
  164. gp_ScrollUp();
  165. }
  166.  
  167. // 改行。
  168. void gp_NewLine(void)
  169. {
  170. // 次の行へ。
  171. gp_cx = 0;
  172. ++gp_cy;
  173. if (gp_cy < ROWS)
  174. return;
  175.  
  176. // 画面の右下端を超えた。修正。
  177. --gp_cy;
  178. // 上にスクロールする。
  179. gp_ScrollUp();
  180. }
  181.  
  182. // 一文字出力する。
  183. void gp_PutChar(char ch)
  184. {
  185. // 文字をgp_bufにセットする。
  186. gp_buf[gp_cy][gp_cx] = ch;
  187.  
  188. // 右へ動く。
  189. gp_MoveRight();
  190. }
  191.  
  192. // 文字列を出力する。
  193. void gp_PutStr(std::string str)
  194. {
  195. // strに含まれる文字を順番に出力する。
  196. for (size_t i = 0; i < str.size(); ++i)
  197. {
  198. gp_PutChar(str[i]);
  199. }
  200. }
  201.  
  202. // 直前の一文字を消して戻る(バックスペース)。
  203. void gp_BackSpace(void)
  204. {
  205. // 左へ動く。
  206. gp_MoveLeft();
  207.  
  208. // gp_bufの一部をずらす。
  209. memmove(&gp_buf[gp_cy][gp_cx], &gp_buf[gp_cy][gp_cx + 1],
  210. COLUMNS - gp_cx - 1);
  211.  
  212. // 行の終わりに空白文字をセットする。
  213. gp_buf[gp_cy][COLUMNS - 1] = ' ';
  214. }
  215.  
  216. // 画面をクリアする。
  217. void gp_Cls(void)
  218. {
  219. // 仮想コンソールを空白で埋め尽くす。
  220. memset(gp_buf, ' ', sizeof(gp_buf));
  221.  
  222. // キャレット位置などを初期化する。
  223. gp_cx = gp_cy = 0;
  224. gp_px = gp_py = 0;
  225. }
  226.  
  227. // 文字列の前後の空白を取り除く。
  228. std::string gp_TrimStr(std::string str)
  229. {
  230. size_t i = str.find_first_not_of(" \t");
  231. if (i != std::string::npos)
  232. {
  233. str = str.substr(i);
  234. i = str.find_last_not_of(" \t");
  235. if (i != std::string::npos)
  236. {
  237. str = str.substr(0, i + 1);
  238. }
  239. }
  240. else
  241. {
  242. str.clear();
  243. }
  244.  
  245. return str;
  246. }
  247.  
  248. // 何かを実行する。
  249. void gp_Execute(std::string str)
  250. {
  251. // 文字列の前後の空白を取り除く。
  252. str = gp_TrimStr(str);
  253.  
  254. // 空文字列なら何もしない。
  255. if (str.empty())
  256. return;
  257.  
  258. // 画面消去コマンド。
  259. if (str == "cls" || str == "CLS")
  260. {
  261. gp_Cls();
  262. return;
  263. }
  264.  
  265. // 終了コマンド。
  266. if (str == "exit" || str == "EXIT")
  267. {
  268. gp_exit_flag = true;
  269. return;
  270. }
  271.  
  272. // その他の場合。
  273. gp_PutStr("You typed: '");
  274. gp_PutStr(str);
  275. gp_PutStr("'");
  276. gp_NewLine();
  277. }
  278.  
  279. // 入力を受け取り、入力に従って処理を行う。
  280. void gp_ReadInput(void)
  281. {
  282. // 文字を入力する。
  283. char ch = GetInputChar(TRUE);
  284. if (ch == 0)
  285. return; // 入力文字なし。
  286.  
  287. #ifdef _DEBUG
  288. // 文字コードをデバッグ出力。
  289. char buf[64];
  290. wsprintf(buf, TEXT("CharCode: %d (0x%02X)\n"), ch, ch);
  291. OutputDebugString(buf);
  292. #endif
  293.  
  294. // 入力された文字コードに従って処理を行う。
  295. switch (ch)
  296. {
  297. case 8: // バックスペース
  298. gp_BackSpace();
  299. break;
  300. case 28: // 右矢印
  301. gp_MoveRight();
  302. break;
  303. case 29: // 左矢印
  304. gp_MoveLeft();
  305. break;
  306. case '\r': // 改行
  307. {
  308. std::string line = gp_GetLine();
  309. gp_NewLine();
  310. gp_Execute(line);
  311. gp_output = PROMPT;
  312. }
  313. break;
  314. default: // その他
  315. gp_PutChar(ch);
  316. }
  317. }
  318.  
  319. // このプログラム内部の初期化を行う。
  320. void gp_Init(void)
  321. {
  322. // 画面サイズの確認。
  323. #if 0
  324. TCHAR gp_buf[32];
  325. wsprintf(gp_buf, TEXT("%d, %d"), CONSOLE_WIDTH, CONSOLE_HEIGHT);
  326. MessageBox(NULL, gp_buf, NULL, 0);
  327. #endif
  328. assert(CONSOLE_WIDTH == 640);
  329. assert(CONSOLE_HEIGHT == 480);
  330. //assert(CONSOLE_WIDTH == 800);
  331. //assert(CONSOLE_HEIGHT == 600);
  332.  
  333. // 後ろの画面に描画する。
  334. SetDrawScreen(DX_SCREEN_BACK);
  335.  
  336. // 画面をクリアする。
  337. gp_Cls();
  338.  
  339. // 指定されたサイズのフォントの作成。アンチエイリアシングを効かせる。
  340. gp_font = CreateFontToHandle("MS ゴシック", CHAR_HEIGHT, 0,
  341. DX_FONTTYPE_ANTIALIASING);
  342.  
  343. // プロンプトを出力する。
  344. gp_output = PROMPT;
  345. }
  346.  
  347. // メイン関数。
  348. INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
  349. {
  350. // 画面サイズとモードの設定。
  351. SetGraphMode(CONSOLE_WIDTH, CONSOLE_HEIGHT, 32);
  352.  
  353. // フルスクリーンにしない。
  354. ChangeWindowMode(TRUE);
  355.  
  356. // DxLibの初期化。
  357. if (DxLib_Init() == -1)
  358. {
  359. return -1;
  360. }
  361.  
  362. // このプログラム内部の初期化。
  363. gp_Init();
  364.  
  365. // 点滅用のカウンタ。
  366. int counter = GetNowCount();
  367.  
  368. // メインループ。
  369. while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen())
  370. {
  371. // 背景を描画する。
  372. gp_DrawBackground();
  373.  
  374. // コンソールを描画する。
  375. gp_DrawConsole();
  376.  
  377. // 出力中か?
  378. if (gp_output.empty())
  379. {
  380. // 入力を受け取り、入力に従って処理を行う。
  381. gp_ReadInput();
  382.  
  383. // 点滅のため、一定時間ごとにフラグを切り替える。
  384. if (GetNowCount() - counter >= BLINK_RATE)
  385. {
  386. // 点滅する。
  387. gp_blink = !gp_blink;
  388.  
  389. // カウンタを更新する。
  390. counter = GetNowCount();
  391. }
  392. }
  393. else
  394. {
  395. // 一文字出力する。
  396. gp_PutChar(gp_output[0]);
  397. gp_output.erase(gp_output.begin());
  398.  
  399. // キャレットを動かせる限界位置を更新。
  400. gp_px = gp_cx;
  401. gp_py = gp_cy;
  402.  
  403. // 点滅しない。
  404. gp_blink = false;
  405. }
  406.  
  407. // 終了フラグが立っていれば終了。
  408. if (gp_exit_flag)
  409. break;
  410. }
  411.  
  412. // DxLibの終了。
  413. DxLib_End();
  414.  
  415. return 0;
  416. } // WinMain
  417.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp:2:45: fatal error: DxLib.h: No such file or directory
compilation terminated.
stdout
Standard output is empty