| #if defined(_WIN32) && !defined(WIN32) |
| #define WIN32 |
| #endif |
| |
| #ifdef __EMSCRIPTEN__ |
| #include <emscripten/emscripten.h> |
| #endif |
| |
| #include "SDL.h" |
| #include <iostream> |
| |
| #include "Input.hpp" |
| #include "Multiplayer.hpp" |
| #include "System.hpp" |
| #include "Renderer.hpp" |
| #include "Audio.hpp" |
| #include "UserCode.hpp" |
| |
| #include "contrib.hpp" |
| |
| #ifdef VIDEO_CAPTURE |
| #include "VideoCapture.hpp" |
| #endif |
| |
| static bool running = true; |
| |
| SDL_Window* window = nullptr; |
| |
| System *blit_system; |
| Input *blit_input; |
| Multiplayer *blit_multiplayer; |
| Renderer *blit_renderer; |
| Audio *blit_audio; |
| |
| const char *launch_path = nullptr; |
| |
| #ifdef VIDEO_CAPTURE |
| VideoCapture *blit_capture; |
| unsigned int last_record_startstop = 0; |
| #endif |
| |
| void handle_event(SDL_Event &event) { |
| switch (event.type) { |
| case SDL_QUIT: |
| running = false; |
| break; |
| |
| case SDL_WINDOWEVENT: |
| if (event.window.event == SDL_WINDOWEVENT_RESIZED) { |
| blit_renderer->resize(event.window.data1, event.window.data2); |
| } |
| break; |
| |
| case SDL_MOUSEBUTTONUP: |
| case SDL_MOUSEBUTTONDOWN: |
| blit_input->handle_mouse(event.button.button, event.type == SDL_MOUSEBUTTONDOWN, event.button.x, event.button.y); |
| break; |
| |
| case SDL_MOUSEMOTION: |
| if (event.motion.state & SDL_BUTTON_LMASK) { |
| blit_input->handle_mouse(SDL_BUTTON_LEFT, event.motion.state & SDL_MOUSEBUTTONDOWN, event.motion.x, event.motion.y); |
| } |
| break; |
| |
| case SDL_KEYDOWN: // fall-though |
| case SDL_KEYUP: |
| if (!blit_input->handle_keyboard(event.key.keysym.sym, event.type == SDL_KEYDOWN)) { |
| #ifdef VIDEO_CAPTURE |
| switch (event.key.keysym.sym) { |
| case SDLK_r: |
| if (event.type == SDL_KEYDOWN && SDL_GetTicks() - last_record_startstop > 1000) { |
| if (blit_capture->recording()) blit_capture->stop(); |
| else blit_capture->start(); |
| last_record_startstop = SDL_GetTicks(); |
| } |
| } |
| #endif |
| } |
| break; |
| |
| case SDL_CONTROLLERBUTTONDOWN: |
| case SDL_CONTROLLERBUTTONUP: |
| blit_input->handle_controller_button(event.cbutton.button, event.type == SDL_CONTROLLERBUTTONDOWN); |
| break; |
| |
| case SDL_CONTROLLERAXISMOTION: |
| blit_input->handle_controller_motion(event.caxis.axis, event.caxis.value); |
| break; |
| |
| case SDL_CONTROLLERDEVICEADDED: |
| blit_input->handle_controller_added(event.cdevice.which); |
| break; |
| |
| case SDL_CONTROLLERDEVICEREMOVED: |
| blit_input->handle_controller_removed(event.cdevice.which); |
| break; |
| |
| #if SDL_VERSION_ATLEAST(2, 0, 14) |
| case SDL_CONTROLLERSENSORUPDATE: |
| if(event.csensor.sensor == SDL_SENSOR_ACCEL) |
| blit_input->handle_controller_accel(event.csensor.data); |
| break; |
| #endif |
| |
| case SDL_RENDER_TARGETS_RESET: |
| std::cout << "Targets reset" << std::endl; |
| break; |
| |
| case SDL_RENDER_DEVICE_RESET: |
| std::cout << "Device reset" << std::endl; |
| break; |
| |
| default: |
| if(event.type == System::loop_event) { |
| blit_renderer->update(blit_system); |
| blit_system->notify_redraw(); |
| blit_renderer->present(); |
| #ifdef VIDEO_CAPTURE |
| if (blit_capture->recording()) blit_capture->capture(blit_renderer); |
| #endif |
| } else if (event.type == System::timer_event) { |
| switch(event.user.code) { |
| case 0: |
| SDL_SetWindowTitle(window, metadata_title); |
| break; |
| case 1: |
| SDL_SetWindowTitle(window, (std::string(metadata_title) + " [SLOW]").c_str()); |
| break; |
| case 2: |
| SDL_SetWindowTitle(window, (std::string(metadata_title) + " [FROZEN]").c_str()); |
| break; |
| } |
| } |
| break; |
| } |
| } |
| |
| #ifdef __EMSCRIPTEN__ |
| void em_loop() { |
| SDL_Event event; |
| while (SDL_PollEvent(&event)) { |
| handle_event(event); |
| } |
| |
| blit_multiplayer->update(); |
| blit_system->loop(); |
| blit_renderer->update(blit_system); |
| blit_renderer->present(); |
| } |
| #endif |
| |
| int main(int argc, char *argv[]) { |
| int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED; |
| bool fullscreen = false; |
| |
| std::cout << metadata_title << " " << metadata_version << std::endl; |
| std::cout << "Powered by 32Blit SDL2 runtime - github.com/32blit/32blit-sdk" << std::endl << std::endl; |
| |
| auto mp_mode = Multiplayer::Mode::Auto; |
| std::string mp_address = "localhost"; |
| |
| for(int i = 1; i < argc; i++) { |
| std::string arg_str(argv[i]); |
| if(arg_str == "--connect" && i + 1 < argc) { |
| mp_mode = Multiplayer::Mode::Connect; |
| mp_address = std::string(argv[i + 1]); |
| i++; |
| } |
| else if(arg_str == "--launch_path" && i + 1 < argc) { |
| launch_path = argv[++i]; |
| } |
| else if(arg_str == "--listen") |
| mp_mode = Multiplayer::Mode::Listen; |
| else if(arg_str == "--position") { |
| SDL_sscanf(argv[i+1], "%d,%d", &x, &y); |
| } else if(arg_str == "--size" && i + 1 < argc) { |
| int w, h; |
| if(SDL_sscanf(argv[i+1], "%d,%d", &w, &h) == 2) { |
| if(w * y < System::max_width * System::max_height) { |
| System::width = w; |
| System::height = h; |
| } |
| } |
| i++; |
| } else if(arg_str == "--fullscreen") |
| fullscreen = true; |
| else if(arg_str == "--credits") { |
| std::cout << "32Blit was made possible by:" << std::endl; |
| std::cout << std::endl; |
| for(auto name : contributors) { |
| if(name != nullptr) { |
| std::cout << " * " << name << std::endl; |
| } |
| } |
| std::cout << std::endl; |
| std::cout << "Special thanks to:" << std::endl; |
| std::cout << std::endl; |
| for(auto name : special_thanks) { |
| if(name != nullptr) { |
| std::cout << " * " << name << std::endl; |
| } |
| } |
| std::cout << std::endl; |
| SDL_Quit(); |
| return 0; |
| } |
| else if(arg_str == "--info") { |
| std::cout << metadata_description << std::endl << std::endl; |
| std::cout << " Category: " << metadata_category << std::endl; |
| std::cout << " Author: " << metadata_author << std::endl; |
| std::cout << " URL: " << metadata_url << std::endl << std::endl; |
| SDL_Quit(); |
| return 0; |
| } |
| else if(arg_str == "--help") { |
| std::cout << "Usage: " << argv[0] << " <options>" << std::endl << std::endl; |
| std::cout << " --connect <addr> -- Connect to a listening game instance." << std::endl; |
| std::cout << " --listen -- Listen for incoming connections." << std::endl; |
| std::cout << " --position x,y -- Set window position." << std::endl; |
| std::cout << " --size w,h -- Set display size. (max 320x240)" << std::endl; |
| std::cout << " --launch_path <file> -- Emulates the file associations on the console." << std::endl; |
| std::cout << " --credits -- Print contributor credits and exit." << std::endl; |
| std::cout << " --info -- Print metadata info and exit." << std::endl << std::endl; |
| SDL_DestroyWindow(window); |
| SDL_Quit(); |
| return 0; |
| } |
| } |
| |
| if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_GAMECONTROLLER|SDL_INIT_AUDIO) < 0) { |
| std::cerr << "could not initialize SDL2: " << SDL_GetError() << std::endl; |
| return 1; |
| } |
| |
| window = SDL_CreateWindow( |
| metadata_title, |
| x, y, |
| System::width*2, System::height*2, |
| SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0) |
| ); |
| |
| if (window == nullptr) { |
| std::cerr << "could not create window: " << SDL_GetError() << std::endl; |
| return 1; |
| } |
| SDL_SetWindowMinimumSize(window, System::width, System::height); |
| |
| blit_system = new System(); |
| blit_input = new Input(blit_system); |
| blit_multiplayer = new Multiplayer(mp_mode, mp_address); |
| blit_renderer = new Renderer(window, System::width, System::height); |
| blit_audio = new Audio(); |
| |
| #ifdef VIDEO_CAPTURE |
| blit_capture = new VideoCapture(argv[0]); |
| #endif |
| |
| blit_system->run(); |
| |
| #ifdef __EMSCRIPTEN__ |
| emscripten_set_main_loop(em_loop, 0, 1); |
| #else |
| SDL_Event event; |
| |
| while (running && SDL_WaitEvent(&event)) { |
| handle_event(event); |
| } |
| #endif |
| |
| if (running) { |
| std::cerr << "Main loop exited with error: " << SDL_GetError() << std::endl; |
| running = false; // ensure timer thread quits |
| } |
| |
| #ifdef VIDEO_CAPTURE |
| if (blit_capture->recording()) blit_capture->stop(); |
| delete blit_capture; |
| #endif |
| |
| blit_system->stop(); |
| delete blit_system; |
| delete blit_input; |
| delete blit_multiplayer; |
| delete blit_renderer; |
| |
| SDL_DestroyWindow(window); |
| SDL_Quit(); |
| return 0; |
| } |