#+TITLE: sdl2 org src #+AUTHOR: screwtape * Rich media sdl2 C applications (skip past window settings in your reading; they are just better at the top) ** Various updates Now has odd inline | SDL_HasIntersection(SDL_Rect *, SDL_Rect *) | | SDL_IntersectRectAndLine(SDL_Rect *, int *x0, int *y0, int *x1, int *y1 | | Array of SDL_Rect rocks being used somehow | Note that SDL_IntersectRectAndLine clobbers intersected endpoint int *s. both intersections should be compared with SDL_TRUE / SDL_FALSE. ** Window settings #+NAME: w-sizing #+HEADER: :includes "/usr/local/include/SDL2/SDL.h" #+begin_src C SDL_WINDOW_RESIZABLE #+end_src #+NAME: w-height #+begin_src C 768 #+end_src #+NAME: w-width #+begin_src C 1280 #+end_src ** template #+BEGIN_EXAMPLE This template does seem a little bit goto cleanup rather than some clunky long, but that is because it handles quit flag; but then, it was easier keyboard and mouse events and mouse to goto quit which gotos cleanup. At position in the general case. I do least the loop isn't goto based! #+END_EXAMPLE includes and libs might need to be customized. I found that my sdl2-config flags on arm64 openbsd didn't actually work! #+name: template #+HEADER: :includes "/usr/local/include/SDL2/SDL.h" <stdlib.h> #+HEADER: :libs "-L/usr/local/lib -lSDL2" #+HEADER: :exports code #+HEADER: :results none #+HEADER: :noweb yes #+begin_src C <<hero-init>> /* random */ int ra, rb; time_t rt; srand((unsigned)time(&rt)); /* /rand */ /* Some rocks */ int NROCKS = 2; int r; struct SDL_Rect rocks[NROCKS]; rocks[0].x = 100; rocks[0].y = 120; rocks[0].w = 50; rocks[0].h = 40; rocks[1].x = 200; rocks[1].y = 220; rocks[1].w = 50; rocks[1].h = 40; /* Sort of clock */ int cycle_limit = 10000; int cycle_now = 0; /* spinning animation */ int ticks = 0; int tox, toy, centerx, centery; float xoff=0.0, yoff=0.0, l; int hitx, hity, hitcx, hitcy; centerx = 635; centery = 384; l = 100.0; /*/spinning animation */ <<sdlstart>> for(;;){ while(SDL_PollEvent(&e)) if (e.type == SDL_QUIT) quit: goto cleanup; else if (e.type == SDL_MOUSEBUTTONDOWN) switch (1){ default: break; } else if (e.type == SDL_MOUSEBUTTONUP) switch (1){ default: break; } else if (e.type == SDL_KEYDOWN) switch (e.key.keysym.sym){ case SDLK_UP: if (hero.alive == 1) hero.rect.y -= 10; for (r=0;r<NROCKS; r++) if (SDL_TRUE == SDL_HasIntersection(&(hero.rect),&(rocks[r]))) hero.rect.y += 10; break; case SDLK_RIGHT: if (hero.alive == 1) hero.rect.x += 10; break; case SDLK_DOWN: if (hero.alive == 1) hero.rect.y += 10; break; case SDLK_LEFT: if (hero.alive == 1) hero.rect.x -= 10; break; case SDLK_r: hero.rect.x = rand() % 1000; hero.rect.y = rand() % 500; hero.alive = 1; break; case SDLK_q: goto quit; default: break; } else if (e.type == SDL_KEYUP) switch (1){ default: break; } mdown = SDL_GetMouseState(&mx, &my); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); <<hero-update>> SDL_SetRenderDrawColor(renderer, 100, 200, 200, 255); /* spinning animation */ ticks++; xoff= l * SDL_sin((float)ticks / (2.0 * M_PI)); tox = centerx + (int)xoff; yoff= l * SDL_cos((float)ticks / (2.0 * M_PI)); toy = centery + (int)yoff; SDL_RenderDrawLine(renderer, centerx, centery, tox, toy); /*/spinning animation */ /* Potentially kill hero */ hitcx = centerx; hitcy = centery; hitx = tox; hity = toy; if (hero.alive== 1 && SDL_IntersectRectAndLine(&(hero.rect), &hitcx, &hitcy, &hitx, &hity) == SDL_TRUE) hero.alive=0; /* Potentially killed hero */ /* Draw rocks */ SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255); for (r=0; r<NROCKS; r++) SDL_RenderFillRect(renderer, &rocks[r]); /* Drawn rocks */ SDL_RenderPresent(renderer); SDL_Delay(25); if ((cycle_now+=25) < cycle_limit) { if (cycle_now < (cycle_limit / 2)) centerx--; else centerx++; } else { cycle_now = 0; } } cleanup: <<sdlcleanup>> #+end_src ** My macros *** Hero **** Hero init #+name: hero-init #+begin_src C struct hero{ int xpos, ypos, width, height, r, g, b, a, speed, alive; SDL_Rect rect; } hero; SDL_Event e; int mx, my; Uint32 mdown; hero.alive = 1; hero.rect.x=100; hero.rect.y=200; hero.rect.w=50; hero.rect.h=60; hero.r = 30; hero.g = 60; hero.b = 90; hero.a = 255; hero.speed = 10; #+end_src **** Hero update #+name: hero-update #+begin_src C if(hero.alive == 1) SDL_SetRenderDrawColor(renderer, hero.r, hero.g, hero.b, hero.a); else SDL_SetRenderDrawColor(renderer, 255, 0, 0, hero.a); SDL_RenderFillRect(renderer, &(hero.rect)); #+end_src ** Simple SDL2, window, renderer init #+NAME: sdlstart #+HEADER: :noweb yes #+begin_src C SDL_Window *window; SDL_Renderer *renderer; if (SDL_Init(SDL_INIT_VIDEO) < 0){ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to init SDL: %s", SDL_GetError()); return 3; } if (SDL_CreateWindowAndRenderer(<<w-width>>, <<w-height>>, <<w-sizing>>, &window, &renderer)){ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create renderer and window: %s", SDL_GetError()); return 3; } #+end_src ** Simple SDL2 cleanup #+NAME: sdlcleanup #+begin_src C SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; #+end_src