#Getting weird textures in Raylib

41 messages · Page 1 of 1 (latest)

proven tiger
#

And I get weird texture id's and sizes get print out like:
button textureID: 980224768
button texture size: 0 x -8619008
button textureID: 32767
button texture size: 6 x 100663296
button textureID: 60106480
button texture size: 32767 x 2
button textureID: 100663296
button texture size: 5061087 x 0
I suppose that I'm doing something wrong with memory but I don't know.

lone brook
#

A slice (such as []Button) is just a pointer to data that exists somewhere else. When you assign a literal to a slice, as you're doing with button_list in set_and_init_screen, what it actually does is create a fixed array on the stack and then set the slice point to that fixed array. The stack space that the array is in is no longer reserved once the proc returns, and can be overwritten by any other procs that gets called

proven tiger
#

I think I understood it

#

        g_state.button_list[0] = Button{
            {GAME_SIZE[0] / 2 - g_state.assets.textures.gui.resume_button.width - 20, 150},
            g_state.assets.textures.gui.resume_button,
        }
        g_state.button_list[1] = Button{
            {GAME_SIZE[0] / 2 + 20, 100},
            g_state.assets.textures.gui.select_save_button,
        }
        g_state.button_list[2] = Button{
            {GAME_SIZE[0] / 2 - g_state.assets.textures.gui.help_button.width - 20, 300},
            g_state.assets.textures.gui.help_button,
        }
        g_state.button_list[3] = Button{
            {GAME_SIZE[0] / 2 + 20, 300},
            g_state.assets.textures.gui.quit_button,
        }```
Is this how I should do it?
cunning parrot
#

Don't forget to delete(g_state.button_list) when you don't need it.

Also, i would use dynamic array for this case, something like:

g_state.button_list = make([dynamic] Button) // no need to say button count here

// now just add buttons as needed (no need to specify index)

append(&g_state.button_list, Button{
            {GAME_SIZE[0] / 2 - g_state.assets.textures.gui.resume_button.width - 20, 150},
            g_state.assets.textures.gui.resume_button,
        })
// ...
proven tiger
#

thank you both

#

and i also get a segmentation fault if i delete() and set a new button list while iterating over it using a for in loop
i kinda fixed it by breaking the for loop after updating
and because that the button drawing runs every game frame only a flash happens
but is there any way to circumvent it from either segfaulting or having it flash

lone brook
proven tiger
#

can post a chunk of the code..

lone brook
#

That would probably help

proven tiger
#

draw_and_handle_button :: proc(button: Button) -> bool {
    mouse_pos := GetScaledMousePosition()
    hovered := rl.CheckCollisionPointRec(
        mouse_pos,
        rl.Rectangle {
            f32(button.position.x),
            f32(button.position.y),
            f32(button.texture.width),
            f32(button.texture.height),
        },
    )

    if rl.IsMouseButtonPressed(rl.MouseButton.LEFT) && hovered {
        button.callback()
        return false // Should break when false if looping over button_list // Prevents segmenation fault because button may modify the button list
    }

    draw_button(button, hovered)

    return true
}
for button in g_state.button_list {
            ok := draw_and_handle_button(button)
            if !ok {
                break
            }
        }```
#
GlobalState :: struct {
    ...
    button_list:     []Button,
    ...}
set_and_init_screen :: proc(screen: Screen, force: bool = false) {
    if g_state.current_screen == screen && !force {
        return
    }

    fmt.println("Freeing button list")
    free_button_list()
    fmt.println("Setting current screen")
    g_state.previous_screen = g_state.current_screen
    g_state.current_screen = screen
    #partial switch screen {
    case .MAIN_MENU:
        fmt.println("Setting up main menu")
        // Allocate the button list on the heap
        g_state.button_list = make([]Button, 4)

        g_state.button_list[0] = Button {
            {GAME_SIZE[0] / 2 - g_state.assets.textures.gui.resume_button.width - 20, 150},
            g_state.assets.textures.gui.resume_button,
            proc() {
                fmt.println("Resume button pressed")
                //set_and_init_screen(.GAME)
            },
        }
        g_state.button_list[1] = Button {
            {GAME_SIZE[0] / 2 + 20, 150},
            g_state.assets.textures.gui.select_save_button,
            proc() {
                set_and_init_screen(.SELECT_LEVEL)
            },
        }
        g_state.button_list[2] = Button {
            {GAME_SIZE[0] / 2 - g_state.assets.textures.gui.help_button.width - 20, 300},
            g_state.assets.textures.gui.help_button,
            proc() {
                set_and_init_screen(.STARS_OBTAINED)
            },
        }
        g_state.button_list[3] = Button {
            {GAME_SIZE[0] / 2 + 20, 300},
            g_state.assets.textures.gui.quit_button,
            proc() {
                g_state.exit_next_frame = true
            },
        }

    case .GAME:
        fmt.println("Setting up game")


    case:
        fmt.println("!!!!!!! Unimplemented screen")

    }
}
proven tiger
lone brook
#

If you try and use the buttons after you've deleted the slice, then that'll definitely cause issues. You probably need to draw and handle the buttons separately; handle them first, do any necessary state changes, and only draw once you've decided what's actually going to go on screen

proven tiger
#

which when for loop iterates again segfaults

#

maybe a dynamic array will fix it but i dont think that its necessary because the data is not that dynamic

lone brook
#

A dynamic array would make it easier to re-use the same memory, instead of having to delete it and reallocate every time you want to change it.

For the handling part, you'd probably still want the same logic to stop handling buttons once you've pressed ones. But for drawing, you don't need to worry about the button list changing mid-iteration

proven tiger
proven tiger
lone brook
#

The dynamic array will (somewhat) help prevent crashes in that the array won't be moved as often, but you can still get a different form of flashing issue if you don't separate the drawing logic. It's very common for game logic to be update first, then draw. If you try and do both at once, you can end up "splitting" your states, i.e. you draw the first 2 buttons of one state, but the second was clicked so it chagnes state, and you draw the third and on buttons from the other state

proven tiger
#

well the flashing was happening because i was breaking in the for loop to prevent segfaulting

#

but in the dynamic array no segfault happens and i can remove the break

proven tiger
cunning parrot
lone brook
proven tiger
#

okay i will separate them, thanks for the help

proven tiger
#

sorry to bother again but how exactly do i separate

        for button in g_state.button_list {
            ok, hovered := handle_button(button)
            if !ok {
                break
            }
        }
        // draw buttons
        for button in g_state.button_list {
            draw_button(button, hovered)
        }```
draw function needs is hovered
#

maybe a "hovered_buttons" dynamic array ?

cunning parrot
#

well. i would do it like:

  • add is_hovered: bool to your Button struct
  • now you can separate all: add all buttons -> update state of all buttons (set/clear is_hovered) -> draw all buttons
proven tiger
lone brook
#

Anything you don't set is zeroed by default. For booleans, that means false

cunning parrot
#

not exactly. if you init strcut every time before drawing/updating, it will be false by default. the "zero value" of type bool is false

proven tiger
lone brook
#

Ah, I guess that only works if you initialize things by name

cunning parrot
#

you need to specify field names if you don't specify all in order

#

or just add false in your init list -- up to you

proven tiger