sarkahn / bevy_ascii_terminal

A simple terminal for rendering ascii in bevy.
MIT License
101 stars 14 forks source link

How to convert from mouse world space coords to terminal index location to implement tooltips for a rogue like? #22

Open iwyatt opened 9 months ago

iwyatt commented 9 months ago

Hi, I'm trying to convert the world space coordinates of the mouse position to the ascii terminal index location so I can implement mouse-over tooltips for a roguelike dungeon crawler. Unfortunately, the bevy examples I've found don't seem to function properly.

My best guess is that this is because the AutoCamera doesn't correctly specify a transform between the window's worldspace to the gamespace.

I believe I can back this out by using my own function to subtract the viewport from the window size / 2 (Since the camera is centered within the window) and then modulo/divide by the map size to get the x/y coordinates, respectively. I suspect that this solution will either (A) be computationally inefficient since it will be calculated every frame or (B) if the calculation is stored to prevent (A), it will break if/when the window is resized. (I suppose I could (C) implement an event system to detect a resize event and then recalculate the computed value).

Is there an example or recommended method to accomplish this?

For reference, I'm basically building the Roguelike Tutorial but in Bevy with bevy_ascii_terminal.

iwyatt commented 9 months ago

Here is the function that I'm calling to convert from the mouse position in the window to the mouse position as a tile position (note the todo item about making it work for different size windows):

fn window_pos_to_map_pos(camera: &TiledCamera, mouse_pos: &Vec2) -> (i32, i32) {
    // TODO : bring in game desktop Window variables and convert mouse pos based on window size
    let camera_space_max_x = bevy_ascii_terminal::Size2d::width(&camera.viewport_size())
        + bevy_ascii_terminal::Size2d::width(&camera.viewport_pos());
    let camera_space_min_x =
        camera_space_max_x - bevy_ascii_terminal::Size2d::width(&camera.viewport_size());
    let mouse_local_x = mouse_pos.x as i32 - camera_space_min_x as i32;
    let tile_x = mouse_local_x / 8 - 1; //divided by pixels per tile minus border

    let camera_space_max_y = (bevy_ascii_terminal::Size2d::height(&camera.viewport_size())
        + bevy_ascii_terminal::Size2d::height(&camera.viewport_pos()))
        as i32;
    let camera_space_min_y =
        camera_space_max_y - bevy_ascii_terminal::Size2d::height(&camera.viewport_size()) as i32;
    let mouse_local_y = camera_space_max_y - camera_space_min_y - mouse_pos.y as i32;
    let tile_y = (-camera_space_max_y / 2 + mouse_local_y) / 8 + MAP_HEIGHT + 2; //divide by pixel height plus map height plus 2 for gui

    (tile_x, tile_y)
}

If there is a similar function already in the bevy_ascii_terminal library, I was unable to find it.