X-Git-Url: https://gitweb.ps.run/npengine/blobdiff_plain/e5d5a61b49a239558bbfac9809cd2a8e75f9a63e..HEAD:/src/main.cpp diff --git a/src/main.cpp b/src/main.cpp index f6d131b..61fda8f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -23,7 +24,16 @@ const int WIDTH = 56, HEIGHT = 29; std::string map; clock_t game_clock; -double dt; +double frame_time = 30; + +int lvl = 0; + +// Util + +double get_dur(clock_t then) { + double result = (double)(clock() - then) / CLOCKS_PER_SEC; + return result * 1000; +} // Edit @@ -32,13 +42,12 @@ HWND hwnd_edit = NULL; string get_text() { int len = SendMessageA(hwnd_edit, WM_GETTEXTLENGTH, 0, 0); - char *buffer = new char[len + 1]; - int read = SendMessageA(hwnd_edit, WM_GETTEXT, len + 1, (LPARAM)buffer); + string result; + result.resize(len + 1); + int read = SendMessageA(hwnd_edit, WM_GETTEXT, len + 1, (LPARAM)result.data()); if (read != len) puts("???"); - buffer[read] = 0; - string result(buffer); - delete[] buffer; + result.data()[read] = 0; return result; } @@ -59,7 +68,7 @@ void replace(string str) { } int get_pos(int x, int y) { - return (y + 1) * (WIDTH + 4) + x + 1; + return (y + 1) * (WIDTH + 3) + x + 1; } char get_block(int x, int y) { @@ -68,42 +77,27 @@ char get_block(int x, int y) { // Player struct Player { - int x_screen = -1, y_screen = -1; - double x, y, x_vel, y_vel; + bool left = false; + int x, y; + int x_spawn, y_spawn; + int jumping = 0; void clear() { - if (x_screen < 0 || y_screen < 0) return; - int pos = get_pos(x_screen, y_screen); + int pos = get_pos(x, y); select_length(pos, 1); replace({ map[pos], 0 }); } void draw() { - if (collision_x(x - x_screen) || collision_y(y - y_screen)) { - x = x_screen; - y = y_screen; - return; - } - x_screen = round(x); - y_screen = round(y); - int pos = get_pos(x_screen, y_screen); + int pos = get_pos(x, y); select_length(pos, 1); - replace({ 'Q', 0 }); - } - - void update() { - x += x_vel; - y += y_vel; - if (!collision_y(1) && y_vel < 9) - y_vel += 1; - if (abs(x - x_screen) >= 1 || abs(x - x_screen) >= 1) { - clear(); - draw(); - } + replace({ left ? '<' : '>', 0 }); } void move_to(int x, int y) { clear(); + if (this->x > x) left = true; + if (this->x < x) left = false; this->x = x; this->y = y; draw(); @@ -117,7 +111,7 @@ struct Player { if (x + n < 0 || x + n >= WIDTH) return true; for (int i = 0; i != n; i += (n < 0 ? -1 : 1)) - if (get_block(x_screen + i + (n < 0 ? -1 : 1), y_screen) == 'X') + if (get_block(x + i + (n < 0 ? -1 : 1), y) == 'X') return true; return false; } @@ -125,7 +119,7 @@ struct Player { if (y + n < 0 || y + n >= HEIGHT) return true; for (int i = 0; i != n; i += (n < 0 ? -1 : 1)) - if (get_block(x_screen, y_screen + i + (n < 0 ? -1 : 1)) == 'X') + if (get_block(x, y + i + (n < 0 ? -1 : 1)) == 'X') return true; return false; } @@ -147,22 +141,28 @@ std::string read_map(int lvl) { ifs.close(); buffer[length] = 0; std::string result(buffer); - delete buffer; + delete[] buffer; return result; } void redraw() { select_all(); replace(map); + player.draw(); } -void load_level(int lvl) { - map = read_map(lvl); +void load_level(int l) { + lvl = l; + map = read_map(l); redraw(); for (int x = 0; x < WIDTH; x++) { for (int y = 0; y < HEIGHT; y++) { - if (map[get_pos(x, y)] == 'S') + if (map[get_pos(x, y)] == 'S') { + player.x_spawn = x; + player.y_spawn = y; player.move_to(x, y); + return; + } } } } @@ -172,24 +172,10 @@ void load_level(int lvl) { STARTUPINFOA si; PROCESS_INFORMATION pi; -BOOL CALLBACK ew_cb(HWND hwnd, LPARAM lp) { - DWORD pid; - DWORD tid = GetWindowThreadProcessId(hwnd, &pid); - if (pi.dwProcessId == pid && pi.dwThreadId == tid) { - hwnd_notepad = hwnd; - return false; - } - return true; -} -BOOL CALLBACK ecw_cb(HWND child, LPARAM in) { - char buffer[1024 + 1]; - int len = GetClassNameA(child, buffer, 1024); - buffer[len] = 0; - if (strcmp(buffer, "Edit") == 0) { - hwnd_edit = child; - return false; - } - return true; +bool check_class(HWND hwnd, const char *name) { + char b[64]; + int n = GetClassNameA(hwnd, b, 64); + return (n && strncmp(b, name, n) == 0); } void start_notepad() { @@ -198,7 +184,7 @@ void start_notepad() { ZeroMemory(&pi, sizeof(pi)); if (!CreateProcessA(NULL, // No module name (use command line) - "notepad.exe", // Command line + "notepad.exe lvl/0.txt", // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE @@ -210,15 +196,44 @@ void start_notepad() { ) { printf("CreateProcess failed (%d).\n", GetLastError()); } - Sleep(100); - EnumWindows(ew_cb, 0); - EnumChildWindows(hwnd_notepad, ecw_cb, 0); + Sleep(1000); + EnumWindows([](HWND hwnd, LPARAM lp)->BOOL{ + if (check_class(hwnd, "Notepad")) { + *(HWND*)lp = hwnd; + return false; + } + return true; + }, (LPARAM)&hwnd_notepad); + EnumChildWindows(hwnd_notepad, [](HWND hwnd, LPARAM lp)->BOOL{ + printf("looking at %p\n", hwnd); + if (check_class(hwnd, "NotepadTextBox")) { + EnumChildWindows(hwnd, [](HWND hwnd, LPARAM lp)->BOOL{ + printf(" looking at %p\n", hwnd); + const size_t size = (WIDTH+4)*(HEIGHT+2); + char b[size]; + DWORD_PTR dwResult; + b[0] = 0; + SendMessageTimeoutA(hwnd, WM_GETTEXT, size, (LPARAM)b, + SMTO_ABORTIFHUNG, 100, &dwResult); + if (b[0] == '+') { + // TODO: check lvl + printf("%.*s.\n", size, b); + *(HWND*)lp = hwnd; + return false; + } + return true; + }, lp); + if (lp) return false; + } + return true; + }, (LPARAM)&hwnd_edit); SendMessage(hwnd_edit, EM_SETREADONLY, TRUE, NULL); } void close_notepad() { - TerminateProcess(pi.hProcess, 0); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + SendMessage(hwnd_edit, EM_SETREADONLY, FALSE, NULL); + //TerminateProcess(pi.hProcess, 0); + //CloseHandle(pi.hProcess); + //CloseHandle(pi.hThread); } // Keys @@ -270,6 +285,131 @@ bool key_up(Key key) { return !key_state[(int)key]; } +// Gameplay + +clock_t jump_clock = clock(); +int jump_height = 3; +double jump_time1 = 50; +double jump_time2 = 100; +int text_speed = 50; + +void update_play(bool can_jump = true, int x_min = 0, int x_max = WIDTH - 1) { + if (key_down(Key::Left) && + !player.collision_x(-1) && + player.x > x_min) + player.move(-1, 0); + if (key_down(Key::Right) && + !player.collision_x(1) && + player.x < x_max) + player.move(+1, 0); + + if (key_pressed(Key::Jump) && + can_jump && + player.jumping == 0 && + !player.collision_y(-1)) { + player.jumping = 1; + player.move(0, -1); + jump_clock = clock(); + } + if (player.jumping != 0) { + if (player.jumping < jump_height && get_dur(jump_clock) > jump_time1) { + if (!player.collision_y(-1)) { + player.move(0, -1); + player.jumping++; + jump_clock = clock(); + } else { + player.jumping = jump_height; + } + } else if (player.jumping == jump_height && get_dur(jump_clock) > jump_time2) { + player.jumping = 0; + } + } + if (!player.jumping && !player.collision_y(1)) + player.move(0, +1); + + char b = get_block(player.x, player.y); + if (b == '/' || b == '\\' || b == '<' || b == '>') + player.move_to(player.x_spawn, player.y_spawn); +} + +void print_text(int x, int y, string text, int delay) { + for (int i = 0; i < text.size(); i++) { + select_length(get_pos(x + i, y), 1); + replace(text.substr(i, 1)); + Sleep(delay); + } +} + +void intro() { + static int progress = 0; + switch (progress) { + case 0: + print_text(4, 2, "Move with A/D.", text_speed); + + progress++; + break; + case 1: + update_play(false); + if (player.x == 17) { + print_text(4, 4, "Jump with up.", text_speed); + print_text(4, 6, "Stand on x.", text_speed); + progress++; + } + break; + case 2: + update_play(); + if (player.x == 22) { + print_text(4, 8, "Collect ? for ???.", text_speed); + progress++; + } + break; + case 3: + update_play(true, 0, 33); + if (get_block(player.x, player.y) == '?') { + print_text(4, 10, "Avoid /\\.", text_speed); + progress++; + } + break; + case 4: + update_play(); + if (player.x == 39) { + print_text(4, 14, "Finish lvl by reaching O.", text_speed); + progress++; + } + break; + case 5: + update_play(); + if (get_block(player.x, player.y) == 'O') { + load_level(1); + } + break; + } +} + +void lvl1() { + static int progress = 0; + switch (progress) { + case 0: + print_text(4, 2, "Also avoid > and <.", text_speed); + progress++; + break; + case 1: + update_play(); + break; + } +} + +void update_game() { + switch (lvl) { + case 0: + intro(); + break; + case 1: + lvl1(); + break; + } +} + #ifdef CONSOLE int main(int argc, char **argv) { #else @@ -280,9 +420,12 @@ int WinMain(HINSTANCE a0, HINSTANCE a1, LPSTR a2, int a3) { puts("error"); return 1; } + load_level(0); + while (true) { - dt = ((double)clock() - game_clock) / CLOCKS_PER_SEC * 1000; + //dt = ((double)clock() - game_clock) / CLOCKS_PER_SEC * 1000; + if (get_dur(game_clock) < frame_time) continue; game_clock = clock(); update_key_state(); @@ -290,20 +433,12 @@ int WinMain(HINSTANCE a0, HINSTANCE a1, LPSTR a2, int a3) { break; if (key_pressed(Key::Redraw)) redraw(); - if (key_down(Key::Left) && !player.collision_x(-1)) - player.move(-1, 0); - if (key_down(Key::Right) && !player.collision_x(1)) - player.move(+1, 0); - if (key_pressed(Key::Jump) && player.collision_y(1)) - player.y_vel = -5; - - player.update(); - - printf("%f %f\n", player.x, player.y); + + update_game(); update_key_state_old(); } close_notepad(); return 0; -} \ No newline at end of file +}