chapter17-creating_game_window_with_sdl2.txt 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. ============================================
  2. Chapter 17: creating a game window with SDL2
  3. ============================================
  4. What you need to know before you read this:
  5. * Linux: text editors
  6. * Git: repositories
  7. * Git: clone
  8. * Git: commits
  9. * Git: checkout
  10. * C programming: variables
  11. * C programming: functions
  12. * C programming: function arguments
  13. * C programming: strings
  14. * C programming: enum
  15. * C programming: typedef
  16. * C programming: struct
  17. * C programming: whitespace
  18. * C preprocessor: #include
  19. * C statements: return
  20. * GCC: compile a program
  21. * GCC: link to external library
  22. * GCC: preprocessor
  23. * SDL2: SDL_Delay
  24. What this chapter will teach you:
  25. * Math: convert binary to decimal
  26. * C programming: unsigned integers
  27. * C operatators: bitwise
  28. * SDL2: SDL_CreateWindow
  29. * SDL2: Uint32
  30. Projects worked on:
  31. * Cuterald
  32. Repo: http://hqetojnktk6trragksiuszsodbuszhmekulsbtp2bfumvh3i7sfiyoyd.onion:80/Maple/cuterald.git
  33. Current commit: a8473aa557604daa8322d06aaa1ad6c93348486b
  34. Section I: chapter introduction
  35. -------------------------------
  36. Two chapters ago, before we took a detour into enums and structs, we linked to SDL2 and used one of
  37. the functions it provides - SDL_Delay. I showed you where the files are and what the process is of
  38. actually getting a C library ready for use. But we didn't really do anything useful in our program
  39. itself.
  40. We'll fix it in this chapter. Now that we're properly linked, we can use everything that SDL2
  41. provides without any additional effort, so getting a window on the screen will be a breeze.
  42. As usual, we continue with the code as we last left it. If you didn't follow along with the last
  43. chapter on Cuterald, or you want to have some working reference to compare to, check out the git
  44. repository listed above, and checkout the given commit. If you forgot how to do so, take a look at
  45. section I of chapter 15 for a brief refresher.
  46. Section II: SDL_CreateWindow example
  47. ------------------------------------
  48. I found that the approach of showing you some code and then explaining it line by line works quite
  49. well, so we'll be doing the same here. Don't try to copy over the code below into your program yet,
  50. as I'll walk you through it through the chapter.
  51. Here's an example on how to create a window in SDL2:
  52. ----------------------------------- [ example ] ---
  53. SDL_Window *window = SDL_CreateWindow (
  54. "Example SDL2 application",
  55. SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
  56. 1280,720,
  57. SDL_WINDOW_RESIZABLE
  58. );
  59. ---------------------------------------------------
  60. I've mentioned it a few times but never fully explained it, so it's worth repeating - C is very
  61. flexible with where you leave whitespace. If you're coming from a language like Python, this may
  62. seem very foreign and perhaps even 'wrong', but you've got the freedom to put newlines and spaces
  63. wherever you see fit. The only exceptions I can think of are after preprocessor commands (like
  64. #include) and of course inside of strings. I've used whitespace here to group function arguments
  65. in what feels like it should logically be together.
  66. Section III: SDL_CreateWindow parameters
  67. ----------------------------------------
  68. You can find the documentation for SDL_CreateWindow here: https://wiki.libsdl.org/SDL_CreateWindow
  69. I'll explain everything in this chapter, but take a moment to look at the page anyway. You should
  70. start to get into the habit of reading and using documentation, and the way to start is by just
  71. exploring it and getting comfortable with it.
  72. SDL_CreateWindow takes six parameters and returns a pointer to a variable of type SDL_Window.
  73. Don't worry yet about what pointers are, you don't need to understand them right now. Just
  74. remember that for the rest of the chapter, we'll use a variable called *window of type SDL_Window.
  75. SDL_Window is a type that SDL2 provides. While writing this, I checked the SDL2 include files to see
  76. what type it is exactly, but it looks like it's hidden from us. Which is fair, you don't really need
  77. to do anything to it directly - we'll just pass our window variable around to different functions
  78. that ask for it.
  79. Anyway, here's the declaration for SDL_CreateWindow, which I copied from the documentation I linked
  80. you to:
  81. ----------------------------- [ reference ] ---
  82. SDL_Window* SDL_CreateWindow(const char* title,
  83. int x,
  84. int y,
  85. int w,
  86. int h,
  87. Uint32 flags)
  88. -----------------------------------------------
  89. 1: const char* title
  90. Title for the window
  91. This is the text that appears on top of the window, usually to the left of the minimize,
  92. maximize and close buttons. Every window has a title like this, including the application
  93. you're using to read this. If you're reading from a shell, you'll probably see the command
  94. and/or directory you're running, and a browser will give you the title of the page.
  95. const char* is somewhat new. char* you know - that's just a string. const I'll explain
  96. shortly.
  97. 2,3: int x, int y
  98. Screen position where the window should be
  99. These are the coordinates of where the top left corner of your window will be, expressed in
  100. pixels. That's x pixels from the left side of the screen, and y pixels down. In the example in
  101. Section II I've instead passed SDL_WINDOWPOS_CENTERED, which the documentation recommends.
  102. It's a value that SDL2 defines, and maps to some magic value (that I didn't bother to check
  103. because there's no reason to know) that SDL2 recognizes as being a different behavior.
  104. 4,5: int w, int h
  105. Size of the window
  106. These are the width (horizontal) and height (vertical) of the window in pixels, not including
  107. any border decoration. This defines how much room you're giving yourself to draw in.
  108. You can put any trivial numbers in here, but I've gone with 1280x720, which is the standard
  109. HD (720p) resolution.
  110. Wikipedia has a pretty neat graph listing a number of resolutions for different purposes:
  111. https://upload.wikimedia.org/wikipedia/commons/0/0c/Vector_Video_Standards8.svg
  112. And you can also check your own display settings to see what would work well on your computer.
  113. 6: Window flags
  114. Flags are a very common way to switch on and off different features for anything you may
  115. create or call in any C (or other) program. In the example I'm passing a single enum value,
  116. but you can also pass multiple at the same time with bitwise operators, which I'll cover later
  117. in this chapter.
  118. If you want to test it in your program right now, then #include the SDL2/SDL_video.h header file and
  119. plop this call just above your SDL_Delay line. If you put it after, the window will still be
  120. created, but it'll be destroyed again when your program exits, which makes your window a "blink and
  121. you'll miss it" phantom. Make sure to pass -lSDL2 when you compile it.
  122. Section IV: the const modifier
  123. ------------------------------
  124. In the example code above, you saw this as one of the arguments to SDL_CreateWindow:
  125. const char* title
  126. That is what we call a "const modifier", which is one of the items that we said we were going to
  127. cover later. For now, know that const tells the compiler that the value should not change after
  128. being assigned.
  129. However, because this particular variable is a C string it actually *is* possible to change it,
  130. because the const here applies to the pointer (see the '*'?) rather than the text itself.
  131. So in this context it behaves the same way as a regular char*, other than some optimizations
  132. happening in the compiler, and adding some minor safeties. It's usually a good idea to mark
  133. variables as const if you don't expect them to change. When we actually come across such a
  134. case, we will explore it in more detail.
  135. Section V: unsigned integer
  136. ---------------------------
  137. Another interesting item variable is flags:
  138. Uint32 flags
  139. In the last chapter we talked about creating custom types. One of the approaches is typedef, which
  140. is exactly what is used to create Uint32. I did some digging in SDL2 code for this chapter, and
  141. I'll spare you from having through any of the code yourself.
  142. Here is the line in the SDL2 code that creates Uint32:
  143. typedef uint32_t Uint32;
  144. And uint32_t is part of the standard C library. You can find a reference for the header that
  145. defines it here:
  146. https://www.cplusplus.com/reference/cstdint/
  147. "Unsigned" is another concept you haven't really learned. It's similar to a variable modifier, like
  148. const, and it applies only to numbers. It makes it so that the number can't go negative, which gives
  149. you one extra bit to store the actual number with, which means you can store numbers twice as high
  150. as what a "normal" (signed) integer would have allowed.
  151. Section VI: binary to decimal
  152. -----------------------------
  153. If you check the documentation again for SDL_CreateWindow, you'll see in the Remarks section that
  154. you can pass multiple enum (which you learned last chapter) values. However, you can't pass them as
  155. separate arguments - they all have to be passed simultaneously. And it's not an array either, the
  156. variable would be decorated with pointer ('*') or array ('[]') syntax.
  157. The trick to understanding this requires that we dive a bit into binary. As you may remember when we
  158. covered variables, everything in a C program is stored in binary, and the variable data type defines
  159. how it's actually read and presented to you. You may see numbers and characters and text and colors
  160. and pixels, but in memory everything is ones and zeroes no exceptions.
  161. Here are some quick examples of what decimal numbers look like in binary:
  162. decimal number | binary number ( 1 byte )
  163. -----------------------------------------
  164. 42 | 0010 1010
  165. 69 | 0100 0101
  166. 255 | 1111 1111
  167. 0 | 0000 0000
  168. The example is with only 8-bit numbers (ie, one byte). Uint32 is 32-bit, so the binary number would
  169. have four times as many digits, which means there are quite a few more zeroes on the left side of
  170. all of these.
  171. The exact mechanics of converting between decimal and binary and the most efficient ways to do so
  172. are out of scope for this book, as it's less about programming and more about math. I'll just show
  173. you the most basic possible way to do it, which is all you really need to understand the concept
  174. of storing flags as an integer.
  175. For this course, grab a calculator that has a science or programmer mode. If you're running Linux
  176. (as you should be), both gnome-calendar and kcalc both have it. Alternatively, type something like
  177. '42 to binary' in duckduckgo and it'll also give you the binary version.
  178. The only thing you need to know about conversion for this course, is the powers of two. When given a
  179. binary number, every digit represents a power of two in decimal. Here's an example for 8 bits:
  180. Binary: 1 1 1 1 1 1 1 1
  181. Decimal: 128 64 32 16 8 4 2 1
  182. You'll notice a pattern: every time you move a digit to the left in the binary number, the
  183. equivalent decimal value multiplies by two. Hence, powers of two. This goes on to infinity.
  184. To easily convert a binary number to decimal in your head, you sum up all the decimal presentations
  185. where the binary is set to '1'. For the example above, that means the value is 128+64+32+16+8+4+2+1
  186. = 255. Since it's all ones here, you can guess that 255 is the largest unsigned number we can
  187. express with just eight bits.
  188. Let's take 10110110 as an example. You can represent the binary and decimal values using the same
  189. little graph:
  190. Binary: 1 0 1 1 0 1 1 0
  191. Decimal: 128 _ 32 16 _ 4 2 _
  192. Whenever the binary is 0, the decimal is also zero, and when it's 1, the decimal is whatever that
  193. spot represents. So add all the numbers from the decimal row together, and you get 182. You can
  194. enter that in your calculator and switch it back to binary, and you'll see that you get the same
  195. binary number back.
  196. Section VII: mapping enums to powers of two
  197. -------------------------------------------
  198. So the way this works with enum values is simple. When you create your enum, you match them to the
  199. decimal representations:
  200. --- [ example code ] ---
  201. enum personality_traits
  202. {
  203. friendly = 1,
  204. curious = 2,
  205. energetic = 4,
  206. annoying = 8
  207. };
  208. ------------------------
  209. Then when you say something like this:
  210. unsigned int my_friend = annoying;
  211. Then you know that the value of my_friend is 8, or - in binary - 1000.. Likewise, if you set the
  212. value to 6, then you know it's 4+2, so he or she is energetic and curious. Below are all of the
  213. combinations you can have with that particular enum:
  214. decimal binary flags active
  215. ------------------------------------------------
  216. 1 0001 friendly
  217. 2 0010 curious
  218. 3 0011 friendly, curious
  219. 4 0100 energetic
  220. 5 0101 energetic, friendly
  221. 6 0110 energetic curious
  222. 7 0111 friendly, energetic, curious
  223. 8 1000 annoying
  224. 9 1001 annoying, friendly
  225. 10 1010 annoying, curious
  226. 11 1011 annoying, curious, friendly
  227. 12 1100 annoying, energetic
  228. 13 1101 annoying, energetic, friendly
  229. 14 1110 annoying, energetic, curious
  230. 15 1111 all the traits!
  231. Are you in the mood for building a Sims clone? Because I sure am now.
  232. If you're confused about the logic, try using this table as a reference:
  233. Binary: 1 1 1 1 -> short: 1111
  234. Decimal: 8 4 2 1 -> total: 8+4+2+1 = 15
  235. Trait: annoying energetic curious friendly -> all the traits!
  236. The binary row is how it's stored in memory. The decimal row shows the decimal representation of
  237. that digit, as before. and the trait describes the personality trait we assigned to that decimal
  238. number, as per our enum above.
  239. So let's say, for example that we have binary value 1010 in memory. You can represent it as such:
  240. Binary: 1 0 1 0 -> short: 1010
  241. Decimal: 8 _ 2 _ -> total: 8+2 = 10
  242. Trait: annoying _ curious _ -> annoying, curious
  243. Like with regular conversion, each binary digit maps to a value in decimal. But now with the enum,
  244. we have the additional mapping of a decimal number to an enum value - our personality traits
  245. in this example.
  246. So when you see value 1010 in memory, you can figure out that the first digit represents 8, the
  247. third represents 2, and the remaining two don't matter because they're set to 0. Only 8 and 2 are
  248. active in this particular binary number, and we know from the enum that they map to 'annoying' and
  249. 'curious' respectively.
  250. You also know that 8 and 2 together makes 10. So when you see something like:
  251. my_friend = 10
  252. Then you know that it the binary representation is 1010, which represents 8 and 2, which represents
  253. annoying and curious.
  254. Section VIII: bitwise operators
  255. -------------------------------
  256. In real life you will very rarely work with numbers directly. You usually don't even known what they
  257. are - you just see the names. This is true for SDL_CreateWindow as well - the documentation lists
  258. the names only, never the numbers. That's because there is one final trick up our sleeve that lets
  259. you just write the names in the enum without ever knowing the corresponding numeric values. As
  260. usual, we went through this just so you know how things work below the surface, so you can
  261. confidently use the easy version without feeling like you have no idea what's really going on.
  262. So how do we combine words together when we can't just add the numbers together? The answer is
  263. bitwise operators.
  264. There are a couple operators in C that operate directly on binary level. You use them on variables,
  265. but the operation is performed directly on the binary in memory. The easiest way to understand this
  266. is to just see them at work.
  267. * The AND operation (symbol: &)
  268. * The OR operation (symbol: |)
  269. * Exclusive OR (symbol: ^)
  270. * Inversion operation (symbol: ~)
  271. All except the last one operate on two binary numbers every time, the same way that regular
  272. mathematical operators do.
  273. Before we explain these, a quick reminder that all math in C operates on binary, even if we
  274. see numbers. So for example, a simple addition would look like this:
  275. 1 0 0 1 0 1 0 1
  276. + 0 1 1 0 1 0 0 1
  277. ---------------
  278. = 1 1 1 1 1 1 1 0
  279. I assume you remember how to do this the slow way (ie, not relying on memory), by handling digits
  280. one at a time from right to left, and remembering carryover. It's the exact same as with regular
  281. decimal math, except here your maximum value for a single digit is 1, rather than 9. Bitwise
  282. operations can be mentally performed in similar ways. Again, this is math, not programming. You can
  283. ask any math teacher how to do addition, subtraction, division or multiplication in math and he'll
  284. be happy to walk you through it.
  285. The AND operation checks for each digit in original and comparison number if both digits are 1. Only
  286. if this is true, is the resulting digit 1 as well. You can see this happen on the third column from
  287. the right in the example below. That is the only column where both digits are 1. Everything else has
  288. at least one 0 in it, and therefor results in a final 0.
  289. 1 0 0 1 0 1 0 1
  290. & 0 0 0 0 1 1 1 0
  291. ---------------
  292. = 0 0 0 0 0 1 0 0
  293. In short:
  294. * Becomes 1 if both numbers are 1
  295. * Becomes 0 if either number is 0
  296. The OR operation is the same basic principle, but looser. It returns 1 is either digit was 1. That
  297. means that the only way to get a final 0 with an OR operation is if both digits were 0 to begin with.
  298. 1 0 0 1 0 1 0 1
  299. | 0 0 0 0 1 1 1 0
  300. ---------------
  301. = 1 0 0 1 1 1 1 1
  302. In short:
  303. * Becomes 0 if both numbers are 0
  304. * Becomes 1 if either number is 1
  305. The exclusive or (usually called XOR) is a bit inbetween the first two. It returns 1 if exactly one of
  306. the two numbers is a 1. It returns 0 in every other case - when you have two zeroes or when you have
  307. two ones.
  308. 1 0 0 1 0 1 0 1
  309. ^ 0 0 0 0 1 1 1 0
  310. ---------------
  311. = 1 0 0 1 1 0 1 1
  312. In short:
  313. * Becomes 1 if exactly one number is 1
  314. * Becomes 0 in every other situation
  315. The inversion (also called the NOT operator) is the only one so far that operates on a single
  316. number. The operation is exceedingly simple. It just flips every bit. 1 becomes 0 and 0 becomes 1.
  317. 1 0 0 1 0 1 0 1
  318. ~ ---------------
  319. = 0 1 1 0 1 0 1 0
  320. There are also shift operators, which move bits left and right. We won't cover them here unless we
  321. actually need them.
  322. Side note: Many explanations online or in books will show you the result of a bitwise operator using
  323. a single digit, but I don't like that approach. In reality, you will always be working on
  324. at least a byte of data in C, never on individual bits. You can actually write numbers in
  325. binary in C code, but it'll always be at least eight of them.
  326. Section IX: writing binary numbers in C
  327. ---------------------------------------
  328. In C, you can write numbers directly as binary, by writing the number as 0bxxxxxxxx, where the x-es
  329. are binary digits.
  330. ----- [ example code ] ---
  331. char binary1 = 0b10100100;
  332. char binary2 = 0b00011100;
  333. char binary3 = 0b11111111;
  334. --------------------------
  335. You can even define your enum this way, if you don't want to to the mental number conversion:
  336. --- [ example code ] ---
  337. enum binary_enum {
  338. value1 = 0b00011101,
  339. value2 = 0b11111111,
  340. value3 = 0b00000000
  341. };
  342. ------------------------
  343. For that last example, you can print the values out and see the integer values too. Just pass it as
  344. '%i' to printf, as you've done multiple times in the past. It doesn't matter that you used binary to
  345. assign it, since it always ends up as binary in memory anyway, even if you had assigned it using the
  346. standard decimal notation.
  347. ---------------- [ example code ] ---
  348. int main()
  349. {
  350. printf("value1 is %i\n", value1);
  351. printf("value2 is %i\n", value2);
  352. printf("value3 is %i\n", value3);
  353. return 0;
  354. }
  355. -------------------------------------
  356. You can also use shorter values. Even if you're storing in an eight bit char variable, you can still
  357. choose to only assign 0bxxxx to it. C will figure out that it has to fill it up with leading zeroes.
  358. The only problem is if you try to assign a number that's too large, such as assigning 16 bits to a
  359. char. Then your compiler will complain. But then it will also do so if you try to assign it a very
  360. large decimal value that can't be represented using the amount of bits that are available.
  361. Section X: combining flags
  362. --------------------------
  363. Some things you've learned are:
  364. * Flags are usually enums that map to powers of two
  365. * Powers of two can represent positions in a binary number
  366. * Bitwise operators work on digits in a binary number
  367. Let's take our example enum from a few sections ago again:
  368. --- [ example code ] ---
  369. enum personality_traits
  370. {
  371. friendly = 1,
  372. curious = 2,
  373. energetic = 4,
  374. annoying = 8
  375. };
  376. ------------------------
  377. Using what you've learned here about binary, you'll know that those values map to binary as such:
  378. * friendly = 1 = 0001
  379. * curious = 2 = 0010
  380. * energetic = 4 = 0100
  381. * annoying = 8 = 1000
  382. If you wanted to define a character who is curious and energetic, you'd have to combine 0010 and
  383. 0100. So using binary math, you'd want to do it like this:
  384. 0 0 1 0
  385. | 0 1 0 0
  386. -------
  387. = 0 1 1 0
  388. In C, you can write the same operation like this:
  389. int my_good_friend = 0b0010 || 0b0100;
  390. The value of my_good_friend will be 0b0110. Which translates to a decimal 6. As yo can see from the
  391. enum declaration, that maps to both energetic and curious.
  392. You can also do it with decimal numbers directly:
  393. int my_good_friend = 2 | 4;
  394. Both are exactly the same, since they're direct translations between binary and decimal
  395. representations of the exact same numbers.
  396. Now, usually when you deal with enums, you don't actually know the numeric values, unless you wrote
  397. it yourself. That's the main reasons that enums exist, actually - because numbers mean very little
  398. to the human brain if they weren't memorized. And even then, word recognition is a far faster
  399. process for the human brain than retrieving a number and matching that to a concept. Don't blindly
  400. believe me on that - I'm a programmer, not a neuroscientist.
  401. Because enum values map to numbers, you can just use the names directly, and it'll still be entirely
  402. equivalent:
  403. int my_good_friend = curious | energetic;
  404. And that's exactly what you see happen in the flags argument for SDL_CreateWindow. That's not just a
  405. guess - here's *exactly* how they're defined in one of the enums in the SDL2 source code:
  406. ---------------------------------------------- [ SDL2 source code ] ---
  407. SDL_WINDOW_FULLSCREEN = 0x00000001,
  408. SDL_WINDOW_OPENGL = 0x00000002,
  409. SDL_WINDOW_SHOWN = 0x00000004,
  410. SDL_WINDOW_HIDDEN = 0x00000008,
  411. SDL_WINDOW_BORDERLESS = 0x00000010,
  412. SDL_WINDOW_RESIZABLE = 0x00000020,
  413. SDL_WINDOW_MINIMIZED = 0x00000040,
  414. SDL_WINDOW_MAXIMIZED = 0x00000080,
  415. SDL_WINDOW_INPUT_GRABBED = 0x00000100,
  416. SDL_WINDOW_INPUT_FOCUS = 0x00000200,
  417. SDL_WINDOW_MOUSE_FOCUS = 0x00000400,
  418. SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
  419. SDL_WINDOW_FOREIGN = 0x00000800,
  420. SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000,
  421. -----------------------------------------------------------------------
  422. Here they use hexadecimal notation rather than binary, which describes the values per byte rather
  423. than per bit but you still see that power of two pattern - 1, 2 4, 8, which is 0b0001, 0b0010,
  424. 0b0100 and 0b1000 in binary, respectively.
  425. You're not meant to use those hex values as they may change over time (and difficult to read
  426. anyway), but you can see now that it's indeed set up so that you can OR any of the enum values
  427. together and they'll never conflict with each other.
  428. Section XI: creating window with SDL_CreateWindow
  429. ------------------------------------------------
  430. After all that theory, it's time to finally make the actual call to the function. Assuming that
  431. you're still following along with the code - this is where we finally add something to our Cuterald
  432. project. Check out the commit listed at the top of the page, and you should end up with this code:
  433. ====================== main.c ===
  434. #include <SDL2/SDL_timer.h>
  435. int main (int argc, char** argv)
  436. {
  437. SDL_Delay(3000);
  438. return 0;
  439. }
  440. =================================
  441. Above the call to SDL_Delay, add the following:
  442. ======================================== main.c ===
  443. SDL_Window *window = SDL_CreateWindow (
  444. "Example SDL2 application",
  445. SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
  446. 1280,720,
  447. SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI
  448. );
  449. ===================================================
  450. You should be able to explain every bit of this on your own, but let's quickly go over it anyway.
  451. The first argument is the title. This is just a const char* and doesn't use anything too special.
  452. For horizontal and vertical size, we're using an special value that SDL defines and recommends in
  453. the documentation. I don't want to give it an exact position, so center of the screen is just fine.
  454. For size we'll just throw standard full HD in there for now. We'll definitely make this configurable
  455. at some point.
  456. The flags we've just spent some time on. Check the SDL documentation page for the possible values
  457. and their explanations. Depending on your system and drivers, you may need some different flags. See
  458. what works for your system and stick with that for now. Error handling isn't something we're going
  459. to bother with for now.
  460. Finally, make sure to also include 'SDL2/SDL_video.h', as that's what defines the SDL_CreateWindow
  461. function.
  462. Compile and run the code. Don't forget to pass -lSDL2 to gcc so it knows to look in the SDL2 library
  463. files for the implementations. If all goes well, you should see the window pop up for three seconds
  464. and then die. There's a good you won't see anything inside of it - it may be see-through, or you may
  465. see some glitchy nonsense. This is normal - we're not actually rendering anything yet, so the window
  466. takes whatever was present in memory or on the screen.
  467. Section XII: chapter summary
  468. ----------------------------
  469. I was originally planning to also set up a renderer in this chapter, but we took a bit longer on
  470. the binary stuff than I expected. The amount of things in the language you haven't learned yet is
  471. quickly decreasing even if it may not feel like it.
  472. In this chapter we took a typical call to SDL_CreateWindow and went in deep detail on all the
  473. arguments and the C syntax that comes with it. The most important part is understanding the binary,
  474. in terms of memory and bitwise operations. If you understand that, then you already know something
  475. that more than half the programmers on this planet have absolutely no clue about.
  476. Next chapter I hope to set up the renderer and draw a few squares. After that we'll probably
  477. get into loops and events.