ui.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. #include <SDL_error.h>
  2. #include <SDL_events.h>
  3. #include <SDL_mutex.h>
  4. #include <SDL_render.h>
  5. #include <SDL_stdinc.h>
  6. #include <SDL_video.h>
  7. #include <string.h>
  8. #include "ui.h"
  9. #define MAX_PATH_NUM 1024
  10. const char *resources = "/home/stone/Project/netscore/";
  11. // 绘制数字
  12. static void drawBigNumber(SDL_Renderer* renderer, SDL_Texture* numberTexture, int x, int y) {
  13. static const int NumberWidth = 344, NumberHeight = 573;
  14. SDL_Rect dstRect = {x, y, NumberWidth, NumberHeight};
  15. SDL_RenderCopy(renderer, numberTexture, NULL, &dstRect);
  16. }
  17. // 绘制数字
  18. static void drawSmallNumber(SDL_Renderer* renderer, SDL_Texture* numberTexture, int x, int y) {
  19. static const int NumberWidth = 290, NumberHeight = 484;
  20. SDL_Rect dstRect = {x, y, NumberWidth, NumberHeight};
  21. SDL_RenderCopy(renderer, numberTexture, NULL, &dstRect);
  22. }
  23. static void drawBox(SDL_Renderer* renderer, SDL_Texture* boxTexture, int x, int y) {
  24. static const int NumberWidth = 892, NumberHeight = 1044;
  25. SDL_Rect dstRect = {x, y, NumberWidth, NumberHeight};
  26. SDL_RenderCopy(renderer, boxTexture, NULL, &dstRect);
  27. }
  28. static void drawWin(SDL_Renderer* renderer, SDL_Texture* winTexture, int x, int y) {
  29. static const int NumberWidth = 639, NumberHeight = 193;
  30. SDL_Rect dstRect = {x, y, NumberWidth, NumberHeight};
  31. SDL_RenderCopy(renderer, winTexture, NULL, &dstRect);
  32. }
  33. static void drawNameTexture(struct Application *app, SDL_Texture *texture, int x, int y) {
  34. static const int NameWidth = 1120, NameHeight = 118;
  35. // 获取纹理的宽度和高度
  36. int textureWidth, textureHeight;
  37. SDL_QueryTexture(texture, NULL, NULL, &textureWidth, &textureHeight);
  38. // 计算居中显示时的位置
  39. int centerX = x + (NameWidth - textureWidth) / 2;
  40. int centerY = y + (NameHeight - textureHeight) / 2;
  41. // 创建目标矩形
  42. SDL_Rect dstRect = { centerX, centerY, textureWidth, textureHeight };
  43. SDL_RenderCopy(app->renderer, texture, NULL, &dstRect);
  44. }
  45. static SDL_Texture* loadTexture(struct Application *app, const char *path) {
  46. SDL_Surface* surface = IMG_Load(path);
  47. if (!surface) {
  48. return NULL;
  49. }
  50. SDL_Texture* texture = SDL_CreateTextureFromSurface(app->renderer, surface);
  51. SDL_FreeSurface(surface);
  52. return texture;
  53. }
  54. int initApplication(struct Application *app) {
  55. int i;
  56. app->ret = 0;
  57. app->errorString[0] = '\0';
  58. app->initialized = 0;
  59. app->window = NULL;
  60. app->winWidth = 0;
  61. app->winHeight = 0;
  62. app->renderer = NULL;
  63. app->bgTexture = NULL;
  64. for (i = 0; i < 10; i++)
  65. app->bigNumTextures[i] = NULL;
  66. for (i = 0; i < 10; i++)
  67. app->smallNumTextures[i] = NULL;
  68. app->nameFont = NULL;
  69. app->p1NameTexture = app->p2NameTexture = NULL;
  70. for (i = 0; i < 2; i++)
  71. app->p1WinTexture[i] = app->p2WinTexture[i] = NULL;
  72. app->scoreHighLightTexture[0] = app->scoreHighLightTexture[1] = NULL;
  73. app->p1Name[0] = '\0';
  74. app->p2Name[0] = '\0';
  75. app->roundNum = app->roundNumSt = app->roundNumNd = 0;
  76. app->p1Num = app->p1NumSt = app->p1NumNd = 0;
  77. app->p2Num = app->p2NumSt = app->p2NumNd = 0;
  78. app->p1Win = app->p2Win = 0;
  79. app->isKey = 0;
  80. app->updateRequire = 1;
  81. app->mutex = NULL;
  82. if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
  83. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: SDL_Init: %s", SDL_GetError());
  84. return -1;
  85. }
  86. app->initialized = 1;
  87. if (TTF_Init() == -1) {
  88. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: TTF_Init: %s", TTF_GetError());
  89. return -1;
  90. }
  91. app->window = SDL_CreateWindow("计分板", 0, 0, 3840, 1100, SDL_WINDOW_FULLSCREEN);
  92. if (!app->window) {
  93. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: SDL_CreateWindow: %s", SDL_GetError());
  94. return -1;
  95. }
  96. SDL_GetWindowSize(app->window, &app->winWidth, &app->winHeight);
  97. app->renderer = SDL_CreateRenderer(app->window, -1, SDL_RENDERER_ACCELERATED);
  98. if (!app->renderer) {
  99. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: SDL_CreateRenderer: %s", SDL_GetError());
  100. return -1;
  101. }
  102. // 加载背景图片
  103. {
  104. char path[MAX_PATH_NUM];
  105. snprintf(path, MAX_PATH_NUM, "%s%s%s", resources, "img/", "bg.png");
  106. SDL_Surface* surface = IMG_Load(path);
  107. if (!surface) {
  108. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load bg image %s: %s", path, IMG_GetError());
  109. return -1;
  110. }
  111. app->bgTexture = SDL_CreateTextureFromSurface(app->renderer, surface);
  112. SDL_FreeSurface(surface);
  113. }
  114. for (i = 0; i < 10; i++) {
  115. char path[MAX_PATH_NUM];
  116. snprintf(path, MAX_PATH_NUM, "%s%s/%d.png", resources, "img/big", i);
  117. app->bigNumTextures[i] = loadTexture(app, path);
  118. if (!app->bigNumTextures[i]) {
  119. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load big numer image %s: %s", path, IMG_GetError());
  120. return -1;
  121. }
  122. }
  123. for (i = 0; i < 10; i++) {
  124. char path[MAX_PATH_NUM];
  125. snprintf(path, MAX_PATH_NUM, "%s%s/%d.png", resources, "img/small", i);
  126. app->smallNumTextures[i] = loadTexture(app, path);
  127. if (!app->smallNumTextures[i]) {
  128. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load small numer image %s: %s", path, IMG_GetError());
  129. return -1;
  130. }
  131. }
  132. {
  133. char path[MAX_PATH_NUM];
  134. snprintf(path, sizeof(path), "%s%s%s", resources, "font/", "msyh.ttc");
  135. app->nameFont = TTF_OpenFont(path, 120);
  136. if (app->nameFont == NULL) {
  137. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load font path %s: %s", path, TTF_GetError());
  138. return -1;
  139. }
  140. }
  141. for (i = 0; i < 2; ++i) {
  142. char path[MAX_PATH_NUM];
  143. snprintf(path, sizeof(path), "%s%s%s_%d.png", resources, "img/", "box", i);
  144. app->scoreHighLightTexture[i] = loadTexture(app, path);
  145. if (!app->scoreHighLightTexture[i]) {
  146. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load box image %s: %s", path, IMG_GetError());
  147. return -1;
  148. }
  149. }
  150. for (i = 0; i < 2; ++i) {
  151. char path[MAX_PATH_NUM];
  152. snprintf(path, sizeof(path), "%s%s%s_%d.png", resources, "img/", "p1_win", i);
  153. app->p1WinTexture[i] = loadTexture(app, path);
  154. if (!app->p1WinTexture[i]) {
  155. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load p1_win image %s: %s", path, IMG_GetError());
  156. return -1;
  157. }
  158. snprintf(path, sizeof(path), "%s%s%s_%d.png", resources, "img/", "p2_win", i);
  159. app->p2WinTexture[i] = loadTexture(app, path);
  160. if (!app->p2WinTexture[i]) {
  161. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: Load p2_win image %s: %s", path, IMG_GetError());
  162. return -1;
  163. }
  164. }
  165. app->mutex = SDL_CreateMutex();
  166. if (app->mutex == NULL) {
  167. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: create mutex error: %s", SDL_GetError());
  168. return -1;
  169. }
  170. return 0;
  171. }
  172. void drawApplication(struct Application *app) {
  173. // 清空渲染器
  174. SDL_RenderClear(app->renderer);
  175. SDL_Color textColor = { 255, 255, 255 }; // 白色
  176. SDL_Surface* surface = NULL;
  177. {
  178. SDL_Surface* surface = NULL;
  179. if (strnlen(app->p1Name, sizeof(app->p1Name)) != 0) {
  180. surface = TTF_RenderUTF8_Solid(app->nameFont, app->p1Name, textColor);
  181. if (!surface) {
  182. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: create utf-8 surface error %s: %s", app->p1Name, TTF_GetError());
  183. }
  184. }
  185. if (app->p1NameTexture)
  186. SDL_DestroyTexture(app->p1NameTexture);
  187. app->p1NameTexture = NULL;
  188. if (surface) {
  189. app->p1NameTexture = SDL_CreateTextureFromSurface(app->renderer, surface);
  190. if (!app->p1NameTexture) {
  191. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: create texture error %s", SDL_GetError());
  192. }
  193. SDL_FreeSurface(surface);
  194. }
  195. }
  196. {
  197. if (strnlen(app->p2Name, sizeof(app->p2Name)) != 0) {
  198. surface = TTF_RenderUTF8_Solid(app->nameFont, app->p2Name, textColor);
  199. if (!surface) {
  200. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: create utf-8 surface error %s: %s", app->p2Name, TTF_GetError());
  201. }
  202. }
  203. if (app->p2NameTexture)
  204. SDL_DestroyTexture(app->p2NameTexture);
  205. app->p2NameTexture = NULL;
  206. if (surface) {
  207. app->p2NameTexture = SDL_CreateTextureFromSurface(app->renderer, surface);
  208. if (!app->p2NameTexture) {
  209. snprintf(app->errorString, sizeof(app->errorString), "[ERROR]: create texture error %s", SDL_GetError());
  210. }
  211. SDL_FreeSurface(surface);
  212. }
  213. }
  214. // 绘制背景图片
  215. SDL_RenderCopy(app->renderer, app->bgTexture, NULL, NULL);
  216. drawBox(app->renderer, app->scoreHighLightTexture[app->isKey], 1475, 29);
  217. if (app->p1NameTexture)
  218. drawNameTexture(app, app->p1NameTexture, 233, 136);
  219. if (app->p2NameTexture)
  220. drawNameTexture(app, app->p2NameTexture, 2490, 136);
  221. drawSmallNumber(app->renderer, app->smallNumTextures[app->roundNumSt], 1589, 409);
  222. drawSmallNumber(app->renderer, app->smallNumTextures[app->roundNumNd], 1962, 409);
  223. drawBigNumber(app->renderer, app->bigNumTextures[app->p1NumSt], 455, 317);
  224. drawBigNumber(app->renderer, app->bigNumTextures[app->p1NumNd], 896, 317);
  225. drawBigNumber(app->renderer, app->bigNumTextures[app->p2NumSt], 2600, 317);
  226. drawBigNumber(app->renderer, app->bigNumTextures[app->p2NumNd], 3041, 317);
  227. drawWin(app->renderer, app->p1WinTexture[app->p1Win], 528, 883);
  228. drawWin(app->renderer, app->p2WinTexture[app->p2Win], 2673, 883);
  229. SDL_RenderPresent(app->renderer);
  230. }
  231. void termApplication(struct Application *app) {
  232. if (app->initialized == 0)
  233. return;
  234. int i;
  235. if (app->mutex)
  236. SDL_DestroyMutex(app->mutex);
  237. for (i = 0; i < 2; i++)
  238. if (app->scoreHighLightTexture[i])
  239. SDL_DestroyTexture(app->scoreHighLightTexture[i]);
  240. for (i = 0; i < 2; i++) {
  241. if (app->p1WinTexture[i])
  242. SDL_DestroyTexture(app->p1WinTexture[i]);
  243. if (app->p2WinTexture[i])
  244. SDL_DestroyTexture(app->p2WinTexture[i]);
  245. }
  246. if (app->p1NameTexture)
  247. SDL_DestroyTexture(app->p1NameTexture);
  248. if (app->p2NameTexture)
  249. SDL_DestroyTexture(app->p2NameTexture);
  250. if (app->nameFont)
  251. TTF_CloseFont(app->nameFont);
  252. for (i = 0; i < 10; i++)
  253. if (app->smallNumTextures[i])
  254. SDL_DestroyTexture(app->smallNumTextures[i]);
  255. for (i = 0; i < 10; i++)
  256. if (app->bigNumTextures[i])
  257. SDL_DestroyTexture(app->bigNumTextures[i]);
  258. if (app->bgTexture)
  259. SDL_DestroyTexture(app->bgTexture);
  260. if (app->renderer)
  261. SDL_DestroyRenderer(app->renderer);
  262. if (app->window)
  263. SDL_DestroyWindow(app->window);
  264. if (TTF_WasInit())
  265. TTF_Quit();
  266. SDL_Quit();
  267. app->initialized = 0;
  268. }
  269. int updateApplicationMode(struct Application *app, uint8 isKey) {
  270. app->isKey = isKey;
  271. return 0;
  272. }
  273. int updateApplication(struct Application *app, const char *p1Name, const char *p2Name, int roundNum, int p1Score, int p2Score) {
  274. printf("%s, %s, %d, %d, %d\n", p1Name, p2Name, roundNum, p1Score, p2Score);
  275. SDL_LockMutex(app->mutex);
  276. if ((strcmp(p1Name, app->p1Name) == 0 && strcmp(p2Name, app->p2Name) == 0) ||
  277. (strcmp(p1Name, app->p2Name) == 0 && strcmp(p2Name, app->p1Name))) {
  278. if (p1Score - app->p1Num == 1 && p2Score == app->p2Num) {
  279. app->p1Win = 1;
  280. } else {
  281. app->p1Win = 0;
  282. }
  283. if (p1Score == app->p1Num && p2Score - app->p2Num == 1) {
  284. app->p2Win = 1;
  285. } else {
  286. app->p2Win = 0;
  287. }
  288. }
  289. if (p1Name != app->p1Name && strcmp(p1Name, app->p1Name) != 0 && strlen(p1Name) <= 30) {
  290. memset(app->p1Name, 0, sizeof(app->p1Name));
  291. strncpy(app->p1Name, p1Name, sizeof(app->p1Name) - 1);
  292. }
  293. if (p2Name != app->p2Name && strcmp(p2Name, app->p2Name) != 0 && strlen(p2Name) <= 30) {
  294. memset(app->p2Name, 0, sizeof(app->p2Name));
  295. strncpy(app->p2Name, p2Name, sizeof(app->p2Name) - 1);
  296. }
  297. app->roundNum = roundNum % 100;
  298. app->roundNumSt = (app->roundNum / 10) % 10;
  299. app->roundNumNd = app->roundNum % 10;
  300. app->p1Num = p1Score % 100;
  301. app->p1NumSt = (app->p1Num / 10) % 10;
  302. app->p1NumNd = app->p1Num % 10;
  303. app->p2Num = p2Score % 100;
  304. app->p2NumSt = (app->p2Num / 10) % 10;
  305. app->p2NumNd = app->p2Num % 10;
  306. SDL_UnlockMutex(app->mutex);
  307. app->updateRequire = 1;
  308. return 0;
  309. }
  310. /*
  311. int main() {
  312. struct Application myApp, *app = &myApp;
  313. if (initApplication(app)) {
  314. printf("初始化应用失败: %s\n", app->errorString);
  315. termApplication(app);
  316. return 0;
  317. }
  318. if (app->initialized) {
  319. updateApplication(app, "昵称最多有八个字", "昵称最多有八个字", 5, 6, 6);
  320. runApplication(app);
  321. }
  322. termApplication(app);
  323. return 0;
  324. }*/