walking and turning effect

This commit is contained in:
Ondřej Novák 2025-01-29 14:22:27 +01:00
parent 3b903e2b52
commit 4f9f985918
12 changed files with 286 additions and 98 deletions

View file

@ -373,7 +373,7 @@ void load_enemies(short *data,int size,int *grptr,TMOB *template,int32_t tsize)
{
mobs[i]=b[j];
if (~mobs[i].vlajky & MOB_MOBILE) mob_map[data[0]]=i+MOB_START;
if (mobs[i].palette>=0)mobs[i].palette=rnd(mobs[i].palette);else mobs[i].palette=abs(mobs[i].palette);
if (mobs[i].palette>0)mobs[i].palette=rnd(mobs[i].palette);else mobs[i].palette=abs(mobs[i].palette);
mobs[i].sector=data[0];
mobs[i].dir=(data[1]>>14)&0x3;
mobs[i].home_pos=data[0];

View file

@ -456,7 +456,7 @@ static void zooming_forward_backward(word *background,char back)
{
int32_t tmp=get_timer_value();
void *buffer=DxPrepareWalk(SCREEN_OFFLINE);
int tpoints[4]={90,31,90+460,31+259};
int tpoints[4]={90,31,90+460,31+270};
int maxtime=5*zoom_speed(-1);
int curtime;
@ -467,7 +467,7 @@ static void zooming_forward_backward(word *background,char back)
curtime=get_timer_value()-tmp;
phase=(curtime)*(1.0f/(float)maxtime);
//phase=(float)sin(3.14159265*0.5f*phase);
if (back) phase=1.0-phase;
if (back) phase=-phase;
DxZoomWalk(buffer, SCREEN_OFFLINE, tpoints,phase, NULL);
do_events();
}
@ -532,7 +532,7 @@ static void turn_left_right(char right)
curtime=get_timer_value()-tmp;
phase=(curtime)*(1.0f/(float)maxtime);
//phase=(float)sin(3.14159265*0.5f*phase);
DxTurn(buffer,right,SCREEN_OFFLINE,90,phase,NULL);
DxTurn(buffer,SCREEN_OFFLINE,90,right?-phase:phase,NULL);
do_events();
}
while (curtime<maxtime);

View file

@ -2393,6 +2393,7 @@ static void shop_mouse_event(EVENT_MSG *msg,void **unused)
int x,y;
char cc=1;
static int last_pos=-1;
EVENT_MSG msgc = clone_message(msg);
ms=get_mouse(msg);
x=ms->x-(BUYBOX_X+SHP_ICPLCX);
@ -2422,10 +2423,12 @@ static void shop_mouse_event(EVENT_MSG *msg,void **unused)
}
if (cc)
{
inv_item_info_box(msg,unused);
inv_item_info_box(&msgc,unused);
last_pos=-1;
}
destroy_message(&msgc);
}
}
static __inline void copy_data(char **src, void *target, int size) {

View file

@ -1600,6 +1600,7 @@ void step_zoom(char smer)
anim_sipky(0,255);
hide_ms_at(385);
ukaz_mysku();
redraw_ms_cursor_on_screen();
if (set_halucination) do_halucinace();
if (loadlevel.name[0])
{
@ -1624,17 +1625,12 @@ void step_zoom(char smer)
if (!cancel_pass)
{
render_scene(viewsector,viewdir);
if (smer==2)
{
OutBuffer2nd();
if (!nopass) shift_zoom(smer);
}
else
{
shift_zoom(smer);
OutBuffer2nd();
if (nopass) shift_zoom(smer+2);
}
OutBuffer2nd();
sort_groups();
bott_draw(0);
other_draw();
shift_zoom(smer);
if (smer==0 && nopass) shift_zoom(smer+2);
if (battle || (game_extras & EX_ALWAYS_MINIMAP)) draw_medium_map();
sort_groups();
bott_draw(0);
@ -1672,6 +1668,9 @@ void turn_zoom(int smer)
viewdir=(viewdir+smer)&3;
render_scene(viewsector,viewdir);
hide_ms_at(387);
OutBuffer2nd();
other_draw();
bott_draw(0);
if (smer==1)
{
anim_sipky(H_SIPKY_SV,1);
@ -1685,9 +1684,7 @@ void turn_zoom(int smer)
turn_right();
}
chod_s_postavama(0);
OutBuffer2nd();
if (battle || (game_extras & EX_ALWAYS_MINIMAP)) draw_medium_map();
other_draw();
update_mysky();
ukaz_mysku();
showview(0,0,0,0);

View file

@ -116,6 +116,7 @@ void show_ms_cursor(integer x,integer y);
void *register_ms_cursor(void *cursor);
void move_ms_cursor(integer newx,integer newy,char nodraw);
void hide_ms_cursor(void);
void redraw_ms_cursor_on_screen(void);
int text_height(char *text);
int text_width(char *text);
void set_aligned_position(int x,int y,char alignx, char aligny,char *text);

View file

@ -509,8 +509,18 @@ void show_ms_cursor(integer x,integer y)
void hide_ms_cursor()
{
put_picture(mscuroldx,mscuroldy,mssavebuffer);
}
void redraw_ms_cursor_on_screen(void) {
if (mssavebuffer) {
integer xs=*(integer *)mssavebuffer;
integer ys=*((integer *)mssavebuffer+1);
showview(mscuroldx,mscuroldy,xs,ys);
}
}
void *register_ms_cursor(void *cursor)
{
integer xs,ys;

View file

@ -1,3 +1,4 @@
#include <cassert>
#include <cstdarg>
#include <cstdint>
#include <iostream>
@ -8,7 +9,9 @@ extern "C" {
void display_error(const char *text) {
char failed_because_error = 0;
std::cerr << "ERROR:" << text << std::endl;
assert(failed_because_error);
}

View file

@ -147,12 +147,9 @@ char is_running(int id_num) {
return id_num < 0 || task_list.find(id_num) != task_list.end();
}
void unsuspend_task(EVENT_MSG *msg) {
if (current_task_inst) return;
msg_queue.push({msg, current_task_inst});
if (current_task_inst) {
switch_to_task(NULL);
} else {
flush_message_queue();
}
flush_message_queue();
}
void task_sleep(void) {

View file

@ -90,22 +90,96 @@ void DXCopyRects64(unsigned short x,unsigned short y,unsigned short xs,unsigned
}
void *DxPrepareWalk(int ypos) {
return 0;
auto &sdl = get_sdl_global_context();
sdl.swap_render_buffers();
sdl.present_rect(screen_buffer.get(), screen_pitch, 0,0,640,480);//new is in hidden buffer
return NULL;
}
void DxZoomWalk(void *handle, int ypos, int *points,float phase, void *lodka) {
auto &sdl = get_sdl_global_context();
if (phase>1.0) phase=1.0f;
if (phase<-1.0) phase=-1.0f;
SDL_Rect rc1;
rc1.x=0;
rc1.y=0+ypos;
rc1.w=640;
rc1.h=360;
SDL_Rect rc2;
rc2.x=points[0];
rc2.y=points[1]+ypos;
rc2.w=points[2]-rc2.x;
rc2.h=points[3]-rc2.y;
sdl.show_blend_transition({0,ypos,640,360},rc1, rc2, phase);
}
void DxDoneWalk(void *handle) {
auto &sdl = get_sdl_global_context();
sdl.swap_display_buffers(); //present hidden buffer
}
void *DxPrepareTurn(int ypos) {
return 0;
auto &sdl = get_sdl_global_context();
sdl.swap_render_buffers();
sdl.present_rect(screen_buffer.get(), screen_pitch, 0,0,640,480);//new is in hidden buffer
return NULL;
}
void DxTurn(void *handle, char right, int ypos,int border, float phase, void *lodka) {
void DxTurn(void *handle, int ypos,int border, float phase, void *lodka) {
auto &sdl = get_sdl_global_context();
if (phase>1.0) phase=1.0f;
if (phase<-1.0) phase=-1.0f;
int width = 640-2*border;
SDL_Rect visible_from{0,ypos,640,360};
SDL_Rect visible_where;
SDL_Rect hidden_from{0,ypos,640,360};
SDL_Rect hidden_where;
if (phase > 0) {
hidden_from.x = border;
} else if (phase < 0) {
visible_from.x = border;
} else {
return ;
}
visible_from.w-= border;
hidden_from.w -= border;
visible_where = visible_from;
hidden_where = hidden_from;
int xsep = border + static_cast<int>(std::round(width * std::abs(phase)));
if (phase > 0) {
xsep = 640-xsep;
hidden_where.x = xsep;
visible_where.x = xsep - visible_where.w;
} else {
hidden_where.x = xsep - visible_where.w;
visible_where.x = xsep;
}
auto crop_rects = [](SDL_Rect &primary, SDL_Rect &secondary) {
if (primary.x < 0) {
secondary.x -= primary.x*2/3;
secondary.w += primary.x*2/3;
primary.w += primary.x;
primary.x = 0;
}
int extra = 640 - (primary.x + primary.w);;
if (extra < 0) {
primary.w += extra;
secondary.w += extra*2/3;
}
};
crop_rects(visible_where, visible_from);
crop_rects(hidden_where, hidden_from);
int adjw = static_cast<int>(hidden_from.w / (1.0+2.0*std::abs(phase)));
if (phase < 0) {
hidden_from.x += adjw;
}
hidden_from.w -= adjw;
sdl.show_slide_transition(visible_from, visible_where, hidden_from, hidden_where);
}
void DxDoneTurn(void *handle) {
auto &sdl = get_sdl_global_context();
sdl.swap_display_buffers(); //present hidden buffer
}
void DxTurnLeftRight(char right, float phase, int border, int ypos, int *last) {

View file

@ -33,7 +33,8 @@ void DxZoomWalk(void *handle, int ypos, int *points,float phase, void *lodka);
void DxDoneWalk(void *handle);
void *DxPrepareTurn(int ypos);
void DxTurn(void *handle, char right, int ypos,int border, float phase, void *lodka);
//phase > 0 right, phase < 0 left
void DxTurn(void *handle, int ypos,int border, float phase, void *lodka);
void DxDoneTurn(void *handle);
void DxTurnLeftRight(char right, float phase, int border, int ypos, int *last);

View file

@ -5,6 +5,7 @@
#include <cassert>
#include "../platform.h"
#include <cmath>
#include <iostream>
#include <stdexcept>
void SDLContext::SDL_Deleter::operator ()(SDL_Window* window) {
@ -79,7 +80,7 @@ void SDLContext::init_screen(DisplayMode mode, const char *title) {
}
_window.reset(window);
SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, 0);
SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, SDL_RENDERER_SOFTWARE);
if (!renderer) {
snprintf(buff,sizeof(buff), "Chyba při vytváření rendereru: %s\n", SDL_GetError());
throw std::runtime_error(buff);
@ -90,15 +91,17 @@ void SDLContext::init_screen(DisplayMode mode, const char *title) {
snprintf(buff, sizeof(buff), "Chyba při vytváření textury: %s\n", SDL_GetError());
throw std::runtime_error(buff);
}
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
_texture.reset(texture);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, 640, 480);
if (!texture) {
snprintf(buff, sizeof(buff), "Chyba při vytváření textury: %s\n", SDL_GetError());
throw std::runtime_error(buff);
}
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
_texture2.reset(texture);
_visible_texture = _texture.get();
_hidden_texture = _texture.get();
_hidden_texture = _texture2.get();
} catch (...) {
e = std::current_exception();
err = true;
@ -164,17 +167,13 @@ void SDLContext::event_loop(std::stop_token stp) {
}
}
} else if (e.type == SDL_MOUSEMOTION) {
int mouseX = e.motion.x;
int mouseY = e.motion.y;
int windowWidth;
int windowHeight;
SDL_GetWindowSize(_window.get(), &windowWidth, &windowHeight);
float normalizedX = (float)mouseX / windowWidth;
float normalizedY = (float)mouseY / windowHeight;
SDL_Point mspt(e.motion.x, e.motion.y);
SDL_Rect winrc = get_window_aspect_rect();
SDL_Point srcpt = to_source_point(winrc, mspt);
ms_event.event = 1;
ms_event.event_type = 1;
ms_event.x = (int16_t)(640*normalizedX);
ms_event.y = (int16_t)(480*normalizedY);
ms_event.x = srcpt.x;
ms_event.y = srcpt.y;
} else if (e.type == SDL_MOUSEBUTTONDOWN || e.type == SDL_MOUSEBUTTONUP) {
int button = e.button.button;
int up = e.type == SDL_MOUSEBUTTONUP?1:0;
@ -183,8 +182,8 @@ void SDLContext::event_loop(std::stop_token stp) {
switch (button) {
default: break;
case 1: ms_event.tl1 = !up; break;
case 2: ms_event.tl2 = !up; break;
case 3: ms_event.tl3 = !up; break;
case 2: ms_event.tl3 = !up; break;
case 3: ms_event.tl2 = !up; break;
}
}
@ -192,57 +191,6 @@ void SDLContext::event_loop(std::stop_token stp) {
}
/*
void SDLContext::pool_events() {
SDL_RenderClear(_renderer.get());
SDL_RenderCopy(_renderer.get(), _texture.get(), NULL, NULL);
SDL_RenderPresent(_renderer.get());
ms_event.event = 0;
SDL_Event e;
while (true) {
if (SDL_WaitEvent(&e)) {
if (e.type == SDL_QUIT) {
_quit_requested = true;
return;
if (e.type == SDL_KEYDOWN) {
if (e.key.keysym.sym == SDLK_RETURN && (e.key.keysym.mod & KMOD_ALT)) {
_fullscreen_mode = !_fullscreen_mode;
SDL_SetWindowFullscreen(_window.get(), _fullscreen_mode ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
}
} else if (e.type == SDL_MOUSEMOTION) {
std::lock_guard _(_mx);
int mouseX = e.motion.x;
int mouseY = e.motion.y;
int windowWidth;
int windowHeight;
SDL_GetWindowSize(_window.get(), &windowWidth, &windowHeight);
float normalizedX = (float)mouseX / windowWidth;
float normalizedY = (float)mouseY / windowHeight;
ms_event.event = 1;
ms_event.event_type = 1;
ms_event.x = (int16_t)(640*normalizedX);
ms_event.y = (int16_t)(480*normalizedY);
} else if (e.type == SDL_MOUSEBUTTONDOWN || e.type == SDL_MOUSEBUTTONUP) {
std::lock_guard _(_mx);
int button = e.button.button;
int up = e.type == SDL_MOUSEBUTTONUP?1:0;
ms_event.event = 1;
ms_event.event_type = (1<<(2*button-1+up));
switch (button) {
default: break;
case 1: ms_event.tl1 = !up; break;
case 2: ms_event.tl2 = !up; break;
case 3: ms_event.tl3 = !up; break;
}
}
} else {
throw std::runtime_error("SDL_WaitEvent error");
}
}
charge_timer();
}*/
void SDLContext::present_rect(uint16_t *pixels, unsigned int pitch,
unsigned int x, unsigned int y, unsigned int xs, unsigned ys) {
@ -271,6 +219,15 @@ bool SDLContext::is_keyboard_ready() const {
return !_keyboard_queue.empty();
}
void SDLContext::show_slide_transition(const SDL_Rect &visible_from,
const SDL_Rect &visible_where, const SDL_Rect &hidden_from,
const SDL_Rect &hidden_where) {
std::lock_guard _(_mx);
signal_push();
push_item(DisplayRequest::slide_transition);
push_item(SlideTransitionReq{visible_from, visible_where,hidden_from, hidden_where});
}
void SDLContext::signal_push() {
if (_display_update_queue.empty()) {
SDL_Event event;
@ -281,8 +238,11 @@ void SDLContext::signal_push() {
}
void SDLContext::update_screen() {
std::optional<BlendTransitionReq> blend_transition;
std::optional<SlideTransitionReq> slide_transition;
{
std::lock_guard _(_mx);
if (_display_update_queue.empty()) return;
QueueIter iter = _display_update_queue.data();
QueueIter end = iter + _display_update_queue.size();
while (iter != end) {
@ -302,14 +262,63 @@ void SDLContext::update_screen() {
break;
case DisplayRequest::swap_visible_buffers: {
std::swap(_visible_texture,_hidden_texture);
blend_transition.reset();
slide_transition.reset();
}
break;
case DisplayRequest::blend_transition:
blend_transition.emplace();
pop_item(iter, *blend_transition);
break;
case DisplayRequest::slide_transition:
slide_transition.emplace();
pop_item(iter, *slide_transition);
break;
}
}
_display_update_queue.clear();
}
SDL_Rect winrc = get_window_aspect_rect();
SDL_RenderClear(_renderer.get());
SDL_RenderCopy(_renderer.get(), _visible_texture, NULL, NULL);
if (slide_transition) {
SDL_SetTextureAlphaMod(_hidden_texture, 255);
SDL_SetTextureAlphaMod(_visible_texture, 255);
SDL_RenderCopy(_renderer.get(), _hidden_texture, NULL, &winrc);
SDL_Rect visible_where_win = to_window_rect(winrc, slide_transition->visible_where);
SDL_Rect hidden_where_win = to_window_rect(winrc, slide_transition->hidden_where);
SDL_RenderCopy(_renderer.get(), _visible_texture, &slide_transition->visible_from, &visible_where_win);
SDL_RenderCopy(_renderer.get(), _hidden_texture, &slide_transition->hidden_from, &hidden_where_win);
}
else if (blend_transition) {
SDL_SetTextureAlphaMod(_hidden_texture, 255);
SDL_RenderCopy(_renderer.get(), _hidden_texture, NULL, &winrc);
if (blend_transition->phase >= 0) {
float f = blend_transition->phase;
SDL_SetTextureAlphaMod(_visible_texture, 255);
SDL_Rect wrkarea = to_window_rect(winrc, blend_transition->wrkarea);
SDL_Rect src1 = transition_rect(blend_transition->prev, blend_transition->next, f);
SDL_RenderCopy(_renderer.get(), _visible_texture, &src1, &wrkarea);
if (SDL_SetTextureAlphaMod(_hidden_texture, (uint8_t)(255.0f*(f)))!= -1) {
SDL_Rect trgnxt = to_window_rect(winrc, blend_transition->next);
SDL_Rect trgwin = transition_rect(trgnxt, wrkarea, f);
SDL_RenderCopy(_renderer.get(), _hidden_texture, &blend_transition->wrkarea, &trgwin);
}
} else {
float f = blend_transition->phase;
SDL_Rect wrkarea = to_window_rect(winrc, blend_transition->wrkarea);
SDL_Rect src1 = transition_rect(blend_transition->prev, blend_transition->next, 1+f);
SDL_RenderCopy(_renderer.get(), _hidden_texture, &src1, &wrkarea);
if (SDL_SetTextureAlphaMod(_visible_texture, (uint8_t)(255.0f*(1+f))) != -1) {
SDL_Rect trgnxt = to_window_rect(winrc, blend_transition->next);
SDL_Rect trgwin = transition_rect(trgnxt, wrkarea, 1+f);
SDL_RenderCopy(_renderer.get(), _visible_texture, &blend_transition->wrkarea, &trgwin);
}
}
} else {
SDL_SetTextureAlphaMod(_visible_texture, 255);
SDL_RenderCopy(_renderer.get(), _visible_texture, NULL, &winrc);
}
SDL_RenderPresent(_renderer.get());
}
@ -359,6 +368,76 @@ void SDLContext::swap_render_buffers() {
void SDLContext::swap_display_buffers() {
std::lock_guard _(_mx);
signal_push();
push_item(DisplayRequest::swap_render_buffers);
push_item(DisplayRequest::swap_visible_buffers);
}
void SDLContext::show_blend_transition(const SDL_Rect &wrkarea, const SDL_Rect &prev,
const SDL_Rect &next, float phase) {
std::lock_guard _(_mx);
signal_push();
push_item(DisplayRequest::blend_transition);
push_item(BlendTransitionReq{wrkarea, prev, next, phase});
}
SDL_Rect SDLContext::get_window_aspect_rect() const {
SDL_Rect w;
int ww;
int wh;
SDL_GetWindowSizeInPixels(_window.get(), &ww, &wh);
int apw = wh * 4 / 3;
int aph = ww * 3 / 4;
int fw;
int fh;
if (apw > ww) {
fw = ww;
fh = aph;
} else {
fw = apw;
fh = wh;
}
w.h = fh;
w.w = fw;
w.x = (ww - fw)/2;
w.y = (wh - fh)/2;
return w;
}
SDL_Point SDLContext::to_window_point(const SDL_Rect &winrc, const SDL_Point &pt) {
return {
pt.x * winrc.w / 640 + winrc.x,
pt.y * winrc.h / 480 + winrc.y,
};
}
SDL_Point SDLContext::to_source_point(const SDL_Rect &winrc, const SDL_Point &win_pt) {
return {
(win_pt.x - winrc.x) * 640 / winrc.w,
(win_pt.y - winrc.y) * 480 / winrc.h,
};
}
int SDLContext::transition_int(int beg, int end, float phase) {
int w = end - beg;
return beg + static_cast<int>(std::round(w * phase));
}
SDL_Rect SDLContext::transition_rect(const SDL_Rect &beg, const SDL_Rect &end, float phase) {
SDL_Rect out;
out.x = transition_int(beg.x, end.x, phase);
out.y = transition_int(beg.y, end.y, phase);
out.w = transition_int(beg.w, end.w, phase);
out.h = transition_int(beg.h, end.h, phase);
return out;
}
SDL_Rect SDLContext::to_window_rect(const SDL_Rect &winrc, const SDL_Rect &source_rect) {
SDL_Point pt1(source_rect.x, source_rect.y);
SDL_Point pt2(source_rect.x+source_rect.w, source_rect.y+source_rect.h);
SDL_Point wpt1(to_window_point(winrc, pt1));
SDL_Point wpt2(to_window_point(winrc, pt2));
return {wpt1.x, wpt1.y, wpt2.x - wpt1.x, wpt2.y - wpt1.y};
}

View file

@ -29,6 +29,9 @@ public:
void present_rect(uint16_t *pixels, unsigned int pitch, unsigned int x, unsigned int y, unsigned int xs,unsigned ys);
void swap_render_buffers();
void swap_display_buffers();
void show_blend_transition(const SDL_Rect &wrkarea, const SDL_Rect &prev, const SDL_Rect &next, float phase);
void show_slide_transition(const SDL_Rect &visible_from, const SDL_Rect &visible_where,
const SDL_Rect &hidden_from, const SDL_Rect &hidden_where);
MS_EVENT getMsEvent() {
std::lock_guard _(_mx);
@ -60,15 +63,27 @@ protected:
void operator()(SDL_Texture *);
};
struct UpdateMsg {
SDL_Rect rc;
std::vector<short> data;
struct BlendTransitionReq {
SDL_Rect wrkarea;
SDL_Rect prev;
SDL_Rect next;
float phase;
};
struct SlideTransitionReq {
SDL_Rect visible_from;
SDL_Rect visible_where;
SDL_Rect hidden_from;
SDL_Rect hidden_where;
};
enum class DisplayRequest {
update,
swap_render_buffers,
swap_visible_buffers,
blend_transition,
slide_transition
};
@ -102,6 +117,7 @@ protected:
void event_loop(std::stop_token stp);
void update_screen();
template<typename T>
requires(std::is_trivially_copy_constructible_v<T>)
void push_item(const T &item);
@ -114,6 +130,13 @@ protected:
void pop_item(QueueIter &iter, T &item);
std::string_view pop_data(QueueIter &iter, std::size_t size);
SDL_Rect get_window_aspect_rect() const;
static SDL_Rect to_window_rect(const SDL_Rect &winrc, const SDL_Rect &source_rect) ;
static SDL_Point to_window_point(const SDL_Rect &win_rec, const SDL_Point &pt) ;
static SDL_Point to_source_point(const SDL_Rect &win_rec, const SDL_Point &win_pt) ;
static SDL_Rect transition_rect(const SDL_Rect &beg, const SDL_Rect &end, float phase);
static int transition_int(int beg, int end, float phase);
void signal_push();