mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-03 11:11:22 +00:00
added missile haloes, with sample for Red Mage
This commit is contained in:
parent
312f113cd2
commit
431c713d20
@ -53,6 +53,7 @@ get_hit_sound=groan.wav
|
||||
begin=-100
|
||||
end=0
|
||||
image=fireball.png
|
||||
halo=fireball-halo.png
|
||||
[/missile_frame]
|
||||
[/attack]
|
||||
[/unit]
|
||||
|
BIN
images/fireball-halo.png
Normal file
BIN
images/fireball-halo.png
Normal file
Binary file not shown.
163
src/halo.cpp
163
src/halo.cpp
@ -1 +1,162 @@
|
||||
#include "halo.hpp"
|
||||
#include "halo.hpp"
|
||||
#include "image.hpp"
|
||||
#include "sdl_utils.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
|
||||
namespace halo
|
||||
{
|
||||
|
||||
namespace {
|
||||
display* disp = NULL;
|
||||
|
||||
class effect
|
||||
{
|
||||
public:
|
||||
effect(int xpos, int ypos, const std::string& img);
|
||||
|
||||
void render();
|
||||
void unrender();
|
||||
private:
|
||||
|
||||
void rezoom();
|
||||
|
||||
std::string image_;
|
||||
int x_, y_;
|
||||
double zoom_;
|
||||
shared_sdl_surface surf_, buffer_;
|
||||
SDL_Rect rect_;
|
||||
};
|
||||
|
||||
std::map<int,effect> haloes;
|
||||
int halo_id = 1;
|
||||
|
||||
static const SDL_Rect empty_rect = {0,0,0,0};
|
||||
|
||||
effect::effect(int xpos, int ypos, const std::string& img)
|
||||
: image_(img), x_(xpos), y_(ypos), zoom_(disp->zoom()), surf_(NULL), buffer_(NULL), rect_(empty_rect)
|
||||
{
|
||||
assert(disp != NULL);
|
||||
|
||||
const gamemap::location zero_loc(0,0);
|
||||
x_ -= disp->get_location_x(zero_loc);
|
||||
y_ -= disp->get_location_y(zero_loc);
|
||||
|
||||
rezoom();
|
||||
}
|
||||
|
||||
void effect::rezoom()
|
||||
{
|
||||
const double new_zoom = disp->zoom();
|
||||
x_ = (x_*new_zoom)/zoom_;
|
||||
y_ = (y_*new_zoom)/zoom_;
|
||||
|
||||
zoom_ = new_zoom;
|
||||
|
||||
surf_.assign(image::get_image(image_,image::UNSCALED));
|
||||
if(surf_ != NULL && zoom_ != 1.0) {
|
||||
surf_.assign(scale_surface(surf_,surf_->w*zoom_,surf_->h*zoom_));
|
||||
}
|
||||
}
|
||||
|
||||
void effect::render()
|
||||
{
|
||||
if(disp == NULL || surf_ == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(zoom_ != disp->zoom()) {
|
||||
rezoom();
|
||||
}
|
||||
|
||||
if(surf_ == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
const gamemap::location zero_loc(0,0);
|
||||
const int screenx = disp->get_location_x(zero_loc);
|
||||
const int screeny = disp->get_location_y(zero_loc);
|
||||
|
||||
const int xpos = x_ + screenx - surf_->w/2;
|
||||
const int ypos = y_ + screeny - surf_->h/2;
|
||||
|
||||
SDL_Rect rect = {xpos,ypos,surf_->w,surf_->h};
|
||||
rect_ = rect;
|
||||
SDL_Rect clip_rect = disp->map_area();
|
||||
if(rects_overlap(rect,clip_rect) == false) {
|
||||
buffer_.assign(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Surface* const screen = disp->video().getSurface();
|
||||
|
||||
const clip_rect_setter clip_setter(screen,clip_rect);
|
||||
if(buffer_ == NULL || buffer_->w != rect.w || buffer_->h != rect.h) {
|
||||
SDL_Rect rect = rect_;
|
||||
buffer_.assign(get_surface_portion(screen,rect));
|
||||
} else {
|
||||
SDL_Rect rect = rect_;
|
||||
SDL_BlitSurface(screen,&rect,buffer_,NULL);
|
||||
}
|
||||
|
||||
SDL_BlitSurface(surf_,NULL,screen,&rect);
|
||||
|
||||
update_rect(rect_);
|
||||
}
|
||||
|
||||
void effect::unrender()
|
||||
{
|
||||
if(buffer_ == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Surface* const screen = disp->video().getSurface();
|
||||
|
||||
SDL_Rect clip_rect = disp->map_area();
|
||||
const clip_rect_setter clip_setter(screen,clip_rect);
|
||||
SDL_Rect rect = rect_;
|
||||
SDL_BlitSurface(buffer_,NULL,screen,&rect);
|
||||
update_rect(rect_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
manager::manager(display& screen) : old(disp)
|
||||
{
|
||||
disp = &screen;
|
||||
}
|
||||
|
||||
manager::~manager()
|
||||
{
|
||||
haloes.clear();
|
||||
disp = old;
|
||||
}
|
||||
|
||||
int add(int x, int y, const std::string& image)
|
||||
{
|
||||
const int id = halo_id++;
|
||||
haloes.insert(std::pair<int,effect>(id,effect(x,y,image)));
|
||||
return id;
|
||||
}
|
||||
|
||||
void remove(int handle)
|
||||
{
|
||||
haloes.erase(handle);
|
||||
}
|
||||
|
||||
void render()
|
||||
{
|
||||
for(std::map<int,effect>::iterator i = haloes.begin(); i != haloes.end(); ++i) {
|
||||
i->second.render();
|
||||
}
|
||||
}
|
||||
|
||||
void unrender()
|
||||
{
|
||||
for(std::map<int,effect>::reverse_iterator i = haloes.rbegin(); i != haloes.rend(); ++i) {
|
||||
i->second.unrender();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
35
src/halo.hpp
35
src/halo.hpp
@ -1,5 +1,40 @@
|
||||
#ifndef HALO_HPP_INCLUDED
|
||||
#define HALO_HPP_INCLUDED
|
||||
|
||||
#include "display.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace halo
|
||||
{
|
||||
|
||||
struct manager
|
||||
{
|
||||
manager(display& disp);
|
||||
~manager();
|
||||
|
||||
private:
|
||||
display* const old;
|
||||
};
|
||||
|
||||
///function to add a haloing effect using 'image'
|
||||
///centered on (x,y)
|
||||
///returns the handle to the halo object
|
||||
int add(int x, int y, const std::string& image);
|
||||
|
||||
///function to remove the halo with the given handle
|
||||
void remove(int handle);
|
||||
|
||||
struct remover
|
||||
{
|
||||
void operator()(int handle) const { remove(handle); }
|
||||
};
|
||||
|
||||
///functions to render and unrender all haloes. Should
|
||||
///be called immediately before/after flipping the screen
|
||||
void render();
|
||||
void unrender();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -15,6 +15,7 @@
|
||||
#include "events.hpp"
|
||||
#include "filesystem.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "halo.hpp"
|
||||
#include "hotkeys.hpp"
|
||||
#include "intro.hpp"
|
||||
#include "language.hpp"
|
||||
@ -295,6 +296,8 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
|
||||
//object that will make sure that labels are removed at the end of the scenario
|
||||
const font::floating_label_manager labels_manager;
|
||||
|
||||
const halo::manager halo_manager(gui);
|
||||
|
||||
gui.labels().read(*level);
|
||||
|
||||
std::cerr << "a... " << (SDL_GetTicks() - ticks) << "\n";
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "image.hpp"
|
||||
#include "log.hpp"
|
||||
#include "preferences.hpp"
|
||||
#include "scoped_resource.hpp"
|
||||
#include "sound.hpp"
|
||||
#include "unit_display.hpp"
|
||||
#include "util.hpp"
|
||||
@ -314,11 +315,14 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
||||
disp.draw_tile(leader_loc.x,leader_loc.y);
|
||||
}
|
||||
|
||||
util::scoped_resource<int,halo::remover> halo_effect(0);
|
||||
|
||||
if(i >= 0 && i < real_last_missile && !hide) {
|
||||
const int missile_frame = i + first_missile;
|
||||
|
||||
const std::string* halo_image = NULL;
|
||||
const std::string* missile_image = attack.get_frame(missile_frame,NULL,
|
||||
attack_type::MISSILE_FRAME,dir);
|
||||
attack_type::MISSILE_FRAME,dir,&halo_image);
|
||||
|
||||
static const std::string default_missile(game_config::missile_n_image);
|
||||
static const std::string default_diag_missile(game_config::missile_ne_image);
|
||||
@ -335,21 +339,29 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
||||
img.assign(image::reverse_image(img));
|
||||
}
|
||||
|
||||
if(img != NULL) {
|
||||
double pos = double(missile_impact - i)/double(missile_impact);
|
||||
if(pos < 0.0) {
|
||||
pos = 0.0;
|
||||
}
|
||||
const int xpos = int(xsrc*pos + xdst*(1.0-pos));
|
||||
const int ypos = int(ysrc*pos + ydst*(1.0-pos));
|
||||
double pos = double(missile_impact - i)/double(missile_impact);
|
||||
if(pos < 0.0) {
|
||||
pos = 0.0;
|
||||
}
|
||||
|
||||
const int xpos = int(xsrc*pos + xdst*(1.0-pos));
|
||||
const int ypos = int(ysrc*pos + ydst*(1.0-pos));
|
||||
|
||||
if(img != NULL) {
|
||||
disp.draw_unit(xpos,ypos,img,vflip);
|
||||
}
|
||||
|
||||
if(halo_image != NULL) {
|
||||
halo_effect.assign(halo::add(xpos+disp.hex_width()/2,ypos+disp.hex_size()/2,*halo_image));
|
||||
}
|
||||
}
|
||||
|
||||
const int wait_time = ticks + time_resolution - SDL_GetTicks();
|
||||
if(wait_time > 0 && !hide) {
|
||||
SDL_Delay(wait_time);
|
||||
} else if(wait_time < 0) {
|
||||
//if we're not keeping up, then skip frames
|
||||
i += minimum<int>(time_resolution*4,-wait_time);
|
||||
}
|
||||
|
||||
ticks = SDL_GetTicks();
|
||||
|
@ -56,7 +56,8 @@ attack_type::attack_type(const config& cfg)
|
||||
const int end = atoi((**range.first)["end"].c_str());
|
||||
const int xoff = atoi((**range.first)["xoffset"].c_str());
|
||||
const std::string& img = (**range.first)["image"];
|
||||
frames_[UNIT_FRAME].push_back(frame(beg,end,img,xoff));
|
||||
const std::string& halo = (**range.first)["halo"];
|
||||
frames_[UNIT_FRAME].push_back(frame(beg,end,img,halo,xoff));
|
||||
}
|
||||
|
||||
range = cfg.child_range("missile_frame");
|
||||
@ -67,10 +68,11 @@ attack_type::attack_type(const config& cfg)
|
||||
|
||||
const std::string& img = (**range.first)["image"];
|
||||
const std::string& img_diag = (**range.first)["image_diagonal"];
|
||||
const std::string& halo = (**range.first)["halo"];
|
||||
if(img_diag.empty())
|
||||
frames_[MISSILE_FRAME].push_back(frame(beg,end,img,xoff));
|
||||
frames_[MISSILE_FRAME].push_back(frame(beg,end,img,halo,xoff));
|
||||
else
|
||||
frames_[MISSILE_FRAME].push_back(frame(beg,end,img,img_diag,xoff));
|
||||
frames_[MISSILE_FRAME].push_back(frame(beg,end,img,img_diag,halo,xoff));
|
||||
|
||||
}
|
||||
|
||||
@ -163,7 +165,7 @@ int attack_type::get_last_frame(attack_type::FRAME_TYPE type) const
|
||||
|
||||
const std::string* attack_type::get_frame(int milliseconds, int* xoff,
|
||||
attack_type::FRAME_TYPE type,
|
||||
attack_type::FRAME_DIRECTION dir) const
|
||||
attack_type::FRAME_DIRECTION dir, const std::string** halo) const
|
||||
{
|
||||
for(std::vector<frame>::const_iterator i = frames_[type].begin();
|
||||
i != frames_[type].end(); ++i) {
|
||||
@ -175,6 +177,14 @@ const std::string* attack_type::get_frame(int milliseconds, int* xoff,
|
||||
*xoff = i->xoffset;
|
||||
}
|
||||
|
||||
if(halo != NULL) {
|
||||
if(i->halo.empty()) {
|
||||
*halo = NULL;
|
||||
} else {
|
||||
*halo = &i->halo;
|
||||
}
|
||||
}
|
||||
|
||||
if(dir == DIAGONAL && i->image_diagonal != "") {
|
||||
return &i->image_diagonal;
|
||||
} else {
|
||||
|
@ -53,7 +53,8 @@ public:
|
||||
//frames before the time of impact
|
||||
const std::string* get_frame(int milliseconds, int* xoffset=NULL,
|
||||
FRAME_TYPE type=UNIT_FRAME,
|
||||
FRAME_DIRECTION direction=VERTICAL) const;
|
||||
FRAME_DIRECTION direction=VERTICAL,
|
||||
const std::string** halo=NULL) const;
|
||||
|
||||
struct sfx {
|
||||
int time;
|
||||
@ -81,20 +82,21 @@ private:
|
||||
bool backstab_;
|
||||
|
||||
struct frame {
|
||||
frame(int i1, int i2, const std::string& img, int offset)
|
||||
: start(i1), end(i2), xoffset(offset), image(img)
|
||||
frame(int i1, int i2, const std::string& img, const std::string& halo, int offset)
|
||||
: start(i1), end(i2), xoffset(offset), image(img), halo(halo)
|
||||
{}
|
||||
|
||||
frame(int i1, int i2, const std::string& img, const std::string& diag,
|
||||
int offset)
|
||||
const std::string& halo, int offset)
|
||||
: start(i1), end(i2), xoffset(offset),
|
||||
image(img), image_diagonal(diag)
|
||||
image(img), image_diagonal(diag), halo(halo)
|
||||
{}
|
||||
|
||||
int start, end;
|
||||
int xoffset;
|
||||
std::string image;
|
||||
std::string image_diagonal;
|
||||
std::string halo;
|
||||
};
|
||||
|
||||
std::vector<frame> frames_[2];
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "cursor.hpp"
|
||||
#include "events.hpp"
|
||||
#include "font.hpp"
|
||||
#include "halo.hpp"
|
||||
#include "image.hpp"
|
||||
#include "mouse.hpp"
|
||||
#include "preferences.hpp"
|
||||
@ -292,6 +293,7 @@ void CVideo::flip()
|
||||
if(fake_screen)
|
||||
return;
|
||||
|
||||
halo::render();
|
||||
events::raise_volatile_draw_event();
|
||||
font::draw_floating_labels(frameBuffer);
|
||||
cursor::draw(frameBuffer);
|
||||
@ -306,6 +308,7 @@ void CVideo::flip()
|
||||
cursor::undraw(frameBuffer);
|
||||
font::undraw_floating_labels(frameBuffer);
|
||||
events::raise_volatile_undraw_event();
|
||||
halo::unrender();
|
||||
}
|
||||
|
||||
void CVideo::lock()
|
||||
|
Loading…
x
Reference in New Issue
Block a user