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
71 int x_screen = -1, y_screen = -1;
\r
72 double x, y, x_vel, y_vel;
\r
75 if (x_screen < 0 || y_screen < 0) return;
\r
76 int pos = get_pos(x_screen, y_screen);
\r
77 select_length(pos, 1);
\r
78 replace({ map[pos], 0 });
\r
82 if (collision_x(x - x_screen) || collision_y(y - y_screen)) {
\r
87 x_screen = round(x);
\r
88 y_screen = round(y);
\r
89 int pos = get_pos(x_screen, y_screen);
\r
90 select_length(pos, 1);
\r
91 replace({ 'Q', 0 });
\r
97 if (!collision_y(1) && y_vel < 9)
\r
99 if (abs(x - x_screen) >= 1 || abs(x - x_screen) >= 1) {
\r
105 void move_to(int x, int y) {
\r
112 void move(int dx, int dy) {
\r
113 move_to(x + dx, y + dy);
\r
116 bool collision_x(int n) {
\r
117 if (x + n < 0 || x + n >= WIDTH)
\r
119 for (int i = 0; i != n; i += (n < 0 ? -1 : 1))
\r
120 if (get_block(x_screen + i + (n < 0 ? -1 : 1), y_screen) == 'X')
\r
124 bool collision_y(int n) {
\r
125 if (y + n < 0 || y + n >= HEIGHT)
\r
127 for (int i = 0; i != n; i += (n < 0 ? -1 : 1))
\r
128 if (get_block(x_screen, y_screen + i + (n < 0 ? -1 : 1)) == 'X')
\r
133 Player player { 0, 0 };
\r
137 std::string read_map(int lvl) {
\r
138 std::ifstream ifs("lvl/" + std::to_string(lvl) + ".txt",
\r
139 std::ios::in | std::ios::binary);
\r
142 ifs.seekg(0, std::ios::end);
\r
143 int length = ifs.tellg();
\r
144 ifs.seekg(0, std::ios::beg);
\r
145 char *buffer = new char[length + 1];
\r
146 ifs.read(buffer, length);
\r
148 buffer[length] = 0;
\r
149 std::string result(buffer);
\r
159 void load_level(int lvl) {
\r
160 map = read_map(lvl);
\r
162 for (int x = 0; x < WIDTH; x++) {
\r
163 for (int y = 0; y < HEIGHT; y++) {
\r
164 if (map[get_pos(x, y)] == 'S')
\r
165 player.move_to(x, y);
\r
173 PROCESS_INFORMATION pi;
\r
175 BOOL CALLBACK ew_cb(HWND hwnd, LPARAM lp) {
\r
177 DWORD tid = GetWindowThreadProcessId(hwnd, &pid);
\r
178 if (pi.dwProcessId == pid && pi.dwThreadId == tid) {
\r
179 hwnd_notepad = hwnd;
\r
184 BOOL CALLBACK ecw_cb(HWND child, LPARAM in) {
\r
185 char buffer[1024 + 1];
\r
186 int len = GetClassNameA(child, buffer, 1024);
\r
188 if (strcmp(buffer, "Edit") == 0) {
\r
195 void start_notepad() {
\r
196 ZeroMemory(&si, sizeof(si));
\r
197 si.cb = sizeof(si);
\r
198 ZeroMemory(&pi, sizeof(pi));
\r
200 if (!CreateProcessA(NULL, // No module name (use command line)
\r
201 "notepad.exe", // Command line
\r
202 NULL, // Process handle not inheritable
\r
203 NULL, // Thread handle not inheritable
\r
204 FALSE, // Set handle inheritance to FALSE
\r
205 0, // No creation flags
\r
206 NULL, // Use parent's environment block
\r
207 NULL, // Use parent's starting directory
\r
208 &si, // Pointer to STARTUPINFO structure
\r
209 &pi) // Pointer to PROCESS_INFORMATION structure
\r
211 printf("CreateProcess failed (%d).\n", GetLastError());
\r
214 EnumWindows(ew_cb, 0);
\r
215 EnumChildWindows(hwnd_notepad, ecw_cb, 0);
\r
216 SendMessage(hwnd_edit, EM_SETREADONLY, TRUE, NULL);
\r
218 void close_notepad() {
\r
219 TerminateProcess(pi.hProcess, 0);
\r
220 CloseHandle(pi.hProcess);
\r
221 CloseHandle(pi.hThread);
\r
235 bool key_state[(uint64_t)Key::COUNT];
\r
236 bool key_state_old[(uint64_t)Key::COUNT];
\r
238 int key_get_vk(Key key) {
\r
240 case Key::Left: return 'A';
\r
241 case Key::Right: return 'D';
\r
242 case Key::Jump: return VK_SPACE;
\r
243 case Key::Exit: return VK_ESCAPE;
\r
244 case Key::Redraw: return 'R';
\r
249 void update_key_state() {
\r
250 for (int i = 0; i < (int)Key::COUNT; i++) {
\r
251 key_state[i] = GetAsyncKeyState(key_get_vk((Key)i));
\r
255 void update_key_state_old() {
\r
256 for (int i = 0; i < (int)Key::COUNT; i++) {
\r
257 key_state_old[i] = key_state[i];
\r
261 bool key_pressed(Key key) {
\r
262 return key_state[(int)key] && !key_state_old[(int)key];
\r
265 bool key_down(Key key) {
\r
266 return key_state[(int)key];
\r
269 bool key_up(Key key) {
\r
270 return !key_state[(int)key];
\r
274 int main(int argc, char **argv) {
\r
276 int WinMain(HINSTANCE a0, HINSTANCE a1, LPSTR a2, int a3) {
\r
279 if (hwnd_notepad == NULL || hwnd_edit == NULL) {
\r
285 dt = ((double)clock() - game_clock) / CLOCKS_PER_SEC * 1000;
\r
286 game_clock = clock();
\r
287 update_key_state();
\r
289 if (key_pressed(Key::Exit))
\r
291 if (key_pressed(Key::Redraw))
\r
293 if (key_down(Key::Left) && !player.collision_x(-1))
\r
294 player.move(-1, 0);
\r
295 if (key_down(Key::Right) && !player.collision_x(1))
\r
296 player.move(+1, 0);
\r
297 if (key_pressed(Key::Jump) && player.collision_y(1))
\r
302 printf("%f %f\n", player.x, player.y);
\r
304 update_key_state_old();
\r