示例#1
0
void game::draw_hit_player(player const &p, const int dam)
{
    if (!use_tiles) {
        draw_hit_player_curses(*this, p, dam);
        return;
    }

    static std::string const player_male   {
        "player_male"
    };
    static std::string const player_female {
        "player_female"
    };
    static std::string const npc_male      {
        "npc_male"
    };
    static std::string const npc_female    {
        "npc_female"
    };

    std::string const& type = p.is_player() ? (p.male ? player_male : player_female)
                              : (p.male ? npc_male    : npc_female);

    tilecontext->init_draw_hit( p.pos3(), type );
    wrefresh(w_terrain);
    draw_animation_delay();
}
void game::draw_hit_mon( const tripoint &p, const monster &m, bool const dead )
{
    if (!use_tiles) {
        draw_hit_mon_curses( p, m, u, dead );
        return;
    }

    tilecontext->init_draw_hit( p, m.type->id.str() );
    wrefresh(w_terrain);
    draw_animation_delay();
}
void game::draw_explosion( const tripoint &p, int const r, nc_color const col )
{
    if (!use_tiles) {
        draw_explosion_curses(*this, p, r, col);
        return;
    }

    for (int i = 1; i <= r; i++) {
        tilecontext->init_explosion( p, i ); // TODO not xpos ypos?
        wrefresh(w_terrain);
        draw_animation_delay(EXPLOSION_MULTIPLIER);
    }

    if (r > 0) {
        tilecontext->void_explosion();
    }
}
示例#4
0
// need to have a version where there is no player defined, possibly. That way shrapnel works as intended
void game::draw_bullet(Creature const &p, const tripoint &t, int const i,
                       std::vector<tripoint> const &trajectory, char const bullet)
{
    //TODO signature and impl could be changed to eliminate these params

    (void)i;          //unused
    (void)trajectory; //unused

    if( !u.sees( t ) ) {
        return;
    }

    if (!use_tiles) {
        draw_bullet_curses(w_terrain, u, m, t, bullet, nullptr, p.is_player());
        return;
    }

    static std::string const bullet_unknown  {};
    static std::string const bullet_normal   {
        "animation_bullet_normal"
    };
    static std::string const bullet_flame    {
        "animation_bullet_flame"
    };
    static std::string const bullet_shrapnel {
        "animation_bullet_shrapnel"
    };

    std::string const &bullet_type =
        (bullet == '*') ? bullet_normal
        : (bullet == '#') ? bullet_flame
        : (bullet == '`') ? bullet_shrapnel
        : bullet_unknown;

    tilecontext->init_draw_bullet( t, bullet_type );
    wrefresh(w_terrain);

    if( p.is_player() ) {
        draw_animation_delay();
    }

    tilecontext->void_bullet();
}
void game::draw_custom_explosion( const tripoint &, const std::map<tripoint, nc_color> &all_area )
{
    constexpr explosion_neighbors all_neighbors = N_NORTH | N_SOUTH | N_WEST | N_EAST;
    // We will "shell" the explosion area
    // Each phase will strip a single layer of points
    // A layer contains all points that have less than 4 neighbors in cardinal directions
    // Layers will first be generated, then drawn in inverse order

    // Start by getting rid of everything except current z-level
    std::map<point, explosion_tile> neighbors;
#if defined(TILES)
    if( !use_tiles ) {
        for( const auto &pr : all_area ) {
            const tripoint relative_point = relative_view_pos( u, pr.first );
            if( relative_point.z == 0 ) {
                point flat_point{ relative_point.x, relative_point.y };
                neighbors[flat_point] = explosion_tile{ N_NO_NEIGHBORS, pr.second };
            }
        }
    } else {
        // In tiles mode, the coordinates have to be absolute
        const tripoint view_center = relative_view_pos( u, u.pos() );
        for( const auto &pr : all_area ) {
            const tripoint &pt = pr.first;
            // Relative point is only used for z level check
            const tripoint relative_point = relative_view_pos( u, pr.first );
            if( relative_point.z == view_center.z ) {
                point flat_point{ pt.x, pt.y };
                neighbors[flat_point] = explosion_tile{ N_NO_NEIGHBORS, pr.second };
            }
        }
    }
#else
    for( const auto &pr : all_area ) {
        const tripoint relative_point = relative_view_pos( u, pr.first );
        if( relative_point.z == 0 ) {
            point flat_point{ relative_point.x, relative_point.y };
            neighbors[flat_point] = explosion_tile{ N_NO_NEIGHBORS, pr.second };
        }
    }
#endif

    // Searches for a neighbor, sets the neighborhood flag on current point and on the neighbor
    const auto set_neighbors = [&]( const point &pos,
                                    explosion_neighbors &ngh,
                                    explosion_neighbors here,
                                    explosion_neighbors there ) {
        if( ( ngh & here ) == N_NO_NEIGHBORS ) {
            auto other = neighbors.find( pos );
            if( other != neighbors.end() ) {
                ngh = ngh | here;
                other->second.neighborhood = other->second.neighborhood | there;
            }
        }
    };

    // If the point we are about to remove has a neighbor in a given direction
    // unset that neighbor's flag that our current point is its neighbor
    const auto unset_neighbor = [&]( const point &pos,
                                     const explosion_neighbors ngh,
                                     explosion_neighbors here,
                                     explosion_neighbors there ) {
        if( ( ngh & here ) != N_NO_NEIGHBORS ) {
            auto other = neighbors.find( pos );
            if( other != neighbors.end() ) {
                other->second.neighborhood = ( other->second.neighborhood | there ) ^ there;
            }
        }
    };

    // Find all neighborhoods
    for( auto &pr : neighbors ) {
        const point &pt = pr.first;
        explosion_neighbors &ngh = pr.second.neighborhood;

        set_neighbors( point( pt.x - 1, pt.y ), ngh, N_WEST, N_EAST );
        set_neighbors( point( pt.x + 1, pt.y ), ngh, N_EAST, N_WEST );
        set_neighbors( point( pt.x, pt.y - 1 ), ngh, N_NORTH, N_SOUTH );
        set_neighbors( point( pt.x, pt.y + 1 ), ngh, N_SOUTH, N_NORTH );
    }

    // We need to save the layers because we will draw them in reverse order
    std::list< std::map<point, explosion_tile> > layers;
    bool changed;
    while( !neighbors.empty() ) {
        std::map<point, explosion_tile> layer;
        changed = false;
        // Find a layer that can be drawn
        for( const auto &pr : neighbors ) {
            if( pr.second.neighborhood != all_neighbors ) {
                changed = true;
                layer.insert( pr );
            }
        }
        if( !changed ) {
            // An error, but a minor one - let it slide
            return;
        }
        // Remove the layer from the area to process
        for( const auto &pr : layer ) {
            const point &pt = pr.first;
            const explosion_neighbors ngh = pr.second.neighborhood;

            unset_neighbor( point( pt.x - 1, pt.y ), ngh, N_WEST, N_EAST );
            unset_neighbor( point( pt.x + 1, pt.y ), ngh, N_EAST, N_WEST );
            unset_neighbor( point( pt.x, pt.y - 1 ), ngh, N_NORTH, N_SOUTH );
            unset_neighbor( point( pt.x, pt.y + 1 ), ngh, N_SOUTH, N_NORTH );
            neighbors.erase( pr.first );
        }

        layers.push_front( std::move( layer ) );
    }

#if defined(TILES)
    if( !use_tiles ) {
        draw_custom_explosion_curses( *this, layers );
        return;
    }

    // We need to draw all explosions up to now
    std::map<point, explosion_tile> combined_layer;
    for( const auto &layer : layers ) {
        combined_layer.insert( layer.begin(), layer.end() );
        tilecontext->init_custom_explosion_layer( combined_layer );
        wrefresh(w_terrain);
        draw_animation_delay(EXPLOSION_MULTIPLIER);
    }

    tilecontext->void_custom_explosion();
#else
    draw_custom_explosion_curses( *this, layers );
#endif
}