Starter project for SDL2.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
4.7 KiB

  1. #include <SDL.h>
  2. #include <stdbool.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <minIni.h>
  6. const char* APP_NAME = "SDL2";
  7. static const unsigned char CONTROLS = 16;
  8. static const unsigned char PLAYERS = 1;
  9. static const SDL_KeyCode KEYBOARD_CONTROLS[CONTROLS] = {
  10. SDLK_RIGHT,
  11. SDLK_DOWN,
  12. SDLK_LEFT,
  13. SDLK_UP,
  14. SDLK_RETURN, // yes
  15. SDLK_BACKSPACE, // no
  16. SDLK_a, // action0
  17. SDLK_s, // action1
  18. SDLK_d, // action2
  19. SDLK_f, // action3
  20. SDLK_z, // action4
  21. SDLK_x, // action5
  22. SDLK_c, // action6
  23. SDLK_v, // action7
  24. SDLK_w, // action8
  25. SDLK_e, // action9
  26. };
  27. static const char* ACTION_NAMES[CONTROLS] = {
  28. "Right",
  29. "Down",
  30. "Left",
  31. "Up",
  32. "Affirm",
  33. "Negate",
  34. "Action0",
  35. "Action1",
  36. "Action2",
  37. "Action3",
  38. "Action4",
  39. "Action5",
  40. "Action6",
  41. "Action7",
  42. "Action8",
  43. "Action9",
  44. };
  45. typedef struct {
  46. unsigned int width;
  47. unsigned int height;
  48. } IZ_VideoConfig;
  49. typedef SDL_KeyCode IZ_KeyCode;
  50. typedef int IZ_PadButton;
  51. typedef struct {
  52. IZ_KeyCode keyboard[CONTROLS];
  53. IZ_PadButton gamepad[CONTROLS];
  54. } IZ_ControlsConfig;
  55. typedef struct {
  56. IZ_VideoConfig video;
  57. IZ_ControlsConfig controls[PLAYERS];
  58. } IZ_Config;
  59. static void IZ_GetConfigPath(char* config_path) {
  60. //const char* config_path_dir = SDL_GetPrefPath("Modal Studios", APP_NAME);
  61. const char* config_path_dir = SDL_GetBasePath();
  62. memcpy_s(config_path, 128, config_path_dir, 128);
  63. strcat_s(config_path, 128, "config.ini");
  64. }
  65. static void IZ_SaveConfig(IZ_Config* config) {
  66. static char config_path[128];
  67. IZ_GetConfigPath(config_path);
  68. FILE* fp;
  69. fopen_s(&fp, config_path, "w");
  70. fprintf_s(fp, "[Video]\n");
  71. fprintf_s(fp, "Width=%u\n", config->video.width);
  72. fprintf_s(fp, "Height=%u\n", config->video.height);
  73. fprintf_s(fp, "\n");
  74. for (unsigned int p = 0; p < PLAYERS; p += 1) {
  75. fprintf_s(fp, "[Controls.%u.Keyboard]\n", p);
  76. for (unsigned int i = 0; i < CONTROLS; i += 1) {
  77. fprintf_s(fp, "%s=%s\n", ACTION_NAMES[i], SDL_GetKeyName(config->controls[p].keyboard[i]));
  78. }
  79. }
  80. }
  81. static void IZ_LoadConfig(IZ_Config* config) {
  82. static char config_path[128];
  83. IZ_GetConfigPath(config_path);
  84. // TODO check if file exists first
  85. config->video.width = ini_getl("Video", "Width", 640l, config_path);
  86. config->video.height = ini_getl("Video", "Height", 480l, config_path);
  87. char buffer[128];
  88. for (int i = 0; i < CONTROLS; i += 1) {
  89. ini_gets("Controls.0.Keyboard", ACTION_NAMES[i], SDL_GetKeyName(KEYBOARD_CONTROLS[i]), buffer, 128, config_path);
  90. config->controls[0].keyboard[i] = SDL_GetKeyFromName(buffer);
  91. }
  92. }
  93. int main(int argc, char* args[]) {
  94. SDL_Window* window = NULL;
  95. SDL_Surface* screen_surface = NULL;
  96. IZ_Config config;
  97. IZ_LoadConfig(&config);
  98. IZ_SaveConfig(&config);
  99. if (SDL_Init(
  100. SDL_INIT_VIDEO
  101. | SDL_INIT_GAMECONTROLLER
  102. | SDL_INIT_EVENTS
  103. ) < 0) {
  104. printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
  105. return -1;
  106. }
  107. window = SDL_CreateWindow(
  108. APP_NAME,
  109. SDL_WINDOWPOS_CENTERED,
  110. SDL_WINDOWPOS_CENTERED,
  111. config.video.width,
  112. config.video.height,
  113. SDL_WINDOW_SHOWN
  114. );
  115. if (window == NULL) {
  116. printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
  117. return -2;
  118. }
  119. bool quit = false;
  120. SDL_Event e;
  121. screen_surface = SDL_GetWindowSurface(window);
  122. unsigned short action = 0;
  123. while (!quit) {
  124. SDL_FillRect(screen_surface, NULL, SDL_MapRGB(screen_surface->format, 0x00, 0x00, 0x00));
  125. uint64_t ticks = SDL_GetTicks64();
  126. for (unsigned char i = 0; i < 64; i += 1) {
  127. const unsigned char column = (64 - i) % 32;
  128. const unsigned char row = i / 32;
  129. const uint64_t bitflag = (0x1lu << i);
  130. const unsigned char size = 4;
  131. if (ticks & bitflag) {
  132. SDL_FillRect(screen_surface, &(SDL_Rect) {
  133. column * size,
  134. config.video.height - ((row + 1) * size),
  135. size,
  136. size
  137. }, SDL_MapRGB(screen_surface->format, 0x00, 0xff, 0xff));
  138. }
  139. }
  140. while (SDL_PollEvent(&e) != 0) {
  141. if (e.type == SDL_QUIT) {
  142. quit = true;
  143. }
  144. for (unsigned char i = 0; i < CONTROLS; i += 1) {
  145. // TODO do same for gamepad
  146. if (e.key.keysym.sym == config.controls[0].keyboard[i]) {
  147. const unsigned short bitflag = (0x1 << i);
  148. if (e.type == SDL_KEYDOWN) {
  149. action |= bitflag;
  150. } else if (e.type == SDL_KEYUP) {
  151. action &= ~bitflag;
  152. }
  153. }
  154. }
  155. for (unsigned char i = 0; i < CONTROLS; i += 1) {
  156. const unsigned char column = i % 4;
  157. const unsigned char row = i / 4;
  158. const unsigned short bitflag = (0x1 << i);
  159. const unsigned char size = 4;
  160. if (action & bitflag) {
  161. SDL_FillRect(screen_surface, &(SDL_Rect) {
  162. column * size,
  163. row * size,
  164. size,
  165. size
  166. }, SDL_MapRGB(screen_surface->format, 0xff, 0xff, 0x00));
  167. }
  168. }
  169. SDL_UpdateWindowSurface(window);
  170. }
  171. }
  172. SDL_DestroyWindow(window);
  173. SDL_Quit();
  174. return 0;
  175. }