6 #include <Richedit.h>
\r
8 #pragma comment(lib, "user32.lib")
\r
13 #pragma comment(linker, "/subsystem:console")
\r
15 #pragma comment(linker, "/subsystem:windows")
\r
18 using namespace std;
\r
21 const int WIDTH = 56, HEIGHT = 29;
\r
30 HWND hwnd_notepad = NULL;
\r
31 HWND hwnd_edit = NULL;
\r
34 int len = SendMessageA(hwnd_edit, WM_GETTEXTLENGTH, 0, 0);
\r
35 char *buffer = new char[len + 1];
\r
36 int read = SendMessageA(hwnd_edit, WM_GETTEXT, len + 1, (LPARAM)buffer);
\r
40 string result(buffer);
\r
46 SendMessage(hwnd_edit, EM_SETSEL, 0, get_text().size());
\r
49 void select_length(int from, int length) {
\r
50 SendMessage(hwnd_edit, EM_SETSEL, from, from + length);
\r
53 void select_from_to(int from, int to) {
\r
54 SendMessage(hwnd_edit, EM_SETSEL, from, to);
\r
57 void replace(string str) {
\r
58 SendMessage(hwnd_edit, EM_REPLACESEL, FALSE, (LPARAM)str.c_str());
\r
61 int get_pos(int x, int y) {
\r
62 return (y + 1) * (WIDTH + 4) + x + 1;
\r
65 char get_block(int x, int y) {
\r
66 return map[get_pos(x, y)];
\r
74 int pos = get_pos(x, y);
\r
75 select_length(pos, 1);
\r
76 replace({ map[pos], 0 });
\r
80 int pos = get_pos(x, y);
\r
81 select_length(pos, 1);
\r
82 replace({ 'Q', 0 });
\r
85 void move_to(int x, int y) {
\r
92 void move(int dx, int dy) {
\r
93 move_to(x + dx, y + dy);
\r
96 bool collision(int xdir, int ydir) {
\r
97 int newx = x + xdir;
\r
98 int newy = y + ydir;
\r
99 if (newx < 0 || newx >= WIDTH || newy < 0 || newy >= HEIGHT)
\r
101 return get_block(newx, newy) == 'X';
\r
104 Player player { 0, 0 };
\r
108 std::string read_map(int lvl) {
\r
109 std::ifstream ifs("lvl/" + std::to_string(lvl) + ".txt",
\r
110 std::ios::in | std::ios::binary);
\r
113 ifs.seekg(0, std::ios::end);
\r
114 int length = ifs.tellg();
\r
115 ifs.seekg(0, std::ios::beg);
\r
116 char *buffer = new char[length + 1];
\r
117 ifs.read(buffer, length);
\r
119 buffer[length] = 0;
\r
120 std::string result(buffer);
\r
130 void load_level(int lvl) {
\r
131 map = read_map(lvl);
\r
133 for (int x = 0; x < WIDTH; x++) {
\r
134 for (int y = 0; y < HEIGHT; y++) {
\r
135 if (map[get_pos(x, y)] == 'S')
\r
136 player.move_to(x, y);
\r
144 PROCESS_INFORMATION pi;
\r
146 BOOL CALLBACK ew_cb(HWND hwnd, LPARAM lp) {
\r
148 DWORD tid = GetWindowThreadProcessId(hwnd, &pid);
\r
149 if (pi.dwProcessId == pid && pi.dwThreadId == tid) {
\r
150 hwnd_notepad = hwnd;
\r
155 BOOL CALLBACK ecw_cb(HWND child, LPARAM in) {
\r
156 char buffer[1024 + 1];
\r
157 int len = GetClassNameA(child, buffer, 1024);
\r
159 if (strcmp(buffer, "Edit") == 0) {
\r
166 void start_notepad() {
\r
167 ZeroMemory(&si, sizeof(si));
\r
168 si.cb = sizeof(si);
\r
169 ZeroMemory(&pi, sizeof(pi));
\r
171 if (!CreateProcessA(NULL, // No module name (use command line)
\r
172 "notepad.exe", // Command line
\r
173 NULL, // Process handle not inheritable
\r
174 NULL, // Thread handle not inheritable
\r
175 FALSE, // Set handle inheritance to FALSE
\r
176 0, // No creation flags
\r
177 NULL, // Use parent's environment block
\r
178 NULL, // Use parent's starting directory
\r
179 &si, // Pointer to STARTUPINFO structure
\r
180 &pi) // Pointer to PROCESS_INFORMATION structure
\r
182 printf("CreateProcess failed (%d).\n", GetLastError());
\r
185 EnumWindows(ew_cb, 0);
\r
186 EnumChildWindows(hwnd_notepad, ecw_cb, 0);
\r
187 SendMessage(hwnd_edit, EM_SETREADONLY, TRUE, NULL);
\r
189 void close_notepad() {
\r
190 TerminateProcess(pi.hProcess, 0);
\r
191 CloseHandle(pi.hProcess);
\r
192 CloseHandle(pi.hThread);
\r
206 bool key_state[(uint64_t)Key::COUNT];
\r
207 bool key_state_old[(uint64_t)Key::COUNT];
\r
209 int key_get_vk(Key key) {
\r
211 case Key::Left: return 'A';
\r
212 case Key::Right: return 'D';
\r
213 case Key::Jump: return VK_SPACE;
\r
214 case Key::Exit: return VK_ESCAPE;
\r
215 case Key::Redraw: return 'R';
\r
220 void update_key_state() {
\r
221 for (int i = 0; i < (int)Key::COUNT; i++) {
\r
222 key_state[i] = GetAsyncKeyState(key_get_vk((Key)i));
\r
226 void update_key_state_old() {
\r
227 for (int i = 0; i < (int)Key::COUNT; i++) {
\r
228 key_state_old[i] = key_state[i];
\r
232 bool key_pressed(Key key) {
\r
233 return key_state[(int)key] && !key_state_old[(int)key];
\r
236 bool key_down(Key key) {
\r
237 return key_state[(int)key];
\r
240 bool key_up(Key key) {
\r
241 return !key_state[(int)key];
\r
245 int main(int argc, char **argv) {
\r
247 int WinMain(HINSTANCE a0, HINSTANCE a1, LPSTR a2, int a3) {
\r
250 if (hwnd_notepad == NULL || hwnd_edit == NULL) {
\r
256 dt = ((double)clock() - game_clock) / CLOCKS_PER_SEC * 1000;
\r
257 game_clock = clock();
\r
258 update_key_state();
\r
260 if (key_pressed(Key::Exit))
\r
262 if (key_pressed(Key::Redraw))
\r
264 if (key_down(Key::Left) && !player.collision(-1, 0))
\r
265 player.move(-1, 0);
\r
266 if (key_down(Key::Right) && !player.collision(1, 0))
\r
267 player.move(+1, 0);
\r
268 if (key_pressed(Key::Jump) && player.collision(0, 1))
\r
269 player.move(0, -1);
\r
271 update_key_state_old();
\r