Quite usefull macro definitions:

// For simple printing, PRINT2 is mainly for the second macro
#define PRINT(str) printf("%s\n",str)
#define PRINT2(str,str2) printf("%s%s\n",str, str2)

// For checking null pointers, gets kind of tedious sometimes
// Only prints if DBG_NULLPTR is defined
#define NULLCHK(ptr) if(ptr == NULL) { PRINT2("Null pointer at variable: ", # ptr  ); }
#define NULLCHK(ptr)


From discord server on unions:

by FuriousProgrammer

As bates said, structs are one of the most important concepts in C. They let you store multiple values in a single variable, which allows you to explicitly relate data that is, well, related.

Unions give C something akin to a "union of types" that's more commonly expressed in functional languages. Practically, they take the largest single element in the union and give the union the size of that (since types in C are mainly a statement of how big something is in memory). Each element of a union accesses the same base memory, so you can for example access the individual bytes of a multi-byte packed integer value. A common example of this is a "vector4" union type:
union vec4 {
  uint32_t data_32;
  uint8_t data_8[4];
  struct { uint8_t r, g, b, a };
  struct { uint8_t x, y, z, w };
  struct { uint8_t u, v, q, d }; // can't remember what people usually use for 4D UV coords
 Which allows you to access the 4 underlying bytes of memory in several different ways, depending on what is most convenient or makes the most sense in any given context.
The key difference between a struct and a union is that Unions store a single value that can be expressed in different ways whereas a Struct stores multiple values. 

An Enumeration is basically just "named magic numbers". Since strings suck to work with and are very memory inefficient, but we like giving things names like NULL instead of 0, or ENABLE_FEATURE_X instead of (1 << 17), Enumerations are an in-language way to define a /type/ that is in actuality a simple integer value.

The original method of naming magic-int-constants using #define macros has a major disadvantage: it cannot tell if you're using the wrong macro for a given function argument! Enumerations solve that by associating a set of enum values (which, I repeat, are just simple integer values) with a particular type, and the compiler will complain if you provide an enum of Type A when it was expecting an enum of Type B, even if the actual /value/ is identical for both. 
I actually haven't used these too terribly much so my memory is rusty on them, but I believe all members of an enum have the same underlying type, e.g. uint32_t, and each individual member has a specific value expressed in that type. (They don't have any other restrictions - by default they're 0-indexed and increase by 1, but you can give them non-unique values and/or specific values that leave gaps) 

More complex Collision detection:
	circle-circle: https://ericleong.me/research/circle-circle/
	there are others as well, like finding the closest point on a line
	to a point. Many are usefull.
Math related:
	the equation to draw a circle is x**2 + x**2 = 1
	the equation to draw a rounded square is x**8 + x**8 = 1
	In other words, to increase the 'squareness' of the circle 
	increase the exponent. _However_ the exponent _must_ be divisable by 2
	Another nice way to do an actual rounded rectangle: