RonenNess / GeonBit.UI

UI system for MonoGame projects.
MIT License
467 stars 63 forks source link

Implementing inventory #130

Closed dclipca closed 2 years ago

dclipca commented 2 years ago

How do you implement a drag-and-drop inventory with GeonBit.UI? I'm struggling to find a way to detect entities underneath the drag-and-dropped entity when the dragging stops.

dclipca commented 2 years ago

Of course, it boils down to iterating over all possible candidates and finding out where the dragged item is located. However, I wonder if GeonBit.UI has some utils for this or I should do it separately on my own,

RonenNess commented 2 years ago

Check out the entities API they have draggable flag and OnDragStart and OnDragEnd events.

You just need to validate the position on drag end to see which cell it falls into

dclipca commented 2 years ago

Check out the entities API they have draggable flag and OnDragStart and OnDragEnd events.

You just need to validate the position on drag end to see which cell it falls into

Indeed I just want to know if there's an API for finding which cell it falls into. Is there any or you have to iterate yourself over all candidate entities?

RonenNess commented 2 years ago

Why would you iterate entities just divide position by cell size to get index (assuming they are all same sized and in grid)

dclipca commented 2 years ago

Why would you iterate entities just divide position by cell size to get index (assuming they are all same sized and in grid)

The inventory is the same size and in grid but if I would use this approach:

This approach is good for very simple inventory systems but in my experience, doesn't scale to more complex requirements.

RonenNess commented 2 years ago

You're supposed to reduce the grid top left corner from the mouse position first. You also store the cell size in a variable to allow easy modification. That's how commercial games do it.

I recommend to read some tutorials on this subject it would make your life a lot easier.

dclipca commented 2 years ago

You're supposed to reduce the grid top left corner from the mouse position first. You also store the cell size in a variable to allow easy modification. That's how commercial games do it.

I recommend to read some tutorials on this subject it would make your life a lot easier.

Can you explain what do you mean by reducing the grid top left corner? Do you mean caching the position of the grid (the entity container that stores the items)?

RonenNess commented 2 years ago

IndexX = (mouse.x - gridPosition.x) / cellSize

dclipca commented 2 years ago

That's basically hashing into the cell index, am I right?

This presumes keeping track of all the grids (adding and deleting references to all the grids as they're created) and then hashing into them as the mouse is released after being dragged? Alright this is a great approach forgive me for my stupidity.

Though if there are multiple grids, you have to iterate through all of them, right?

dclipca commented 2 years ago

It seems to me that it's really no different that iterating through all the slots on the screen and checking for collision. It achieves the same purpose. Where am I wrong?

RonenNess commented 2 years ago

'That's basically hashing into the cell index, am I right?' - wouldn't call it hashing that's just calculating index from position.

Edit: ah I understand what you meant now with hashing, so yes you either need to translate x and y index to entity index in array (x + y * columns) or keep the cells in a 2d grid, which is simpler imo and would make everything easier like checking neighboring cells if you want items that are more than one cell.

If you have multiple grids you need to test first which grid you're in. All solutions are fine in this case it doesn't really matter (calculating index is a lot faster obviously, but performance won't be an issue either way for this use case). calculating index is just a lot simpler and cleaner and easier to debug. Can't get any more straightforward than that.

dclipca commented 2 years ago

'That's basically hashing into the cell index, am I right?' - wouldn't call it hashing that's just calculating index from position.

Edit: ah I understand what you meant now with hashing, so yes you either need to translate x and y index to entity index in array (x + y * columns) or keep the cells in a 2d grid, which is simpler imo and would make everything easier like checking neighboring cells if you want items that are more than one cell.

If you have multiple grids you need to test first which grid you're in. All solutions are fine in this case it doesn't really matter (calculating index is a lot faster obviously, but performance won't be an issue either way for this use case). calculating index is just a lot simpler and cleaner and easier to debug. Can't get any more straightforward than that.

Thank you very much for your help. I think I said this somewhere in another issue, but this library is a piece of art. Tried quite a few MonoGame UI libraries but GeonBit.UI was 10X better than any of them.

In case I would not end up abandoning the game prototype I'm making right now, would it be alright if I make an easy entity detection API (for drag-and-dropping purposes or something else) in GeonBit.UI and send a pull request?

RonenNess commented 2 years ago

Thanks!

There are already plenty of ways to do this, like IsTouching. Please read the online docs, everything is covered there. Using vs auto complete with guessing also works most of the time.

dclipca commented 2 years ago

Thanks!

There are already plenty of ways to do this, like IsTouching. Please read the online docs, everything is covered there. Using vs auto complete with guessing also works most of the time.

That's for a single entity though. There's no API for just checking what entities are located in a specific area. I understand it's not necessary though it might come handy.