/enemies.c

https://github.com/jayrhynas/Corridor-Defence · C · 269 lines · 239 code · 14 blank · 16 comment · 72 complexity · 0546896e60c6beaa5a9a69c6bdbad6ff MD5 · raw file

  1. /*
  2. * File: enemies.c
  3. * Author: Jayson Rhynas, 20299211
  4. * Created: January 14, 2011
  5. *
  6. * Implements enemy functions.
  7. */
  8. #include "enemies.h"
  9. #include "main.h"
  10. Enemy* createEnemy(EType type, int x, int id) {
  11. Enemy *e;
  12. e = (Enemy*)malloc(sizeof(Enemy));
  13. e->type = type;
  14. e->container = NULL;
  15. e->id = id;
  16. e->x = x;
  17. e->floor = 0;
  18. e->dy = 0;
  19. e->size = 20;
  20. e->flying = 0;
  21. e->slow = 0;
  22. e->sTime = 0;
  23. e->burn = 0;
  24. e->bTime = 0;
  25. e->lastBurn = 0;
  26. e->burnInterval = 1000;
  27. e->maxEffectTime = 10000;
  28. e->dTime = 0;
  29. e->damageInterval = 750;
  30. e->showHealth = 1;
  31. // specific inits
  32. if (e->type == SLOW || e->type == FLYING_SLOW) {
  33. e->dx = -2;
  34. e->y = 308 + e->size;
  35. if (e->type == FLYING_SLOW) {
  36. e->y = 290 + e->size;
  37. e->flying = 1;
  38. }
  39. e->maxHealth = 100;
  40. if (e->type == SLOW) {
  41. e->damage = 50;
  42. e->dollarValue = 10;
  43. } else {
  44. e->damage = 20;
  45. e->dollarValue = 20;
  46. }
  47. } else if (e->type == FAST || e->type == FLYING_FAST) {
  48. e->dx = -4;
  49. e->y = 308 + e->size;
  50. if (e->type == FLYING_FAST) {
  51. e->y = 290 + e->size;
  52. e->flying = 1;
  53. }
  54. e->maxHealth = 50;
  55. if (e->type == FAST) {
  56. e->damage = 40;
  57. e->dollarValue = 20;
  58. } else {
  59. e->damage = 10;
  60. e->dollarValue = 50;
  61. }
  62. }
  63. e->health = e->maxHealth;
  64. return e;
  65. }
  66. void moveEnemy(void *ve) {
  67. long long cur_time;
  68. Enemy *e;
  69. e = ve;
  70. // if an enemy goes off screen, reverse its movement and move it up a level
  71. if ((e->x < -50 && e->dx < 0) || (e->x > WIN_W + 50 && e->dx > 0)) {
  72. e->dx = e->dx * -1;
  73. if (e->x < 0) {
  74. e->x = -50;
  75. } else {
  76. e->x = WIN_W + 50;
  77. }
  78. e->y -= 120;
  79. e->floor++;
  80. }
  81. // if an enemy runs into the door, destory the enemy (no money awarded) and damage the door
  82. if (e->floor == 2 && e->x < 70) {
  83. e->health = 0;
  84. e->dollarValue = 0;
  85. castle.curHealth -= e->damage;
  86. return;
  87. }
  88. // disable any effects if they have expired
  89. cur_time = getTime();
  90. if (abs(cur_time - e->sTime) > e->maxEffectTime) {
  91. e->slow = 0;
  92. }
  93. if (abs(cur_time - e->bTime) > e->maxEffectTime) {
  94. e->burn = 0;
  95. }
  96. // apply burn damage
  97. if (e->burn && (abs(cur_time - e->lastBurn) > e->burnInterval)) {
  98. e->lastBurn = cur_time;
  99. e->health -= 2;
  100. }
  101. // move the enemy
  102. if (e->slow) {
  103. e->x += e->dx / 2;
  104. e->y += e->dy / 2;
  105. } else {
  106. e->x += e->dx;
  107. e->y += e->dy;
  108. }
  109. }
  110. void drawEnemy(void *ve) {
  111. Enemy *e;
  112. e = (Enemy*)ve;
  113. XSetLineAttributes(display, enemyGC, 2, LineSolid, CapRound, JoinRound);
  114. if (e->type == SLOW) {
  115. XSetForeground(display, enemyGC, green.pixel);
  116. XFillArc(display, buffer, enemyGC, e->x - e->size, e->y - e->size, e->size*2, e->size*3, 0, 360*32);
  117. XFillArc(display, buffer, enemyGC, e->x - e->size/2 - e->size/4, e->y + e->size/2, e->size/2, e->size/2, 0, 360*64);
  118. XFillArc(display, buffer, enemyGC, e->x + e->size/2 - e->size/4, e->y + e->size/2, e->size/2, e->size/2, 0, 360*64);
  119. if (e->burn) {
  120. XSetForeground(display, enemyGC, red.pixel);
  121. } else {
  122. XSetForeground(display, enemyGC, black.pixel);
  123. }
  124. XDrawArc(display, buffer, enemyGC, e->x - e->size, e->y - e->size, e->size*2, e->size*3, 0, 360*32);
  125. XDrawLine(display, buffer, enemyGC, e->x - e->size, e->y + e->size/2, e->x + e->size, e->y + e->size/2);
  126. XDrawArc(display, buffer, enemyGC, e->x - e->size/2 - e->size/4, e->y + e->size/2, e->size/2, e->size/2, 0, 360*64);
  127. XDrawArc(display, buffer, enemyGC, e->x + e->size/2 - e->size/4, e->y + e->size/2, e->size/2, e->size/2, 0, 360*64);
  128. } else if (e->type == FLYING_SLOW) {
  129. XSetForeground(display, enemyGC, brown.pixel);
  130. XFillArc(display, buffer, enemyGC, e->x - e->size, e->y - e->size, e->size*2, e->size*2, 0, 360*64);
  131. if (e->burn) {
  132. XSetForeground(display, enemyGC, red.pixel);
  133. } else {
  134. XSetForeground(display, enemyGC, black.pixel);
  135. }
  136. XDrawArc(display, buffer, enemyGC, e->x - e->size, e->y - e->size, e->size*2, e->size*2, 0, 360*64);
  137. } else if (e->type == FAST) {
  138. int npoints = 5;
  139. XPoint points[] = {{e->x - e->size, e->y + e->size},
  140. {e->x + e->size, e->y - e->size},
  141. {e->x + e->size/4, e->y + e->size/2},
  142. {e->x + e->size, e->y + e->size},
  143. {e->x - e->size, e->y + e->size}};
  144. if (e->floor == 1) {
  145. flipPoints(points, npoints, e->x, e->y, -1, 1);
  146. }
  147. XSetForeground(display, enemyGC, blue.pixel);
  148. XFillPolygon(display, buffer, enemyGC, points, npoints, Nonconvex, CoordModeOrigin);
  149. if (e->burn) {
  150. XSetForeground(display, enemyGC, red.pixel);
  151. } else {
  152. XSetForeground(display, enemyGC, black.pixel);
  153. }
  154. XDrawLines(display, buffer, enemyGC, points, npoints, CoordModeOrigin);
  155. } else if (e->type == FLYING_FAST) {
  156. int npoints = 7;
  157. XPoint points[] = {{e->x - e->size, e->y},
  158. {e->x, e->y - e->size},
  159. {e->x + e->size, e->y - e->size},
  160. {e->x, e->y},
  161. {e->x + e->size, e->y + e->size},
  162. {e->x, e->y + e->size},
  163. {e->x - e->size, e->y}};
  164. if (e->floor == 1) {
  165. flipPoints(points, npoints, e->x, e->y, -1, 1);
  166. }
  167. XSetForeground(display, enemyGC, yellow.pixel);
  168. XFillPolygon(display, buffer, enemyGC, points, npoints, Nonconvex, CoordModeOrigin);
  169. if (e->burn) {
  170. XSetForeground(display, enemyGC, red.pixel);
  171. } else {
  172. XSetForeground(display, enemyGC, black.pixel);
  173. }
  174. XDrawLines(display, buffer, enemyGC, points, npoints, CoordModeOrigin);
  175. }
  176. if (e->showHealth) {
  177. // draw health bar
  178. XSetForeground(display, enemyGC, white.pixel);
  179. XFillRectangle(display, buffer, enemyGC, e->x - e->size, e->y - e->size - 10, e->size * 2, 5);
  180. XSetForeground(display, enemyGC, red.pixel);
  181. XFillRectangle(display, buffer, enemyGC, e->x - e->size, e->y - e->size - 10, e->size * 2 * ((float)e->health/(float)e->maxHealth), 5);
  182. XDrawRectangle(display, buffer, lineGC, e->x - e->size, e->y - e->size - 10, e->size * 2, 5);
  183. }
  184. }
  185. void drawThumbEnemy(EType type, int x, int y) {
  186. Enemy *e;
  187. e = thumbEnemies[type];
  188. e->x = x;
  189. e->y = y;
  190. e->size = 10;
  191. e->showHealth = 0;
  192. drawEnemy(thumbEnemies[type]);
  193. }
  194. void cleanupEnemies() {
  195. Node *cur, *next;
  196. Enemy *e;
  197. cur = eList->first;
  198. while (cur != NULL) {
  199. next = cur->next;
  200. e = cur->item;
  201. if (e->floor > 2 || e->health <= 0) {
  202. money += e->dollarValue;
  203. if (e->dollarValue > 0) { // enemies who reach the end have a dollar value of 0 and don't count
  204. points++;
  205. }
  206. listRemove(eList, cur);
  207. }
  208. cur = next;
  209. }
  210. }
  211. void createWave(EType type, int num) {
  212. int i;
  213. Enemy *e;
  214. if (nextWave != NULL) {
  215. listDelete(nextWave);
  216. fprintf(stderr, "called createWave when nextWave != NULL, deleting nextWave");
  217. }
  218. nextWave = listCreate(ENEMY);
  219. for (i = 0; i < num; i++) {
  220. e = createEnemy(type, WIN_W + 100 + i*50, i);
  221. listAppend(nextWave, e);
  222. }
  223. }
  224. void createRandomWave() {
  225. EType type;
  226. int num;
  227. type = ((double)random()/(double)RAND_MAX) * NUM_ENEMY_TYPES;
  228. num = ((double)random()/(double)RAND_MAX) * 3 + 4;
  229. createWave(type, num);
  230. nextWaveTime = getTime() + (((double)random()/(double)RAND_MAX) * 30 + 45) * 1000;
  231. }
  232. void sendWave() {
  233. Node *cur, *next;
  234. if (nextWave != NULL) {
  235. cur = nextWave->first;
  236. // copy enemies to main eList
  237. while (cur != NULL) {
  238. listAppend(eList, cur->item);
  239. cur = cur->next;
  240. }
  241. // free the nodes and the list, but not the enemies
  242. cur = nextWave->first;
  243. while (cur != NULL) {
  244. next = cur->next;
  245. free(cur);
  246. cur = next;
  247. }
  248. free(nextWave);
  249. nextWave = NULL;
  250. }
  251. }
  252. void sendAndCreateWave() {
  253. sendWave();
  254. createRandomWave();
  255. }