From de29b11a88dbdd3af0824e59b51528b91ee73c54 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Thu, 30 Nov 2017 22:49:38 +0100 Subject: First commit. Version works on Linux (keyboard only, not configurable) --- src/weapon.c | 601 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 601 insertions(+) create mode 100644 src/weapon.c (limited to 'src/weapon.c') diff --git a/src/weapon.c b/src/weapon.c new file mode 100644 index 0000000..999c7b1 --- /dev/null +++ b/src/weapon.c @@ -0,0 +1,601 @@ +#include "weapon.h" +#include +#include +#include +#include "hero.h" +#include "PHL.h" +#include "game.h" +#include "object.h" + +void updateWeaponMask(Weapon* w); + +void addWeapon(int type, int x, int y) +{ + if (heroAmmo > 0 || type == SWORD) { + int i, weaponcount = 0; + + //Count + for (i = 0; i < MAX_WEAPONS; i++) { + if (weapons[i] != NULL) { + if (weapons[i]->type != SWORD) { + weaponcount += 1; + } + } + } + + if (type == BOMB) { //Bombs have one lower limit + weaponcount += 1; + } + + if (type == SWORD || weaponcount < (2 + hasItem[15])) { //3 projectiles if have green scroll + + if (type != SWORD) { + PHL_PlaySound(sounds[sndShot01], CHN_WEAPONS); + } + + for (i = 0; i < MAX_WEAPONS; i++) { + if (weapons[i] == NULL) { + Weapon* w = malloc(sizeof *w); + w->id = i; + w->type = type; + + w->x = x; + w->y = y; + + w->hsp = 0; + w->vsp = 0; + + w->grav = 0; + w->imageIndex = 0; + + w->power = 1; + w->timer = 0; + w->state = 0; + w->cooldown = 0; + w->hitflag = 0; + + w->dir = getHeroDirection(); + + w->weaponMask.circle = 0; + w->weaponMask.unused = 0; + w->weaponMask.x = 0; + w->weaponMask.y = 0; + w->weaponMask.w = 10; + w->weaponMask.h = 10; + + if (w->type == SWORD) + { + w->weaponMask.unused = 1; + }else if (w->type == ARROW) + { + w->hsp = 8 * getHeroDirection(); + w->weaponMask.y += 16; + w->weaponMask.w = 32; + w->weaponMask.h = 6; + }else if (w->type == AXE) + { + w->hsp = 2 * getHeroDirection(); + w->vsp = -6; + w->grav = 0.2; + w->weaponMask.w = w->weaponMask.h = 24; + w->y += (40 - getHeroMask().h) - ((40 - w->weaponMask.h) / 2); + w->weaponMask.x = w->x + ((40 - w->weaponMask.w) / 2); + w->weaponMask.y = w->y + ((40 - w->weaponMask.h) / 2); + + }else if (w->type == BOOMERANG) + { + w->x += 20; + w->y += 20; + updateWeaponMask(w); + w->weaponMask.circle = 1; + w->weaponMask.w = 16; + + w->hsp = 6 * getHeroDirection(); + w->vsp = getHeroDirection(); //Vsp is used for starting direction + w->timer = 120; + }else if (w->type == FIREBALL) + { + w->vsp = -2; + w->grav = 0.1; + + w->hsp = 2 * getHeroDirection(); + + w->x += 20; + w->y += 20; + + w->weaponMask.circle = 1; + w->weaponMask.w = 15; + updateWeaponMask(w); + + Mask tempMask; + tempMask.circle = tempMask.unused = 0; + tempMask.y = w->y - w->weaponMask.w; + tempMask.x = w->x - w->weaponMask.w; + tempMask.w = tempMask.h = w->weaponMask.w * 2; + + PHL_Rect collide = getTileCollision(1, tempMask); + if (collide.x == -1) { + collide = getTileCollision(3, tempMask); + } + if (collide.x != -1) { + w->y = collide.y + 40 + w->weaponMask.w; + } + + }else if (w->type == BOMB) + { + w->dir = 0; + w->vsp = -2; + w->grav = 0.1; + w->hsp = getHeroDirection(); + + w->weaponMask.unused = 1; + + Mask tempMask; + tempMask.y = w->y + 8; + tempMask.x = w->x + 8; + tempMask.w = tempMask.h = 24; + tempMask.circle = tempMask.unused = 0; + + PHL_Rect collide = getTileCollision(1, tempMask); + if (collide.x == -1) { + collide = getTileCollision(3, tempMask); + } + if (collide.x != -1) { + w->y = collide.y + 40 - 8; + } + } + + updateWeaponMask(w); + + weapons[i] = w; + i = MAX_WEAPONS; + + if (type != SWORD) { + heroAmmo -= 1; + } + } + } + } + } +} + +//When a weapon lands a hit +void weaponHit(Weapon* w) +{ + //w->cooldown = 15; + w->hitflag = 1; + + if (w->type == SWORD) { + createEffect(1, w->weaponMask.x + (w->weaponMask.w / 2) - 10 + (rand() % 20) - 10, w->weaponMask.y + (w->weaponMask.h / 2) - 10 + (rand() % 20) - 10); + PHL_PlaySound(sounds[sndHit02], CHN_WEAPONS); + }else if (w->type == ARROW || w->type == AXE) { + PHL_PlaySound(sounds[sndPi02], CHN_WEAPONS); + createEffect(1, w->x, w->y); + weaponDestroy(w->id); + }else if (w->type == BOOMERANG) { + PHL_PlaySound(sounds[sndPi02], CHN_WEAPONS); + createEffect(1, w->x, w->y - 40 + (rand() % 40) + 1); + }else if (w->type == FIREBALL) { + PHL_PlaySound(sounds[sndPi02], CHN_WEAPONS); + createEffect(1, w->x - 20, w->y - 20); + //weaponDestroy(w->id); + }else if (w->type == BOMB) { + + } +} + +void weaponStep(Weapon* w) +{ + char dead = 0; + + if (w->cooldown > 0) { + w->cooldown -= 1; + } + + if (w->hitflag == 1) { + w->hitflag = 0; + w->cooldown = 15; + } + + if (w->type == SWORD) + { + double imgind = getHeroImageIndex(); + if ((getHeroState() != 1 && getHeroState() != 5) || imgind >= 4) { //Not slashing + dead = 1; + } + + w->x = herox; + w->y = heroy; + updateWeaponMask(w); + + }else if (w->type == ARROW) + { + //Yes, this does have to be done before movement + //Destroy if out of view or collides with wall + if (w->x > 640 || w->x + 40 < 0 || checkTileCollision(1, w->weaponMask) == 1) { + weaponHit(w); + } + + w->x += w->hsp; + updateWeaponMask(w); + }else if (w->type == AXE) + { + w->y += w->vsp; + w->vsp += w->grav; + updateWeaponMask(w); + + PHL_Rect collide = getTileCollisionWeapon(1, w->weaponMask); + if (collide.x == -1) { + collide = getTileCollision(3, w->weaponMask); + } + + if (collide.x != -1) { + if (w->vsp <= 0) { + w->y = collide.y + 40 - ((40 - w->weaponMask.h) / 2); + w->vsp = 0; + }else{ + weaponHit(w); + } + } + + w->x += w->hsp; + updateWeaponMask(w); + + collide = getTileCollisionWeapon(1, w->weaponMask); + + if (collide.x != -1) { + if (w->hsp > 0) { + w->x = collide.x - 40 + ((40 - w->weaponMask.w) / 2); + }else{ + w->x = collide.x + 40 - ((40 - w->weaponMask.w) / 2); + } + } + + //Animate + { + w->imageIndex += 0.33; + if (w->imageIndex >= 8) { + w->imageIndex -= 8; + } + } + + if (w->x > 640 || w->x + 40 < 0 || w->y > 520) { + dead = 1; + } + }else if (w->type == BOOMERANG) + { + w->x += w->hsp; + w->hsp -= 0.125 * (w->vsp); //Vsp is recycled to be the starting direction + if (w->hsp >= 6) { + w->hsp = 6; + } + if (w->hsp <= -6) { + w->hsp = -6; + } + + w->dir = 1; + if (w->hsp < 0) { + w->dir = -1; + } + + w->y = heroy + 20; + updateWeaponMask(w); + + w->imageIndex -= (0.33 * w->vsp); + if (w->imageIndex < 0) { + w->imageIndex += 8; + } + if (w->imageIndex >= 8) { + w->imageIndex -= 8; + } + + w->timer -= 1; + if (w->timer <= 0) { + createEffect(5, w->x, w->y); + dead = 1; + } + }else if (w->type == FIREBALL) + { + //Move vertically + w->y += w->vsp; + w->vsp += w->grav; + + Mask tempMask; + tempMask.circle = tempMask.unused = 0; + tempMask.y = w->y - w->weaponMask.w; + tempMask.w = tempMask.h = w->weaponMask.w * 2; + tempMask.x = w->x - w->weaponMask.w; + + //Check vertical collision + PHL_Rect collide = getTileCollisionWeapon(1, tempMask); + if (collide.x == -1) { + collide = getTileCollisionWeapon(3, tempMask); + } + + if (collide.x != -1) { + if (w->vsp <= 0) { + w->y = collide.y + 40 + w->weaponMask.w; + w->vsp = 0; + }else{ + w->y = collide.y - w->weaponMask.w; + if (w->timer == 0) { + w->vsp = -2; + PHL_PlaySound(sounds[sndPi02], 2); + }else if (w->timer == 1) { + w->vsp = -1; + PHL_PlaySound(sounds[sndPi02], 2); + }else{ + weaponHit(w); + dead = 1; + } + w->timer += 1; + } + + tempMask.y = w->y - w->weaponMask.w; + } + + //Move horizontally + w->x += w->hsp; + tempMask.x = w->x - w->weaponMask.w; + + //Check horizontal collision + collide = getTileCollisionWeapon(1, tempMask); + if (collide.x != -1) { + if (w->hsp > 0) { + w->x = collide.x - (tempMask.w / 2) ; + }else{ + w->x = collide.x + 40 + (tempMask.w / 2); + } + w->hsp *= -1; + tempMask.x = w->x - w->weaponMask.w; + + w->dir = 1; + if (w->hsp < 0) { + w->dir = -1; + } + } + + updateWeaponMask(w); + + //animate + { + w->imageIndex += 0.5; + if (w->imageIndex >= 8) { + w->imageIndex -= 8; + } + } + + if (w->x > 640 || w->x + 40 < 0 || w->y > 520) { + dead = 1; + } + }else if (w->type == BOMB) + { + if (w->state == 0) { //Bouncing bomb + Mask tempMask; + tempMask.y = w->y + 8; + tempMask.w = tempMask.h = 24; + tempMask.circle = tempMask.unused = 0; + + w->x += w->hsp; + tempMask.x = w->x + 8; + PHL_Rect collide = getTileCollision(1, tempMask); + if (collide.x != -1) { + if (w->hsp > 0) { + w->x = collide.x - 40 + 8; + }else{ + w->x = collide.x + 40 - 8; + } + w->hsp *= -1; + tempMask.x = w->x + 8; + } + + w->imageIndex -= (0.33 * w->hsp); + if (w->imageIndex < 0) { + w->imageIndex += 8; + } + if (w->imageIndex >= 8) { + w->imageIndex -= 8; + } + + w->y += w->vsp; + w->vsp += w->grav; + + tempMask.y = w->y + 8; + collide = getTileCollision(1, tempMask); + if (collide.x == -1) { + collide = getTileCollision(3, tempMask); + } + if (collide.x != -1) { + if (w->vsp <= 0) { + w->y = collide.y + 40 - 8; + w->vsp = 0; + }else{ + w->y = collide.y - 40 + 8; + if (w->timer == 0) { + w->vsp = -2; + PHL_PlaySound(sounds[sndPi02], CHN_WEAPONS); + }else if (w->timer == 1) { + w->vsp = -1; + PHL_PlaySound(sounds[sndPi02], CHN_WEAPONS); + }else{ + w->state = 1; + w->imageIndex = 0; + w->weaponMask.unused = 0; + PHL_PlaySound(sounds[sndBom03], CHN_WEAPONS); + } + w->timer += 1; + } + } + + updateWeaponMask(w); + + if (w->x > 640 || w->x + 40 < 0 || w->y > 520) { + //weaponDestroy(w->id); + dead = 1; + } + } + else if (w->state == 1) { //Explosion + updateWeaponMask(w); + + if (checkCollision(getHeroMask(), w->weaponMask) == 1) { + heroHit(20, w->x + 20); + } + + w->imageIndex += 0.34; + if (w->imageIndex >= 11) { + //weaponDestroy(w->id); + dead = 1; + } + } + } + + if (dead == 1) { + weaponDestroy(w->id); + } +} + +void weaponDraw(Weapon* w) +{ + if (w->type == SWORD) { + //PHL_DrawMask(w->weaponMask); + + //Draw Sword + double imgind = getHeroImageIndex(); + int dir = getHeroDirection(); + if (imgind < 4) { + int swordx = 0, swordy = 0; + int scropx = 40 * (int)floor(imgind), + scropy = 240; + if (imgind < 1) { + swordy = -16; + swordx = -8; + }else if (imgind < 2) { + swordy = -8; + swordx = 24; + }else if (imgind < 4) { + swordy = 14; + swordx = 26; + } + + if (dir == -1) { + swordx *= -1; + scropx += 160; + } + + if (getHeroInvincible() % 2 == 0) { + PHL_DrawSurfacePart(herox - 20 + swordx, heroy + swordy, scropx, scropy, 40, 40, images[imgHero]); + } + + //PHL_DrawSurfacePart(w->x, w->y, 0, 240, 40, 40, images[imgHero]); + } + + } + else if (w->type == ARROW) + { + int dx = 240; + if (w->hsp <= 0) { + dx += 40; + } + PHL_DrawSurfacePart(w->x, w->y, dx, 200, 40, 40, images[imgMisc20]); + }else if (w->type == AXE) + { + int dx = 0; + if (w->hsp <= 0) { + dx = 320; + } + PHL_DrawSurfacePart(w->x, w->y, dx + ((int)w->imageIndex * 40), 240, 40, 40, images[imgMisc20]); + }else if (w->type == BOOMERANG) + { + PHL_DrawSurfacePart(w->x - 20, w->y - 20, 320 + ((int)w->imageIndex * 40), 160, 40, 40, images[imgMisc20]); + }else if (w->type == FIREBALL) + { + int dx = 0; + if (w->hsp <= 0) { + dx = 320; + } + PHL_DrawSurfacePart(w->x - 20, w->y - 20, dx + ((int)w->imageIndex * 40), 280, 40, 40, images[imgMisc20]); + }else if (w->type == BOMB) + { + if (w->state == 0) { + PHL_DrawSurfacePart(w->x, w->y, (int)w->imageIndex * 40, 160, 40, 40, images[imgMisc20]); + } + else if (w->state == 1) { + //PHL_DrawMask(w->weaponMask); + + int cx = (int)w->imageIndex * 128; + int cy = 0; + while (cx >= 640) { + cx -= 640; + cy += 96; + } + PHL_DrawSurfacePart(w->weaponMask.x, w->weaponMask.y, cx, cy, 128, 96, images[imgExplosion]); + } + } + //PHL_DrawMask(w->weaponMask); +} + +void updateWeaponMask(Weapon* w) +{ + if (w->type == SWORD) { + //Sword mask + //swordMask.unused = 0; + double imgind = getHeroImageIndex(); + int dir = getHeroDirection(); + w->weaponMask.unused = 0; + + if (imgind < 1) { + /*w->weaponMask.w = 8; + w->weaponMask.h = 24; + w->weaponMask.x = herox - 4 + (dir * -8); //herox - 20 + (direction * -8) + 16 + w->weaponMask.y = heroy - 8; //heroy - 16 + 8 + */ + w->weaponMask.unused = 1; + }else if (imgind < 2) { + w->weaponMask.w = 32; + w->weaponMask.h = 38; + w->weaponMask.x = herox - 20 + (dir * 28) + 4; + w->weaponMask.y = heroy - 6; + }else if (imgind < 3) { + w->weaponMask.w = 24; + w->weaponMask.h = 20; + w->weaponMask.x = herox - 20 + (dir * 26) + 8; + w->weaponMask.y = heroy + 18; + }else if (imgind < 4) { + w->weaponMask.w = 24; + w->weaponMask.h = 6; + w->weaponMask.x = herox - 20 + (dir * 26) + 8; + w->weaponMask.y = heroy + 30; + } + }else if (w->type == ARROW) { + w->weaponMask.x = w->x; + w->weaponMask.y = w->y + 16; + if (w->hsp > 0) { + w->weaponMask.x += 8; + } + + }else if (w->type == AXE) { + w->weaponMask.x = w->x + ((40 - w->weaponMask.w) / 2); + w->weaponMask.y = w->y + ((40 - w->weaponMask.h) / 2); + }else if (w->type == BOOMERANG) { + w->weaponMask.x = w->x; + w->weaponMask.y = w->y; + }else if (w->type == FIREBALL) { + w->weaponMask.x = w->x; + w->weaponMask.y = w->y; + }else if (w->type == BOMB) { + if (w->state == 1) { //Update mask on explosion + w->weaponMask.x = w->x - 44; + w->weaponMask.y = w->y - 44 - 8; + w->weaponMask.w = 128; + w->weaponMask.h = 90; //Hits blocks below + } + } +} + +void weaponDestroy(int id) +{ + if (weapons[id] != NULL) { + free(weapons[id]); + } + weapons[id] = NULL; +} \ No newline at end of file -- cgit v1.2.3