From 56540a56acbd78a600e286a9e4c137f1b3286246 Mon Sep 17 00:00:00 2001 From: Sweeney Date: Wed, 24 Feb 2016 15:02:51 +0000 Subject: [PATCH] Start of bullet, debris, and effect performance updates. Dynamic array sizing. --- src/battle/battle.c | 180 +++++++++++++++++---------------- src/battle/bullets.c | 169 ++++++++++++++++++------------- src/battle/bullets.h | 6 +- src/battle/debris.c | 81 ++++++++++----- src/battle/debris.h | 4 +- src/battle/effects.c | 230 ++++++++++++++++++++++++++----------------- src/battle/effects.h | 2 + 7 files changed, 397 insertions(+), 275 deletions(-) diff --git a/src/battle/battle.c b/src/battle/battle.c index d17b229..594bdd0 100644 --- a/src/battle/battle.c +++ b/src/battle/battle.c @@ -47,52 +47,52 @@ void initBattle(void) battle.effectTail = &battle.effectHead; battle.objectiveTail = &battle.objectiveHead; battle.locationTail = &battle.locationHead; - + app.delegate.logic = &logic; app.delegate.draw = &draw; memset(&app.keyboard, 0, sizeof(int) * MAX_KEYBOARD_KEYS); - + initQuadtree(&battle.quadtree); - + initBullets(); - + initEntities(); - + initStars(); - + initBullets(); - + initBackground(); - + initEffects(); - + initHud(); - + initRadar(); - + initMessageBox(); - + initMissionInfo(); - + initDebris(); - + resetWaypoints(); - + show = SHOW_BATTLE; - + getWidget("ok", "startBattle")->action = start; - + getWidget("resume", "inBattle")->action = resume; getWidget("options", "inBattle")->action = options; getWidget("restart", "inBattle")->action = retry; getWidget("quit", "inBattle")->action = quitBattle; - + getWidget("continue", "battleWon")->action = continueGame; getWidget("retry", "battleWon")->action = retry; - + getWidget("retry", "battleLost")->action = retry; getWidget("quit", "battleLost")->action = quitBattle; - + selectWidget("ok", "startBattle"); } @@ -101,7 +101,7 @@ static void logic(void) if (battle.status == MS_IN_PROGRESS || battle.status == MS_COMPLETE || battle.status == MS_FAILED) { handleKeyboard(); - + if (show == SHOW_BATTLE) { if (!battle.epic || (battle.epic && !battle.playerSelect)) @@ -114,7 +114,7 @@ static void logic(void) } } } - + doWidgets(); } @@ -129,58 +129,58 @@ static void doBattle(void) { ssx = ssy = 0; } - + scrollBackground(-ssx * 0.1, -ssy * 0.1); - + battle.planet.x -= ssx * 0.05; battle.planet.y -= ssy * 0.05; - + doHud(); - + doStars(ssx, ssy); - + doBullets(); - + doEntities(); - + doEffects(); - + doDebris(); - + doPlayer(); - + doObjectives(); - + if (player != NULL) { doLocations(); - + doMessageBox(); - + if (battle.status == MS_IN_PROGRESS) { doScript(); } } - + if (battle.status != MS_IN_PROGRESS) { battle.missionFinishedTimer--; } - + if (battle.stats[STAT_TIME] % FPS == 0) { runScriptFunction("TIME %d", battle.stats[STAT_TIME] / 60); } - + battle.stats[STAT_TIME]++; - + if (battle.unwinnable && battle.missionFinishedTimer <= -FPS * 6) { postBattle(); destroyBattle(); - + initGalacticMap(); } } @@ -192,41 +192,41 @@ static void draw(void) battle.camera.x = player->x - (SCREEN_WIDTH / 2); battle.camera.y = player->y - (SCREEN_HEIGHT / 2); } - + drawBackground(battle.background); - + blitScaled(battle.planetTexture, battle.planet.x, battle.planet.y, battle.planetWidth, battle.planetHeight); - + drawStars(); - + drawEntities(); - + drawBullets(); - + drawDebris(); - + drawEffects(); - + if (dev.debug) { drawLocations(); } - + drawHud(); - + if (player != NULL) { drawMessageBox(); } - + drawMissionInfo(); - + switch (show) { case SHOW_MENU: drawMenu(); break; - + case SHOW_OPTIONS: drawOptions(); break; @@ -236,22 +236,22 @@ static void draw(void) static void drawMenu(void) { SDL_Rect r; - + SDL_SetRenderDrawBlendMode(app.renderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawColor(app.renderer, 0, 0, 0, 128); SDL_RenderFillRect(app.renderer, NULL); SDL_SetRenderDrawBlendMode(app.renderer, SDL_BLENDMODE_NONE); - + r.w = 400; r.h = 400; r.x = (SCREEN_WIDTH / 2) - r.w / 2; r.y = (SCREEN_HEIGHT / 2) - r.h / 2; - + SDL_SetRenderDrawColor(app.renderer, 0, 0, 0, 0); SDL_RenderFillRect(app.renderer, &r); SDL_SetRenderDrawColor(app.renderer, 200, 200, 200, 255); SDL_RenderDrawRect(app.renderer, &r); - + drawWidgets("inBattle"); } @@ -266,21 +266,21 @@ static void handleKeyboard(void) selectWidget("resume", "inBattle"); show = SHOW_MENU; break; - + case SHOW_MENU: show = SHOW_BATTLE; break; - + case SHOW_OBJECTIVES: show = SHOW_BATTLE; break; } - + memset(app.keyboard, 0, sizeof(int) * MAX_KEYBOARD_KEYS); - + playSound(SND_GUI_CLOSE); } - + if (app.keyboard[SDL_SCANCODE_TAB]) { battle.status = MS_PAUSED; @@ -295,57 +295,57 @@ static void start(void) static void resume(void) { show = SHOW_BATTLE; - + memset(app.keyboard, 0, sizeof(int) * MAX_KEYBOARD_KEYS); } static void continueGame(void) { postBattle(); - + destroyBattle(); - + initGalacticMap(); } static void options(void) { show = SHOW_OPTIONS; - + initOptions(returnFromOptions); } static void returnFromOptions(void) { show = SHOW_MENU; - + selectWidget("resume", "inBattle"); } static void retry(void) { postBattle(); - + destroyBattle(); - + initBattle(); - + loadMission(game.currentMission->filename); } static void quitBattle(void) { postBattle(); - + destroyBattle(); - + initGalacticMap(); } static void postBattle(void) { int i; - + for (i = 0 ; i < STAT_MAX ; i++) { if (i != STAT_TIME && i != STAT_EPIC_KILL_STREAK) @@ -353,12 +353,12 @@ static void postBattle(void) game.stats[i] += battle.stats[i]; } } - + if (game.currentMission && !game.currentMission->completed) { game.currentMission->completed = (battle.status == MS_COMPLETE || !battle.numObjectivesTotal); } - + } void destroyBattle(void) @@ -369,7 +369,7 @@ void destroyBattle(void) Effect *e; Objective *o; Location *l; - + while (battle.entityHead.next) { ent = battle.entityHead.next; @@ -377,7 +377,7 @@ void destroyBattle(void) free(ent); } battle.entityTail = &battle.entityHead; - + while (battle.bulletHead.next) { b = battle.bulletHead.next; @@ -385,7 +385,7 @@ void destroyBattle(void) free(b); } battle.bulletTail = &battle.bulletHead; - + while (battle.debrisHead.next) { d = battle.debrisHead.next; @@ -393,7 +393,7 @@ void destroyBattle(void) free(d); } battle.debrisTail = &battle.debrisHead; - + while (battle.effectHead.next) { e = battle.effectHead.next; @@ -401,7 +401,7 @@ void destroyBattle(void) free(e); } battle.effectTail = &battle.effectHead; - + while (battle.objectiveHead.next) { o = battle.objectiveHead.next; @@ -409,7 +409,7 @@ void destroyBattle(void) free(o); } battle.objectiveTail = &battle.objectiveHead; - + while (battle.locationHead.next) { l = battle.locationHead.next; @@ -417,16 +417,22 @@ void destroyBattle(void) free(l); } battle.locationTail = &battle.locationHead; - + cJSON_Delete(battle.missionJSON); - + resetHud(); - + resetMessageBox(); - + destroyEntities(); - + destroyScript(); - + destroyQuadtree(); + + destroyDebris(); + + destroyBullets(); + + destroyEffects(); } diff --git a/src/battle/bullets.c b/src/battle/bullets.c index 01ca780..629ac37 100644 --- a/src/battle/bullets.c +++ b/src/battle/bullets.c @@ -22,16 +22,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void huntTarget(Bullet *b); static void checkCollisions(Bullet *b); +static void resizeDrawList(void); static Bullet bulletDef[BT_MAX]; -static Bullet *bulletsToDraw[MAX_BULLETS_TO_DRAW]; +static Bullet **bulletsToDraw; static int incomingMissile; +static int drawCapacity; void initBullets(void) { incomingMissile = 0; - - memset(bulletsToDraw, 0, sizeof(Bullet*) * MAX_BULLETS_TO_DRAW); + + drawCapacity = INITIAL_BULLET_DRAW_CAPACITY; + + bulletsToDraw = malloc(sizeof(Bullet*) * drawCapacity); + memset(bulletsToDraw, 0, sizeof(Bullet*) * drawCapacity); } void initBulletDefs(void) @@ -40,27 +45,27 @@ void initBulletDefs(void) char *text; int type; Bullet *def; - + memset(&bulletDef, 0, sizeof(Bullet) * BT_MAX); - + text = readFile(getFileLocation("data/battle/bullets.json")); - + root = cJSON_Parse(text); - + for (node = root->child ; node != NULL ; node = node->next) { type = lookup(cJSON_GetObjectItem(node, "type")->valuestring); - + def = &bulletDef[type]; def->type = type; def->damage = cJSON_GetObjectItem(node, "damage")->valueint; def->texture = getTexture(cJSON_GetObjectItem(node, "texture")->valuestring); def->sound = lookup(cJSON_GetObjectItem(node, "sound")->valuestring); def->flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring, NULL); - + SDL_QueryTexture(def->texture, NULL, NULL, &def->w, &def->h); } - + cJSON_Delete(root); free(text); } @@ -70,16 +75,16 @@ void doBullets(void) int i = 0; Bullet *b; Bullet *prev = &battle.bulletHead; - + incomingMissile = 0; - + memset(bulletsToDraw, 0, sizeof(Bullet*) * MAX_BULLETS_TO_DRAW); - + for (b = battle.bulletHead.next ; b != NULL ; b = b->next) { b->x += b->dx; b->y += b->dy; - + if (b->type == BT_ROCKET) { addMissileEngineEffect(b); @@ -87,29 +92,29 @@ void doBullets(void) else if (b->type == BT_MISSILE) { addMissileEngineEffect(b); - + huntTarget(b); - + if (b->target == player && player != NULL && player->health > 0) { incomingMissile = 1; } } - + checkCollisions(b); - + if (--b->life <= 0) { if (player != NULL && player->alive == ALIVE_ALIVE && b->type == BT_MISSILE && b->damage > 0 && b->target == player) { battle.stats[STAT_MISSILES_EVADED]++; } - + if (b == battle.bulletTail) { battle.bulletTail = prev; } - + prev->next = b->next; free(b); b = prev; @@ -119,25 +124,48 @@ void doBullets(void) if (collision(b->x - (b->w / 2) - battle.camera.x, b->y - (b->h / 2) - battle.camera.y, b->w * 2, b->h * 2, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)) { bulletsToDraw[i++] = b; - if (i >= MAX_BULLETS_TO_DRAW) + + if (i == drawCapacity) { - printf("Too many bullets to draw\n"); - exit(1); + resizeDrawList(); } } } - + prev = b; } } +static void resizeDrawList(void) +{ + int i, n; + Bullet **bullets; + + n = drawCapacity + INITIAL_BULLET_DRAW_CAPACITY; + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Resizing bullet draw capacity: %d -> %d\n", drawCapacity, n); + + bullets = malloc(sizeof(Bullet*) * n); + memset(bullets, 0, sizeof(Bullet*) * n); + + for (i = 0 ; i < drawCapacity ; i++) + { + bullets[i] = bulletsToDraw[i]; + } + + free(bulletsToDraw); + + bulletsToDraw = bullets; + drawCapacity = n; +} + static void checkCollisions(Bullet *b) { Entity *e, **candidates; int i; - + candidates = getAllEntsWithin(b->x - (b->w / 2), b->y - (b->h / 2), b->w, b->h, NULL); - + for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) { if (e->flags & EF_TAKES_DAMAGE) @@ -146,7 +174,7 @@ static void checkCollisions(Bullet *b) { continue; } - + if (b->owner != e && e->health > 0 && collision(b->x - b->w / 2, b->y - b->h / 2, b->w, b->h, e->x - e->w / 2, e->y - e->h / 2, e->w, e->h)) { if (b->owner->side == e->side) @@ -164,38 +192,38 @@ static void checkCollisions(Bullet *b) battle.stats[STAT_ROCKETS_HIT]++; } } - + if (!(e->flags & EF_IMMORTAL)) { damageFighter(e, b->damage, b->flags); } - + b->life = 0; b->damage = 0; - + if (b->flags & BF_EXPLODES) { addMissileExplosion(b); playBattleSound(SND_EXPLOSION_1, b->x, b->y); - + if (e == player) { battle.stats[STAT_MISSILES_STRUCK]++; } } - + /* assuming that health <= 0 will always mean killed */ if (e->health <= 0 && b->owner == player) { battle.stats[STAT_ENEMIES_KILLED_PLAYER]++; battle.stats[STAT_EPIC_KILL_STREAK]++; } - + if (b->owner == player && b->type == BT_MISSILE) { battle.stats[STAT_MISSILES_HIT]++; } - + return; } } @@ -206,12 +234,12 @@ void drawBullets(void) { int i; Bullet *b; - + for (i = 0, b = bulletsToDraw[i] ; b != NULL ; b = bulletsToDraw[++i]) { blitRotated(b->texture, b->x - battle.camera.x, b->y - battle.camera.y, b->angle); } - + if (incomingMissile && battle.stats[STAT_TIME] % FPS < 40) { drawText(SCREEN_WIDTH / 2, SCREEN_HEIGHT - 60, 18, TA_CENTER, colors.red, "WARNING: INCOMING MISSILE!"); @@ -222,17 +250,17 @@ static void faceTarget(Bullet *b) { int dir; int wantedAngle = getAngle(b->x, b->y, b->target->x, b->target->y); - + wantedAngle %= 360; - + if (fabs(wantedAngle - b->angle) > TURN_THRESHOLD) { dir = (wantedAngle - b->angle + 360) % 360 > 180 ? -1 : 1; - + b->angle += dir * TURN_SPEED; - + b->angle = mod(b->angle, 360); - + /* lower your speed while you're not at the correct angle */ b->dx *= 0.38; b->dy *= 0.38; @@ -243,14 +271,14 @@ static void applyMissileThrust(Bullet *b) { int maxSpeed; float v, thrust; - + b->dx += sin(TO_RAIDANS(b->angle)); b->dy += -cos(TO_RAIDANS(b->angle)); - + maxSpeed = MAX(MIN(b->target->speed + 1, 999), 3); - + thrust = sqrt((b->dx * b->dx) + (b->dy * b->dy)); - + if (thrust > maxSpeed) { v = (maxSpeed / sqrt(thrust)); @@ -264,9 +292,9 @@ static void huntTarget(Bullet *b) if (b->target != NULL && b->target->health > 0) { faceTarget(b); - + applyMissileThrust(b); - + if (b->target == player && battle.ecmTimer < FPS) { b->life = 0; @@ -283,16 +311,16 @@ static void huntTarget(Bullet *b) static Bullet *createBullet(int type, int x, int y, Entity *owner) { Bullet *b; - + b = malloc(sizeof(Bullet)); memset(b, 0, sizeof(Bullet)); battle.bulletTail->next = b; battle.bulletTail = b; - + memcpy(b, &bulletDef[type], sizeof(Bullet)); - + b->next = NULL; - + b->x = x; b->y = y; b->dx += sin(TO_RAIDANS(owner->angle)) * 16; @@ -301,7 +329,7 @@ static Bullet *createBullet(int type, int x, int y, Entity *owner) b->angle = owner->angle; b->owner = owner; b->target = owner->target; - + return b; } @@ -311,44 +339,44 @@ void fireGuns(Entity *owner) int i; float x, y; float c, s; - + for (i = 0 ; i < MAX_FIGHTER_GUNS ; i++) { if (owner->guns[i].type == owner->selectedGunType || (owner->guns[i].type != BT_NONE && owner->combinedGuns)) { s = sin(TO_RAIDANS(owner->angle)); c = cos(TO_RAIDANS(owner->angle)); - + x = (owner->guns[i].x * c) - (owner->guns[i].y * s); y = (owner->guns[i].x * s) + (owner->guns[i].y * c); - + x += owner->x; y += owner->y; - + b = createBullet(owner->guns[i].type, x, y, owner); - + if (owner == player) { battle.stats[STAT_SHOTS_FIRED]++; } } } - + owner->reload = owner->reloadTime; - + playBattleSound(b->sound, owner->x, owner->y); } void fireRocket(Entity *owner) { Bullet *b; - + b = createBullet(BT_ROCKET, owner->x, owner->y, owner); - + playBattleSound(b->sound, owner->x, owner->y); - + owner->reload = FPS; - + if (owner == player) { battle.stats[STAT_ROCKETS_FIRED]++; @@ -358,20 +386,20 @@ void fireRocket(Entity *owner) void fireMissile(Entity *owner) { Bullet *b; - + b = createBullet(BT_MISSILE, owner->x, owner->y, owner); - + b->life = FPS * 30; - + owner->missiles--; - + if (owner == player) { battle.stats[STAT_MISSILES_FIRED]++; } - + playBattleSound(b->sound, owner->x, owner->y); - + if (owner->target == player) { playSound(SND_INCOMING); @@ -380,4 +408,7 @@ void fireMissile(Entity *owner) void destroyBulletDefs(void) { + free(bulletsToDraw); + + bulletsToDraw = NULL; } diff --git a/src/battle/bullets.h b/src/battle/bullets.h index 70d66a9..6a42359 100644 --- a/src/battle/bullets.h +++ b/src/battle/bullets.h @@ -22,9 +22,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../json/cJSON.h" -#define TURN_SPEED 2 -#define TURN_THRESHOLD 3 -#define MAX_BULLETS_TO_DRAW 512 +#define TURN_SPEED 2 +#define TURN_THRESHOLD 3 +#define INITIAL_BULLET_DRAW_CAPACITY 32 extern SDL_Texture *getTexture(char *filename); extern void blitRotated(SDL_Texture *texture, int x, int y, float angle); diff --git a/src/battle/debris.c b/src/battle/debris.c index 95c984e..b9c3343 100644 --- a/src/battle/debris.c +++ b/src/battle/debris.c @@ -21,34 +21,39 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "debris.h" static void changeCourse(Debris *d); +static void resizeDrawList(void); -static Debris *debrisToDraw[MAX_DEBRIS_TO_DRAW]; +static Debris **debrisToDraw; static SDL_Texture *debrisTexture[MAX_DEBRIS_TEXTURES]; +static int drawCapacity; void initDebris(void) { - memset(debrisToDraw, 0, sizeof(Debris*) * MAX_DEBRIS_TO_DRAW); - debrisTexture[0] = getTexture("gfx/debris/debris1.png"); debrisTexture[1] = getTexture("gfx/debris/debris2.png"); debrisTexture[2] = getTexture("gfx/debris/debris3.png"); debrisTexture[3] = getTexture("gfx/debris/debris4.png"); debrisTexture[4] = getTexture("gfx/debris/debris5.png"); debrisTexture[5] = getTexture("gfx/debris/debris6.png"); + + drawCapacity = INITIAL_BULLET_DRAW_CAPACITY; + + debrisToDraw = malloc(sizeof(Bullet*) * drawCapacity); + memset(debrisToDraw, 0, sizeof(Bullet*) * drawCapacity); } void addDebris(int x, int y, int amount) { int i; Debris *d; - + for (i = 0 ; i < amount ; i++) { d = malloc(sizeof(Debris)); memset(d, 0, sizeof(Debris)); battle.debrisTail->next = d; battle.debrisTail = d; - + d->x = x; d->y = y; d->dx = rand() % 1000 - rand() % 1000; @@ -56,7 +61,7 @@ void addDebris(int x, int y, int amount) d->dy = rand() % 1000 - rand() % 1000; d->dy *= 0.01; d->health = FPS + (FPS * (rand() % 3)); - + d->texture = debrisTexture[rand() % MAX_DEBRIS_TEXTURES]; } } @@ -65,34 +70,34 @@ void doDebris(void) { int i; Debris *d, *prev; - + memset(debrisToDraw, 0, sizeof(Debris*) * MAX_DEBRIS_TO_DRAW); - + prev = &battle.debrisHead; - + i = 0; - + for (d = battle.debrisHead.next ; d != NULL ; d = d->next) { d->x += d->dx; d->y += d->dy; - + if (--d->thinkTime <= 0) { changeCourse(d); } - + d->angle = mod(d->angle + 1, 360); - + addDebrisFire(d->x, d->y); - + if (--d->health <= 0) { if (d == battle.debrisTail) { battle.debrisTail = prev; } - + prev->next = d->next; free(d); d = prev; @@ -102,30 +107,53 @@ void doDebris(void) if (collision(d->x - 16 - battle.camera.x, d->y - 16 - battle.camera.y, 32, 32, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)) { debrisToDraw[i++] = d; - if (i >= MAX_DEBRIS_TO_DRAW) + + if (i == drawCapacity) { - printf("Too much debris to draw\n"); - exit(1); + resizeDrawList(); } } } - + prev = d; } } +static void resizeDrawList(void) +{ + int i, n; + Debris **debris; + + n = drawCapacity + INITIAL_BULLET_DRAW_CAPACITY; + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Resizing debris draw capacity: %d -> %d\n", drawCapacity, n); + + debris = malloc(sizeof(Debris*) * n); + memset(debris, 0, sizeof(Debris*) * n); + + for (i = 0 ; i < drawCapacity ; i++) + { + debris[i] = debrisToDraw[i]; + } + + free(debrisToDraw); + + debrisToDraw = debris; + drawCapacity = n; +} + static void changeCourse(Debris *d) { float dir; - + dir = rand() % 25 - rand() % 25; dir *= 0.01; d->dx += dir; - + dir = rand() % 25 - rand() % 25; dir *= 0.01; d->dy += dir; - + d->thinkTime = 1 + (rand() % 5); } @@ -133,9 +161,16 @@ void drawDebris(void) { int i; Debris *d; - + for (i = 0, d = debrisToDraw[i] ; d != NULL ; d = debrisToDraw[++i]) { blitRotated(d->texture, d->x - battle.camera.x, d->y - battle.camera.y, d->angle); } } + +void destroyDebris(void) +{ + free(debrisToDraw); + + debrisToDraw = NULL; +} diff --git a/src/battle/debris.h b/src/battle/debris.h index 9c61feb..2ab0432 100644 --- a/src/battle/debris.h +++ b/src/battle/debris.h @@ -22,8 +22,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../json/cJSON.h" -#define MAX_DEBRIS_TO_DRAW 512 -#define MAX_DEBRIS_TEXTURES 6 +#define INITIAL_DEBRIS_DRAW_CAPACITY 32 +#define MAX_DEBRIS_TEXTURES 6 extern float mod(float n, float x); extern void blitRotated(SDL_Texture *texture, int x, int y, float angle); diff --git a/src/battle/effects.c b/src/battle/effects.c index 88662f0..0cdef59 100644 --- a/src/battle/effects.c +++ b/src/battle/effects.c @@ -26,87 +26,128 @@ static void setRandomShieldHue(Effect *e); static SDL_Texture *explosionTexture; static SDL_Texture *shieldHitTexture; static SDL_Texture *haloTexture; +static Effect **effectsToDraw; void initEffects(void) { explosionTexture = getTexture("gfx/effects/explosion.png"); shieldHitTexture = getTexture("gfx/effects/shieldHit.png"); haloTexture = getTexture("gfx/effects/halo.png"); + + drawCapacity = INITIAL_EFFECTS_TO_DRAW; + + effectsToDraw = malloc(sizeof(Effect*) * drawCapacity); } void doEffects(void) { Effect *e; Effect *prev = &battle.effectHead; - + for (e = battle.effectHead.next ; e != NULL ; e = e->next) { e->x += e->dx; e->y += e->dy; - + e->a -= (e->type != EFFECT_ECM) ? 1 : 3; e->a = MAX(0, e->a); - + e->health--; - + e->size += e->scaleAmount; - + if (e->health <= 0) { if (e == battle.effectTail) { battle.effectTail = prev; } - + prev->next = e->next; free(e); e = prev; } - + else + { + if (e->type == EFFECT_LINE || collision(e->x - (e->size / 2) - battle.camera.x, e->y - (b->size / 2) - battle.camera.y, e->size * 2, e->size * 2, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)) + { + effectsToDraw[i++] = e; + + if (i == drawCapacity) + { + resizeDrawList(); + } + } + } + prev = e; } } +static void resizeDrawList(void) +{ + int i, n; + Effect **effects; + + n = drawCapacity + INITIAL_EFFECT_DRAW_CAPACITY; + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Resizing effect draw capacity: %d -> %d\n", drawCapacity, n); + + effects = malloc(sizeof(Effect*) * n); + memset(effects, 0, sizeof(Effect*) * n); + + for (i = 0 ; i < drawCapacity ; i++) + { + effects[i] = effectsToDraw[i]; + } + + free(effectsToDraw); + + effectsToDraw = effects; + drawCapacity = n; +} + void drawEffects(void) { + int i; Effect *e; - + SDL_SetRenderDrawBlendMode(app.renderer, SDL_BLENDMODE_BLEND); - - for (e = battle.effectHead.next ; e != NULL ; e = e->next) + + for (i = 0, e = effectsToDraw[i] ; e != NULL ; e = effectsToDraw[++i]) { SDL_SetRenderDrawColor(app.renderer, e->r, e->g, e->b, e->a); - + SDL_SetTextureBlendMode(e->texture, SDL_BLENDMODE_ADD); SDL_SetTextureAlphaMod(e->texture, e->a); - + switch (e->type) { case EFFECT_POINT: SDL_RenderDrawPoint(app.renderer, e->x - battle.camera.x, e->y - battle.camera.y); break; - + case EFFECT_LINE: SDL_RenderDrawLine(app.renderer, e->x - battle.camera.x, e->y - battle.camera.y, e->x + (e->dx * 3) - battle.camera.x, e->y + (e->dy * 3) - battle.camera.y); break; - + case EFFECT_TEXTURE: SDL_SetTextureColorMod(e->texture, e->r, e->g, e->b); blitScaled(e->texture, e->x - battle.camera.x, e->y - battle.camera.y, e->size, e->size); break; - + case EFFECT_HALO: SDL_SetTextureColorMod(e->texture, e->r, e->g, e->b); blitScaled(e->texture, e->x - battle.camera.x - (e->size / 2), e->y - battle.camera.y - (e->size / 2), e->size, e->size); break; - + case EFFECT_ECM: SDL_SetTextureColorMod(e->texture, e->r, e->g, e->b); blitScaled(e->texture, SCREEN_WIDTH / 2 - (e->size / 2), SCREEN_HEIGHT / 2 - (e->size / 2), e->size, e->size); break; } } - + SDL_SetRenderDrawBlendMode(app.renderer, SDL_BLENDMODE_NONE); } @@ -120,24 +161,24 @@ void drawShieldHitEffect(Entity *e) void addSmallFighterExplosion(void) { Effect *e; - + e = malloc(sizeof(Effect)); memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_TEXTURE; - + e->x = self->x + (rand() % 16 - rand() % 16); e->y = self->y + (rand() % 16 - rand() % 16); e->texture = explosionTexture; e->size = 32; - + setRandomFlameHue(e); - + e->a = 128 + (rand() % 128); e->health = e->a; - + e->x -= e->size / 2; e->y -= e->size / 2; } @@ -145,24 +186,24 @@ void addSmallFighterExplosion(void) void addDebrisFire(int x, int y) { Effect *e; - + e = malloc(sizeof(Effect)); memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_TEXTURE; - + e->x = x + (rand() % 8 - rand() % 8); e->y = y + (rand() % 8 - rand() % 8); e->texture = explosionTexture; e->size = 4 + rand() % 12; - + setRandomFlameHue(e); - + e->a = rand() % 256; e->health = e->a; - + e->x -= e->size / 2; e->y -= e->size / 2; } @@ -171,16 +212,16 @@ void addSmallExplosion(void) { int i; Effect *e; - + for (i = 0 ; i < 32 ; i++) { e = malloc(sizeof(Effect)); memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_TEXTURE; - + e->x = self->x; e->y = self->y; e->dx = (rand() % 25) - (rand() % 25); @@ -190,23 +231,23 @@ void addSmallExplosion(void) e->texture = explosionTexture; e->size = 32 + (rand() % 64); e->r = 255; - + setRandomFlameHue(e); - + e->a = 128 + (rand() % 128); e->health = e->a; - + e->x -= e->size / 2; e->y -= e->size / 2; } - + for (i = 0 ; i < 96 ; i++) { e = malloc(sizeof(Effect)); memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_LINE; e->x = self->x; e->y = self->y; @@ -214,10 +255,10 @@ void addSmallExplosion(void) e->dx *= 0.1; e->dy = rand() % 64 - rand() % 64; e->dy *= 0.1; - + e->a = 128; e->health = e->a; - + setRandomFlameHue(e); } } @@ -226,16 +267,16 @@ void addMissileExplosion(Bullet *b) { int i; Effect *e; - + for (i = 0 ; i < 8 ; i++) { e = malloc(sizeof(Effect)); memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_TEXTURE; - + e->x = b->x; e->y = b->y; e->dx = (rand() % 25) - (rand() % 25); @@ -245,23 +286,23 @@ void addMissileExplosion(Bullet *b) e->texture = explosionTexture; e->size = 32 + (rand() % 64); e->r = 255; - + setRandomFlameHue(e); - + e->a = 128 + (rand() % 128); e->health = e->a; - + e->x -= e->size / 2; e->y -= e->size / 2; } - + for (i = 0 ; i < 24 ; i++) { e = malloc(sizeof(Effect)); memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_LINE; e->x = b->x; e->y = b->y; @@ -269,10 +310,10 @@ void addMissileExplosion(Bullet *b) e->dx *= 0.1; e->dy = rand() % 64 - rand() % 64; e->dy *= 0.1; - + e->a = 128; e->health = e->a; - + setRandomFlameHue(e); } } @@ -282,33 +323,33 @@ void addEngineEffect(void) Effect *e; float c, s; int h; - + e = malloc(sizeof(Effect)); memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_TEXTURE; - + s = sin(TO_RAIDANS(self->angle)); c = cos(TO_RAIDANS(self->angle)); - + h = self->h / 2; - + e->x = -(h * s) + self->x; e->y = (h * c) + self->y; - + e->x += rand() % 4 - rand() % 4; - + e->texture = explosionTexture; e->size = 16; e->r = 128; e->g = 128; e->b = 255; e->a = 64; - + e->health = e->a; - + e->x -= e->size / 2; e->y -= e->size / 2; } @@ -316,32 +357,32 @@ void addEngineEffect(void) void addLargeEngineEffect(void) { Effect *e; - + e = malloc(sizeof(Effect)); memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_TEXTURE; - + e->x = self->x; e->y = self->y; - + e->x -= sin(TO_RAIDANS(self->angle)) * 16; e->y -= -cos(TO_RAIDANS(self->angle)) * 16; - + e->x += rand() % 4; e->x -= rand() % 4; - + e->texture = explosionTexture; e->size = 64; e->r = 128; e->g = 128; e->b = 255; e->a = 64; - + e->health = e->a; - + e->x -= e->size / 2; e->y -= e->size / 2; } @@ -349,30 +390,30 @@ void addLargeEngineEffect(void) void addMissileEngineEffect(Bullet *b) { Effect *e; - + e = malloc(sizeof(Effect)); memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_TEXTURE; - + e->x = b->x; e->y = b->y; - + e->x -= sin(TO_RAIDANS(b->angle)) * 10; e->y -= -cos(TO_RAIDANS(b->angle)) * 10; - + e->x += rand() % 4; e->x -= rand() % 4; - + e->texture = explosionTexture; e->size = 12; setRandomFlameHue(e); e->a = 128; - + e->health = e->a; - + e->x -= e->size / 2; e->y -= e->size / 2; } @@ -381,14 +422,14 @@ void addShieldSplinterEffect(Entity *ent) { int i; Effect *e; - + for (i = 0 ; i < 48 ; i++) { e = malloc(sizeof(Effect)); memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_LINE; e->x = ent->x; e->y = ent->y; @@ -396,9 +437,9 @@ void addShieldSplinterEffect(Entity *ent) e->dx *= 0.1; e->dy = rand() % 64 - rand() % 64; e->dy *= 0.1; - + e->a = 255; - + setRandomShieldHue(e); } } @@ -407,27 +448,27 @@ void addECMEffect(Entity *ent) { int i; Effect *e; - + for (i = 0 ; i < 3 ; i++) { e = malloc(sizeof(Effect)); - + memset(e, 0, sizeof(Effect)); battle.effectTail->next = e; battle.effectTail = e; - + e->type = EFFECT_ECM; e->x = ent->x; e->y = ent->y; e->size = i * 4; e->scaleAmount = 5; e->texture = haloTexture; - + e->r = 128; e->g = 128 + (i * 64); e->b = 255; e->a = 255; - + e->health = 255; } } @@ -435,20 +476,20 @@ void addECMEffect(Entity *ent) static void setRandomFlameHue(Effect *e) { e->r = 255; - + switch (rand() % 4) { case 0: break; - + case 1: e->g = 128; break; - + case 2: e->g = 255; break; - + case 3: e->g = e->b = 255; break; @@ -458,23 +499,30 @@ static void setRandomFlameHue(Effect *e) static void setRandomShieldHue(Effect *e) { e->b = 255; - + switch (rand() % 4) { case 0: e->g = 128; break; - + case 1: e->g = 196; break; - + case 2: e->g = 255; break; - + case 3: e->r = e->g = 255; break; } } + +void destroyEffects(void) +{ + free(effectsToDraw); + + effectsToDraw = NULL; +} diff --git a/src/battle/effects.h b/src/battle/effects.h index 27b1d33..a938b6c 100644 --- a/src/battle/effects.h +++ b/src/battle/effects.h @@ -20,6 +20,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../common.h" +#define INITIAL_EFFECTS_TO_DRAW 128 + extern void blitScaled(SDL_Texture *texture, int x, int y, int w, int h); extern SDL_Texture *getTexture(char *name); extern void blit(SDL_Texture *t, int x, int y, int center);