Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to access tile data? #10

Open
TLINDEN opened this issue Jan 29, 2024 · 8 comments
Open

How to access tile data? #10

TLINDEN opened this issue Jan 29, 2024 · 8 comments

Comments

@TLINDEN
Copy link

TLINDEN commented Jan 29, 2024

Hi,

this is possibly a dumb question, but I'm not getting it yet :) Let's say I define grid this way:

type Cell struct {
	sprite string
}

grid := tile.NewGridOf[Cell](width, height)

When iterating over the grid, like this:

grid.Each(func(point tile.Point, t tile.Tile[Cell]) {
  // t.Value() returns an int16 which is 0 in all tiles, no Cell ???
})

Of course I can create another map of cells like this:

cells := make(map[tile.Point]Cell, width*height)
grid.Each(func(point tile.Point, t tile.Tile[Cell]) {
  cells[point] = &Cell{"...."}
})

But that way I'd have two grids, the one provided by the tile module and my "shadow" grid holding the cell data (where I'd put things like sprites, properties etc).

What am I doing wrong?

Thanks in advance,
Tom

@kelindar
Copy link
Owner

There's a few methods you can use to manipulate the objects associated to a tile Add(), Del() and Range() (see: https://github.com/kelindar/tile/blob/master/grid.go#L369-L391)

@TLINDEN
Copy link
Author

TLINDEN commented Jan 29, 2024

Ah, thanks a lot, this works!

@TLINDEN
Copy link
Author

TLINDEN commented Jan 30, 2024

Ahm, no it doesn't :(

Here's my test program:

package main

import (
	"fmt"

	"github.com/kelindar/tile"
)

type Cell struct {
	sprite string
}

const (
	height int16 = 9
	width  int16 = 9
)

func main() {
	tl := Cell{"topleft"}
	tr := Cell{"topright"}
	bl := Cell{"bottomleft"}
	br := Cell{"bottomright"}
	vt := Cell{"vertical"}
	h := Cell{"horizontal"}
	l := Cell{"lawn"}

	matrix := [][]Cell{
		{tl, h, h, h, h, h, h, h, tr},
		{vt, l, l, l, l, l, l, l, vt},
		{vt, l, l, l, l, l, l, l, vt},
		{vt, l, l, l, l, l, l, l, vt},
		{vt, l, l, l, l, l, l, l, vt},
		{vt, l, l, l, l, l, l, l, vt},
		{vt, l, l, l, l, l, l, l, vt},
		{vt, l, l, l, l, l, l, l, vt},
		{bl, h, h, h, h, h, h, h, br},
	}

	grid := tile.NewGridOf[Cell](width, height)

	count := 1
	grid.Each(func(point tile.Point, t tile.Tile[Cell]) {
		fmt.Printf("Adding cell %d on %d,%d\n", count, point.X, point.Y)
		cell := matrix[point.X][point.Y]
		t.Add(cell)
		count++
	})

	grid.Each(func(point tile.Point, t tile.Tile[Cell]) {
		fmt.Println(point)
		t.Range(func(cell Cell) error {
			fmt.Printf("Cell pos: %d,%d (%s)\n",
				point.X, point.Y, cell.sprite)
			return nil
		})
	})
	fmt.Println()
}

So, I create a 2d matrix of Cells and put them into the grid. Then I just iterate over the grid and print every cell on every grid position. Here's the output:

scip@tripod: % go run main.go 
Adding cell 1 on 0,0
Adding cell 2 on 1,0
Adding cell 3 on 2,0
Adding cell 4 on 0,1
Adding cell 5 on 1,1
Adding cell 6 on 2,1
Adding cell 7 on 0,2
Adding cell 8 on 1,2
Adding cell 9 on 2,2
Adding cell 10 on 3,0
Adding cell 11 on 4,0
Adding cell 12 on 5,0
Adding cell 13 on 3,1
Adding cell 14 on 4,1
Adding cell 15 on 5,1
Adding cell 16 on 3,2
Adding cell 17 on 4,2
Adding cell 18 on 5,2
Adding cell 19 on 6,0
Adding cell 20 on 7,0
Adding cell 21 on 8,0
Adding cell 22 on 6,1
Adding cell 23 on 7,1
Adding cell 24 on 8,1
Adding cell 25 on 6,2
Adding cell 26 on 7,2
Adding cell 27 on 8,2
Adding cell 28 on 0,3
Adding cell 29 on 1,3
Adding cell 30 on 2,3
Adding cell 31 on 0,4
Adding cell 32 on 1,4
Adding cell 33 on 2,4
Adding cell 34 on 0,5
Adding cell 35 on 1,5
Adding cell 36 on 2,5
Adding cell 37 on 3,3
Adding cell 38 on 4,3
Adding cell 39 on 5,3
Adding cell 40 on 3,4
Adding cell 41 on 4,4
Adding cell 42 on 5,4
Adding cell 43 on 3,5
Adding cell 44 on 4,5
Adding cell 45 on 5,5
Adding cell 46 on 6,3
Adding cell 47 on 7,3
Adding cell 48 on 8,3
Adding cell 49 on 6,4
Adding cell 50 on 7,4
Adding cell 51 on 8,4
Adding cell 52 on 6,5
Adding cell 53 on 7,5
Adding cell 54 on 8,5
Adding cell 55 on 0,6
Adding cell 56 on 1,6
Adding cell 57 on 2,6
Adding cell 58 on 0,7
Adding cell 59 on 1,7
Adding cell 60 on 2,7
Adding cell 61 on 0,8
Adding cell 62 on 1,8
Adding cell 63 on 2,8
Adding cell 64 on 3,6
Adding cell 65 on 4,6
Adding cell 66 on 5,6
Adding cell 67 on 3,7
Adding cell 68 on 4,7
Adding cell 69 on 5,7
Adding cell 70 on 3,8
Adding cell 71 on 4,8
Adding cell 72 on 5,8
Adding cell 73 on 6,6
Adding cell 74 on 7,6
Adding cell 75 on 8,6
Adding cell 76 on 6,7
Adding cell 77 on 7,7
Adding cell 78 on 8,7
Adding cell 79 on 6,8
Adding cell 80 on 7,8
Adding cell 81 on 8,8
0,0
Cell pos: 0,0 (topleft)
1,0
2,0
Cell pos: 2,0 (vertical)
0,1
1,1
2,1
0,2
Cell pos: 0,2 (horizontal)
1,2
2,2
Cell pos: 2,2 (lawn)
3,0
4,0
5,0
Cell pos: 5,0 (vertical)
3,1
4,1
5,1
3,2
4,2
5,2
Cell pos: 5,2 (lawn)
6,0
7,0
Cell pos: 7,0 (vertical)
8,0
Cell pos: 8,0 (bottomleft)
6,1
7,1
8,1
6,2
7,2
Cell pos: 7,2 (lawn)
8,2
Cell pos: 8,2 (horizontal)
0,3
1,3
2,3
0,4
1,4
2,4
0,5
Cell pos: 0,5 (horizontal)
1,5
2,5
Cell pos: 2,5 (lawn)
3,3
4,3
5,3
3,4
4,4
5,4
3,5
4,5
5,5
Cell pos: 5,5 (lawn)
6,3
7,3
8,3
6,4
7,4
8,4
6,5
7,5
Cell pos: 7,5 (lawn)
8,5
Cell pos: 8,5 (horizontal)
0,6
1,6
2,6
0,7
Cell pos: 0,7 (horizontal)
1,7
2,7
Cell pos: 2,7 (lawn)
0,8
Cell pos: 0,8 (topright)
1,8
2,8
Cell pos: 2,8 (vertical)
3,6
4,6
5,6
3,7
4,7
5,7
Cell pos: 5,7 (lawn)
3,8
4,8
5,8
Cell pos: 5,8 (vertical)
6,6
7,6
8,6
6,7
7,7
Cell pos: 7,7 (lawn)
8,7
Cell pos: 8,7 (horizontal)
6,8
7,8
Cell pos: 7,8 (vertical)
8,8
Cell pos: 8,8 (bottomright)

As can be seen, 81 cells have been added successfuly but only a subset could be retrieved (25 cells out of 81). The other grid positions have no cells. I'd expect to be able to retrieve all 81 cells I put into the grid earlier.

@TLINDEN
Copy link
Author

TLINDEN commented Jan 30, 2024

PS: and there's a pattern (although I can't see which): it doesn't matter how often the latter loops runs, it's always the same grid positions without a cell. So I suspect, the t.Add(cell) doesn't work right.

@g-getsov
Copy link

g-getsov commented Sep 5, 2024

Just spent a couple hours debugging the exact same issue. @TLINDEN The pattern that your seeing is that the "state" in each "page" of 3x3 tiles is stored in a map[T]uint8 this map stores the relation of state (T) to tile index in the page. The problem here is that when, like in your case, the state (the map key) is equal(==) between tile.Add() calls, the map fails to store the relation correctly but instead stores only the last tile index with the given state. (offending code)

In your case, every "page" that contains more than one instance of non-unique state like lawn, horizontal or vertical will only store one instance of the relation. That's why you're seeing irregularities in the tile.Range() function. It skips tiles because they have no state.

I solved this by making my state unique (just added a idx value) and now the map stores the relation of state to tile index correctly because each struct is considered a unique key.

@kelindar I believe a fix would be to inverse the relationship of the map from map[T]uint8 to map[uint8]T so identical state can be stored per index if a user wishes so. The only cascading change from this flip would be to potentially change the tile.Del(T) method to something like tile.Del() or tile.Clear() to avoid looping over the map to find if the state is present.

I'm happy to put a fix in if you agree with the solution.

@kelindar
Copy link
Owner

@g-getsov If we inverse the relationship, we could simply have []T and lookup by index instead of a map. But I think you're right, T could then be implemented in any way necessary, so if one wants to store a more complex state it can be itself an array or any other structure. Let's do this, but we probably should also reconsider the API itself (i.e. Add, Del, Range)

@nneesshh
Copy link

is any progress now?

@g-getsov
Copy link

@nneesshh I've got a working PR draft with the fix on my home desktop, but I'm AFK for the next week. I'll put it up for review first thing when I get back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants