Defines are not necssary but can make life easier.
Generally the compiler replaces the first part in the define with the second part of the define BEFORE he starts to compile.

With a define you can for example replace certain numbers with names. Example:

#define max_health 200
if(my.health > max_health) { //CHEATER!!! }
if(my.health > 200) { Thats the same }

As you hopefully see the first if statement is better to read and understand.

You can also write full statements with #defines. E.g.

#define is(obj,flag) (obj.flags & FLAG)

if(is(my,TRANSLUCENT)) { my is transparent }
if(my.flags & TRANSLUCENT) { exactly the same }

Maybe you're interested on how the compiler handles with defines. Before the Compiler starts to compile he checks (code above) if there is any code line in your project that fits to the syntax is(obj,flag). If so he replaces it with (obj.flags & FLAG). After that he starts compiling.

You can refine almost everything (attention, #defines are not always the best solution!!). You could also redfine the name of skills for example.

#define skill[0] health
//..
my.health = 100;
my.skill[0] = 100; //does exactly the same but not as nice to read as the one above