diff --git a/common.mk b/common.mk index 29c000a..9ba374c 100644 --- a/common.mk +++ b/common.mk @@ -17,7 +17,7 @@ OBJS += init.o input.o io.o items.o OBJS += lookup.o OBJS += main.o map.o maths.o OBJS += objectives.o -OBJS += player.o +OBJS += particles.o player.o OBJS += quadtree.o OBJS += sound.o sprites.o OBJS += text.o textures.o title.o triggers.o diff --git a/src/combat/combat.c b/src/combat/combat.c index 617302c..bb29e8a 100644 --- a/src/combat/combat.c +++ b/src/combat/combat.c @@ -27,7 +27,7 @@ void preFire(Entity *e) { if (e->flags & EF_WEIGHTLESS) { - if (world.bob->y < e->y && e->isOnGround && (int) (rand() * 4) == 0) + if (world.bob->y < e->y && e->isOnGround && (int) (rand() % 4) == 0) { e->dy = JUMP_POWER; } diff --git a/src/defs.h b/src/defs.h index 588a93f..bf4290e 100644 --- a/src/defs.h +++ b/src/defs.h @@ -140,6 +140,19 @@ enum MS_MISSING_HEART_CELL }; +enum +{ + PLANE_BACKGROUND, + PLANE_FOREGROUND +}; + +enum +{ + PT_LINE, + PT_POINT, + PT_TEXTURED +}; + enum { MSG_STANDARD, diff --git a/src/structs.h b/src/structs.h index ab21947..6736ac1 100644 --- a/src/structs.h +++ b/src/structs.h @@ -25,6 +25,8 @@ typedef struct Entity Entity; typedef struct Objective Objective; typedef struct Trigger Trigger; typedef struct Marker Marker; +typedef struct Particle Particle; +typedef struct Sprite Sprite; typedef struct { int debug; @@ -196,10 +198,36 @@ struct Quadtree { Quadtree *node[4]; }; +struct Sprite { + int numFrames; + int times[1]; +}; + +struct Particle { + int type; + int plane; + float health; + float x; + float y; + float dx; + float dy; + int size; + float r; + float g; + float b; + int spriteIndex; + double spriteTime; + int spriteFrame; + int destroyAfterAnim; + int onScreen; + Particle *next; +}; + typedef struct { Entity *bob; Map map; Entity entityHead, *entityTail; + Particle particleHead, *particleTail; int allObjectivesComplete; int currentStatus; int isBossMission; diff --git a/src/system/sprites.c b/src/system/sprites.c index a763955..8a71405 100644 --- a/src/system/sprites.c +++ b/src/system/sprites.c @@ -24,3 +24,8 @@ int getSpriteIndex(char *name) { return 0; } + +Sprite *getSprite(int i) +{ + return NULL; +} diff --git a/src/util/maths.c b/src/util/maths.c index 2ef90eb..d77dd2b 100644 --- a/src/util/maths.c +++ b/src/util/maths.c @@ -30,6 +30,11 @@ int rrnd(int low, int high) return low + rand() % ((high - low) + 1); } +double randF(void) +{ + return (double)rand() / (double)((unsigned)RAND_MAX + 1); +} + int getPercent(float current, float total) { return (current / total) * 100; @@ -77,6 +82,21 @@ void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy) *dy /= steps; } +float wrap(float value, float low, float high) +{ + if (value < low) + { + return high; + } + + if (value > high) + { + return low; + } + + return value; +} + int lineIntersectsRect(SDL_Rect r, int x1, int y1, int x2, int y2) { return 0; diff --git a/src/world/particles.c b/src/world/particles.c new file mode 100644 index 0000000..1046dc6 --- /dev/null +++ b/src/world/particles.c @@ -0,0 +1,268 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "particles.h" + +static void animate(Particle *p); +static Particle *createParticle(void); + +static int bloodSprite[3]; +static int explosionSprite[2]; +static int flameSprite; +static int smokeSprite; +static int teleportStarSprite; + +void initParticles(void) +{ + bloodSprite[0] = getSpriteIndex("Blood1"); + bloodSprite[1] = getSpriteIndex("Blood2"); + bloodSprite[2] = getSpriteIndex("Blood3"); + + explosionSprite[0] = getSpriteIndex("Explosion1"); + explosionSprite[1] = getSpriteIndex("Explosion2"); + + flameSprite = getSpriteIndex("Flame"); + smokeSprite = getSpriteIndex("Smoke"); + + teleportStarSprite = getSpriteIndex("TeleportStar"); +} + +void addBlood(float x, float y) +{ + Particle *p; + + p = createParticle(); + p->type = PT_TEXTURED; + p->x = x; + p->y = y; + p->size = 1; + p->dy = 1; + p->health = rrnd(5, 30); + p->spriteIndex = bloodSprite[(int) (rand() % 3)]; +} + +void addSparkParticles(float x, float y) +{ + Particle *p; + int i; + float c; + + for (i = 0; i < 3; i++) + { + p = createParticle(); + p->x = x; + p->y = y; + p->dx = rand() % 300 - rand() % 300; + p->dx /= 100; + p->dy = rand() % 300 - rand() % 300; + p->dy /= 100; + p->health = rrnd(5, 30); + + c = 50 + (rand() % 50); + c /= 100; + + p->r = p->g = p->b = c; + } +} + +void addSmokeParticles(float x, float y) +{ + Particle *p; + + p = createParticle(); + p->type = PT_TEXTURED; + p->x = x; + p->y = y; + p->size = 1; + p->health = rrnd(5, 30); + p->spriteIndex = smokeSprite; + p->spriteTime = 5; + p->spriteFrame = 0; + p->destroyAfterAnim = 1; +} + +void addFlameParticles(float x, float y) +{ + Particle *p; + + p = createParticle(); + p->type = PT_TEXTURED; + p->x = x; + p->y = y; + p->size = 1; + p->health = rrnd(5, 30); + p->spriteIndex = flameSprite; + p->spriteTime = 5; + p->spriteFrame = 0; + p->destroyAfterAnim = 1; +} + + +void addExplosionParticles(float x, float y, float radius, int amount) +{ + int i; + Particle *p; + + for (i = 0; i < amount; i++) + { + p = createParticle(); + p->type = PT_TEXTURED; + p->x = x; + p->y = y; + p->dx = (randF() - randF()) * radius; + p->dx /= 5; + p->dy = (randF() - randF()) * radius; + p->dy /= 5; + p->health = rrnd(FPS / 4, FPS); + p->spriteTime = 5; + p->spriteFrame = 0; + p->spriteIndex = explosionSprite[i % 2]; + } +} + +void addTeleportStar(float x, float y) +{ + Particle *p; + + p = createParticle(); + p->type = PT_TEXTURED; + p->x = x; + p->y = y; + p->dx = ((randF() - randF()) * 4); + p->dy = ((randF() - randF()) * 4); + p->health = rrnd(FPS / 4, FPS); + p->r = p->g = p->b = 1.0f; + p->spriteIndex = teleportStarSprite; + p->spriteFrame = (rand() % 12); + p->plane = PLANE_FOREGROUND; +} + +void addTeleportStars(Entity *e) +{ + int x, y, i; + + x = (int) (e->x + (e->w / 2)); + y = (int) (e->y + (e->h / 2)); + + for (i = 0 ; i < 32 ; i++) + { + addTeleportStar(x, y); + } +} + +void addMIATeleportStars(float x, float y) +{ + Particle *p; + + p = createParticle(); + p->type = PT_TEXTURED; + p->x = x; + p->y = y; + p->dy = -(1 + (rand()) % 4); + p->health = FPS * 3; + p->r = p->g = p->b = 1.0f; + p->spriteIndex = teleportStarSprite; + p->spriteFrame = (rand() % 12); + p->plane = PLANE_FOREGROUND; +} + +void addTeleporterEffect(float x, float y) +{ + Particle *p; + + p = createParticle(); + p->type = PT_TEXTURED; + p->x = x; + p->y = y; + p->dx = 0; + p->dy = -(randF() * 2); + p->health = rrnd(FPS / 4, FPS); + p->r = p->g = p->b = 1.0f; + p->spriteIndex = teleportStarSprite; + p->spriteFrame = (rand() % 12); +} + +void doParticles(void) +{ + Particle *p, *prev; + int camMidX, camMidY; + + camMidX = camera.x + (SCREEN_WIDTH / 2); + camMidY = camera.y + (SCREEN_HEIGHT / 2); + + prev = &world.particleHead; + + for (p = world.particleHead.next ; p != NULL ; p = p->next) + { + animate(p); + + p->x += p->dx; + p->y += p->dy; + + p->onScreen = 0; + + if (--p->health <= 0 || (p->destroyAfterAnim && p->spriteTime == -1)) + { + if (p == world.particleTail) + { + world.particleTail = prev; + } + + prev->next = p->next; + free(p); + p = prev; + } + else if (getDistance(camMidX, camMidY, p->x, p->y) < SCREEN_WIDTH) + { + p->onScreen = 1; + } + + prev = p; + } +} + +static void animate(Particle *p) +{ + Sprite *s; + + if (p->spriteTime != -1) + { + p->spriteTime--; + + if (p->spriteTime <= 0) + { + s = getSprite(p->spriteIndex); + p->spriteFrame = (int) wrap(++p->spriteFrame, 0, s->numFrames); + p->spriteTime = s->times[p->spriteFrame]; + } + } +} + +static Particle *createParticle(void) +{ + Particle *p; + + p = malloc(sizeof(Particle)); + memset(p, 0, sizeof(Particle)); + world.particleTail->next = p; + world.particleTail = p; + + return p; +} diff --git a/src/world/particles.h b/src/world/particles.h new file mode 100644 index 0000000..d78cfa9 --- /dev/null +++ b/src/world/particles.h @@ -0,0 +1,31 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +extern Sprite *getSprite(int i); +extern int getSpriteIndex(char *name); +extern float wrap(float value, float low, float high); +extern int rrnd(int low, int high); +extern double randF(void); +extern int getDistance(int x1, int y1, int x2, int y2); + +extern Camera camera; +extern World world;