Rough background:
I wrote a few functions in Python/Pygame to create a tiled level map from a coloured mini-map. One pixel on the small one stands for a certain type of tile on the big one.
Now I found out, that the colours you get by using Pygame's surface.get_at((x, y)) are no tuples despite the fact that they look like that...
Short example of the result of get_at on a black surface:
surf = pygame.Surface((64, 64)).convert()
surf.fill((0, 0, 0))
print(surf.get_at((32, 32))
Print:
(0, 0, 0, 255)
So I thought, creating a dictionary with the colours as key would work just like that:
tiledict = {(0, 0, 0, 255): [tile list 1], (255, 0, 0, 255): [tile list 2], etc}
for y in range(0, tilemap.get_height()):
for x in range(0, tilemap.get_width()):
clr = tilemap.get_at((x, y))
lvlmap.blit(tiledict[clr][random.randint(0, len(tiledict[clr]) - 1)]
Result:
lvlmap.blit(tiledict[clr][random.randint(0, len(tiledict[clr]) - 1)]
TypeError: unhashable type: 'pygame.Color'
Yet when I define the colours as tuples before using them as keys, it works:
GRAY = (128, 128, 128, 255)
print(GRAY == clr)
yields:
True
I have my workaround: I made the dictionary keys all strings and then do the get_at call this way
clr = str(tilemap.get_at((x, y)))
Does anybody have a clue what the issue is here? I find it rather interesting. Colours are no tuples and therefore not hashable, but when I ask, whether it's equal to a tuple, the return is "True"...
I also tried to define all colours as tuples and it worked as well. But that approach is way slower than my current one.
Does anybody have a clue of what else I could try without having to chance types?
The fact that the equality operator works for a tuple and a pygame.Color does NOT mean that you can index into a dict with a pygame.Color. You're thinking that's the same comparison but dicts need key objects to be hashable.
The PyGame.Color
type specifically supports comparisons to tuples , provided the tuple is of length 3 or 4 and contains integers in the range 0-255 (see the RGBAFromObj
source ).
This is explicitly documented on the PyGame.Color page :
Color objects support equality comparison with other color objects and 3 or 4 element tuples of integers
Any Python class can implement custom equality tests by implementing a __eq__
method .
The type also implements everything to be a sequence, returning the R, G, B and A components; you can turn a PyGame.Color
into a tuple by calling tuple()
on it:
tiledict[tuple(clr)]
and turn it back into a PyGame.Color
object by simply passing in the tuple as separate arguments:
pygame.Color(*tuple_of_rgba_ints)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.