Subversion Repositories battle

[/] [trunk/] [Battle/] [Bomb.cpp] - Rev 174

Compare with Previous | Blame | View Log

#include "SDL/SDL.h"

#include "Gameplay.h"
#include "Bomb.h"

const int Bomb::FRAME_COUNT = 5;
const int Bomb::FRAME_NORMAL = 0;
const int Bomb::FRAME_FLASH = 1;
const int Bomb::FRAME_STRIKE_NORMAL = 2;
const int Bomb::FRAME_STRIKE_FLASH = 3;
const int Bomb::FRAME_EXPLOSION = 4;

Bomb::Bomb() {
        damage = 0;
        speedy = 0;

        exploded = false;
        done = false;

        hit_on_impact = false;

        position = new SDL_Rect();
}

Bomb::Bomb(SDL_Surface * surface) {
        damage = 0;
        time = 180;
        speedy = 0;

        exploded = false;
        done = false;

        hit_on_impact = false;

        sprite = surface;

        position = new SDL_Rect();
        position->x = 0;
        position->y = 0;
        position->w = BOMB_W;
        position->h = BOMB_H;

        current_frame = 0;

        set_clips();
}

Bomb::~Bomb() {
        delete position;
        for(int i = 0; i < FRAME_COUNT; i++) {
                delete clip[i];
        }
}

void Bomb::draw(SDL_Surface * screen) {
        SDL_Rect rect;

        rect.x = position->x;
        rect.y = position->y;
        
        // Flicker explosion
        if(exploded) {
                if(current_frame != FRAME_EXPLOSION) {
                        current_frame = FRAME_EXPLOSION;
                        frame_change_start = 0;
                        flicker_frame = 0;
                }
                flicker_frame++;
                if(flicker_frame >= 30)
                        done = true;
                if(flicker_frame % 12 >= 6) return;
        }

        if(current_frame == FRAME_EXPLOSION) {
                rect.x = position->x + explosion_offset_x;
                rect.y = position->y + explosion_offset_y;
        }

        SDL_BlitSurface(sprite, clip[current_frame], screen, &rect);

        // If the bomb is going out the side of the screen, we want it to
        // appear on the other side.
        if(current_frame == FRAME_EXPLOSION) {
                rect.x = position->x + explosion_offset_x;
                rect.y = position->y + explosion_offset_y;
        }
        if(rect.x >= screen->w - clip[current_frame]->w) {
                rect.x = rect.x - screen->w;
                rect.y = rect.y;
                SDL_BlitSurface(sprite, clip[current_frame], screen, &rect);
        }
        else if(rect.x <= 0) {
                rect.x = rect.x + screen->w;
                rect.y = rect.y;
                SDL_BlitSurface(sprite, clip[current_frame], screen, &rect);
        }
}

void Bomb::hit_player(Player * p) {
        if(exploded)
                return;

        if(p == owner)
                return;

        if(p->is_hit)
                return;

        explode();
}

void Bomb::hit_npc(NPC * npc) {
        if(exploded)
                return;

        if(npc->is_hit)
                return;

        explode();
}

void Bomb::move(Level * level) {
        int speed;

        if(!exploded) {
                // Move the bomb
                speed = (int)(speedy / 10);

                if(speed != 0) {
                        position->y += speed;

                        if(level->is_intersecting(position)) {
                                position->y -= speed;
                                speedy = 0;
                                if(hit_on_impact)
                                        explode();
                        }
                        if(position->y > WINDOW_HEIGHT)
                                done = true;
                }
                
                // Check if the bomb is on the floor, fall if not
                if(!level->is_on_bottom(position)) {
                        if(speedy > -20)
                                speedy += 2;
                }
        }
}

void Bomb::process() {
        if(!exploded) {
                // Animate bomb
                if(Gameplay::frame - frame_change_start >= frame_change_count) {
                        if(hit_on_impact)
                                current_frame = current_frame == FRAME_STRIKE_NORMAL ? FRAME_STRIKE_FLASH : FRAME_STRIKE_NORMAL;
                        else
                                current_frame = current_frame == FRAME_NORMAL ? FRAME_FLASH : FRAME_NORMAL;
                        frame_change_start = Gameplay::frame;
                }

                // Explode
                if(Gameplay::frame - frame_start >= time) {
                        explode();
                }
        }
}

void Bomb::explode() {
        if(exploded)
                return;

        exploded = true;

        Main::audio->play(SND_EXPLODE, position->x);

        Player * p;
        NPC * npc;
        SDL_Rect * rect_bomb;
        SDL_Rect * rect_player = NULL;
        SDL_Rect * rect_npc = NULL;
        bool player_hit = false;
        bool npcs_hit = false;

        rect_bomb = get_damage_rect();

        for(unsigned int i = 0; i < Gameplay::instance->players->size(); i++) {
                p = Gameplay::instance->players->at(i);
                if(p == owner)
                        continue;

                rect_player = p->get_rect();

                if(Gameplay::is_intersecting(rect_bomb, rect_player)) {
                        if(p->damage(damage))
                                player_hit = true;
                }

                delete rect_player;
        }

        for(unsigned int i = 0; i < Gameplay::instance->npcs->size(); i++) {
                npc = Gameplay::instance->npcs->at(i);

                rect_npc = npc->get_rect();

                if(Gameplay::is_intersecting(rect_bomb, rect_npc)) {
                        if(npc->damage(damage))
                                npcs_hit = true;
                }

                delete rect_npc;
        }

        if(player_hit || npcs_hit)
                owner->bombs_hit++;

        // Tiles below are also to be damaged
        rect_bomb->h += TILE_H;

        Gameplay::instance->level->damage_tiles(rect_bomb, damage);

        delete rect_bomb;
}

SDL_Rect * Bomb::get_damage_rect() {
        SDL_Rect * rect;

        rect = new SDL_Rect();
        rect->x = position->x + explosion_offset_x;
        rect->y = position->y + explosion_offset_y;
        rect->w = clip[FRAME_EXPLOSION]->w;
        rect->h = clip[FRAME_EXPLOSION]->h;
        return rect;
}

void Bomb::set_clips() {
        clip[FRAME_NORMAL] = new SDL_Rect();
        clip[FRAME_NORMAL]->x = 0;
        clip[FRAME_NORMAL]->y = 0;
        clip[FRAME_NORMAL]->w = BOMB_W;
        clip[FRAME_NORMAL]->h = BOMB_H;
        
        clip[FRAME_FLASH] = new SDL_Rect();
        clip[FRAME_FLASH]->x = BOMB_W;
        clip[FRAME_FLASH]->y = 0;
        clip[FRAME_FLASH]->w = BOMB_W;
        clip[FRAME_FLASH]->h = BOMB_H;

        clip[FRAME_STRIKE_NORMAL] = new SDL_Rect();
        clip[FRAME_STRIKE_NORMAL]->x = BOMB_W * 2;
        clip[FRAME_STRIKE_NORMAL]->y = 0;
        clip[FRAME_STRIKE_NORMAL]->w = BOMB_W;
        clip[FRAME_STRIKE_NORMAL]->h = BOMB_H;
        
        clip[FRAME_STRIKE_FLASH] = new SDL_Rect();
        clip[FRAME_STRIKE_FLASH]->x = BOMB_W * 3;
        clip[FRAME_STRIKE_FLASH]->y = 0;
        clip[FRAME_STRIKE_FLASH]->w = BOMB_W;
        clip[FRAME_STRIKE_FLASH]->h = BOMB_H;
        
        clip[FRAME_EXPLOSION] = new SDL_Rect();
        clip[FRAME_EXPLOSION]->x = 0;
        clip[FRAME_EXPLOSION]->y = BOMB_H;
        clip[FRAME_EXPLOSION]->w = 86;
        clip[FRAME_EXPLOSION]->h = 68;

        explosion_offset_x = (clip[FRAME_NORMAL]->w - clip[FRAME_EXPLOSION]->w) / 2;
        explosion_offset_y = -clip[FRAME_EXPLOSION]->h + clip[FRAME_NORMAL]->h;
}

Compare with Previous | Blame