Help drawing to the screen at any time

Discussion of all aspects of the game engine, including development of new and existing features.

Moderators: Forum Moderators, Developers

Post Reply
DevEight
Posts: 2
Joined: March 26th, 2013, 9:40 am

Help drawing to the screen at any time

Post by DevEight »

Hello,

Me and some classmates are currently working on a project to make Wesnoth playable using only one's eyes (using an eyetracker).
Typically the user interacts with buttons etc by staring at them for a certain amount of time. To keep the user from accidentally clicking on things it is common practice to display some kind of indicator which shows how long time is left until the button is clicked. This can for example be a circle which slowly fills up.

I'm trying to implement such an indicator in the code right now and I have found a method to do so, but it isn't very robust and doesn't follow the proper workflow set up by the Wesnoth developers. How would one go about to properly implement this sort of feature in the game given that it has to be always be available (as it's used both in-game, in menus, etc)? I'm fairly familiar with the codebase and C++, so some pointers would be great.

Thanks a lot!

SkeletonCrew
Developer
Posts: 787
Joined: March 31st, 2006, 6:55 am

Re: Help drawing to the screen at any time

Post by SkeletonCrew »

It sounds interesting. Could you post a patch with your code? That makes discussing it easier.

DevEight
Posts: 2
Joined: March 26th, 2013, 9:40 am

Re: Help drawing to the screen at any time

Post by DevEight »

This is what my function which draws the indicator looks like currently:
video_ is the CVideo created when the game is first started and then passed on to interaction_controller.

The function is called every X ms with a new size_multiplier depending on how long time is left until the button gets clicked.

Code: Select all

void interaction_controller::draw_indicator(int x, int y, int square_side_length, double size_multiplier)
{
    surface& surf = video_->getSurface();
    ptrdiff_t start = reinterpret_cast<ptrdiff_t>(surf->pixels);
    unsigned w = surf->w;
    Uint32 color = SDL_MapRGBA(surf->format, 0, 0, 254, 60);

    int square_length = (int) ((double) square_side_length * size_multiplier);
    std::cerr << "Square length is:" << square_length << "\n";

    for(int i = x - square_side_length + square_length/2; i < x + square_side_length - square_length/2; i++)
    {
        for(int j = y - square_side_length + square_length/2; j < y + square_side_length - square_length/2; j++)
        {
            *reinterpret_cast<Uint32*>(start + (j * w * 4) + i * 4) = color;
        }
    }
    SDL_Flip(surf);
}
The major issue with this is that it writes directly to the main surface. I have thought about storing what the surface previously contained at those points and then restoring it before the button actually gets clicked, but I think there's a better way of doing this. I tried looking at SDL's documentation and using multiple surfaces and bliting one onto the other, but that seemed to crash the game. I'm assuming this is because I'm not doing things according to the way they have been designed in Wesnoth?

Any pointers on how to improve this piece of code? It would be great if I didn't have to hack into SDL to draw. Keep in mind that I must be able to draw the indicator at any point during the game.

Thanks!

AI
Developer
Posts: 2394
Joined: January 31st, 2008, 8:38 pm

Re: Help drawing to the screen at any time

Post by AI »

I'm not an expert on this part of the game, but I believe everything is simply blitted to the video surface, so there's no buffer you can restore from. Blitting from the video surface to back it up should be possible though. Could you post some code where you attempt this?

SkeletonCrew
Developer
Posts: 787
Joined: March 31st, 2006, 6:55 am

Re: Help drawing to the screen at any time

Post by SkeletonCrew »

In Wesnoth there is an option to use a coloured cursor, its code is in

cursor.[ch]pp

Have a look at the draw() function, I think the colour cursor is quite similar
to what you need. Drawing a rectangle can be done with the function
sdl_fill_rect(), residing in sdl_utils.[ch]pp.

I'm not sure yet what the best way is to get the movement events in Wesnoth's
event loop. But I think for testing it would be the easiest to replace the
coloured cursor with your own code.

Post Reply