FAQ: Python in Pokitto

Deviously clever. I love it.

2 Likes

This also has the advantage to open a predictable way to control the RNG, which is really interesting for speedrunning :slight_smile:

1 Like

Exactly how I do it in Noggin. A very good method.

1 Like

@spinal the goal in Noggin is to flip all tiles right? Also is it possible to make so that the game knows when there’s no moves possible and display a game over? My guess is that it would be a bit complicated but I had to ask. I am enjoying the game a lot either way.

That’s the goal alright. As for detecting no further moves, I had though about that, but I really can’t think of a way to do it. I would imagine some sort of flood-fill or path-finding routine might be involved, but I’m not sure how possible it could be.

Well in this case I guess you would have to run a check that check the tile you are on and see if you can move that many times. And if you don’t have any ‘!’ it result in a game over. So yeah basically what you said I guess would work.

Technically you get the same sequence, but at a different point in the sequence.

It won’t matter though, as long as nobody is trying to do encryption with it,and as long as the use of random numbers isn’t deterministic.
(E.g. if it was being used to generate the next piece in tetris then you could theoretically predict the next piece.)

Or just edit the code to use a specific seed, nobody would notice. :P

If I knew the rules I could have a go at figuring out how to do that.
Most likely it would involve a graph, a stack or a tree,
and also RAM might be a limiting factor.

Is there a way to make upython store some data in Flash.
So like a tuple that contains game data not alterable?

Bytes literal (b’’)goes to ROM. There are also a const keyword. More info here: http://docs.micropython.org/en/latest/reference/constrained.html

1 Like

Is there a way to build a surface defining also x and y?

now upg.surface.Surface(w, h, pixels) to like upg.surface.Surface(x, y, w, h, pixels) ?

I can return a Rect with surface.get_rect() but it seems like an immutable object, so not really useful to store some data.

Hmm…why would you like to have that?

Associating a surface with a position isn’t a good idea because you might want to use the same surface for more than one object and each object would have a different position.

Just write a class that combines a surface with a position:

class Object:
	def __init__(self, x, y, surface):
		self.x = x
		self.y = y
		self.surface = surface
		
	def draw(self, transparent_index = 0):
		surface.blit(self.surface, self.x, self.y, transparent_index)
		
	def get_rectangle(self):
		rect = self.surface.get_rect()
		rect.x = self.x
		recy.y = self.y
		return rect

(I’m assuming this is right, I don’t know much about the semantics of Python, so I don’t know if surface.get_rect() returns a copy or a reference.)

Come to think of it, if the x and y of surface.get_rect() will always be 0,
maybe get_width() and get_height() would be more appropriate?
Unless it’s done that way so there’s only one function instead of two,
I would presume function calls have a larger overhead in Python.

1 Like

Just popped to my mind that @jonne has said that io pins are mapped to the memory address, just like in the computers of the eighties. So if you know the right address, you can read the keys directly using memNN() functions. Not tested thought.

1 Like

Maybe I’m just confused about surface use. Considering it can return a rectangle I’ve supposed it contains all rectangle data (x,y,w,h) so it can be used as a Tile.
Otherwise it could be better to just create a class Tile that contains all rectangle data and a reference to the pixel data.
@Pharap proposed class is just what I’m using now, but it looks like a waste of space to define x and y again and not use the surface position instead.

From what I gather, surfaces don’t have a position,
get_rect() just uses 0 where x and y should be.
(I could be wrong, I haven’t checked the code, but that’s what I would expect the behaviour to be.)

The concept of a surface is roughly equivalent to a 2D array of pixel data,
it doesn’t include the position onto which the surface should be drawn because the surface might need to be drawn in more than one place.

In other words, a surface is supposed to be a flyweight:
http://gameprogrammingpatterns.com/flyweight.html

Think of it a bit like this…


(Image taken from the afforementioned article about the flyweight pattern.)

‘Grass’, ‘river’ and ‘hill’ are surfaces,
but they’re being drawn in more than once place in order to be tiled,
so associating an x and a y with the actual surface wouldn’t be very useful,
it makes more sense to associate the x and y with the tiles themselves.
(Or more likely, the tiles are in a grid and the x and y are determined by the grid rather than the tiles).

(Actual tile drawing usually uses indices rather than pointers because indices tend to be cheaper and more useful, but hopefully it illustrates the idea.)

2 Likes

It should really return width and height instead of Rect.

it is because I wanted to keep it (at least partly) source compatible with the original PyGame:
https://www.pygame.org/docs/ref/surface.html#pygame.Surface.get_rect

1 Like

If I crate a tile class (surface + position) at runtime, what’s the best way to pass the surface in the constructor and avoid memory consumption? Also some tiles may have multiple surface.
I’m now passing the pixels data in the constructor, and create surface when need. But I’m not sure that’s the right way to do.

Here a project I’m working on, if you want to give a look: Rings.zip (23.6 KB)

aaaaac

2 Likes

If you’re trying to do a tile system and you don’t want to use the tilemap module or can’t use the tilemap module because of its constraints…

A better way is to store the tiles as a 2D array of tile types/tile indices.
Then when rendering you map those tile types to surface indices (storing all your tile surfaces in an array so you can map a ‘surface index’ to a surface) and you draw the tiles like that.

E.g.

for y in range(map_width):
	draw_y = # calculate draw y
	for x in range(map_height):
		draw_x = # calculate draw x
		tile_type = get_tile(x, y)
		surface = get_surface(tile_type)
		Surface.blit(surface, draw_x, draw_y, transparent_index)

If you’re trying to have coins and/or moving platforms, those should be entities, not tiles.
Alternatively, you can have two layers of tiles.

If having a 2D array of tiles is too memory hungry then you can have a sparse matrix instead, but sparse matrices tend to be more computationally complex.


I take it that by ‘partly’, you mean it doesn’t do this:

You can pass keyword argument values to this function. These named values will be applied to the attributes of the Rect before it is returned. An example would be ‘mysurf.get_rect(center=(100,100))’ to create a rectangle for the Surface centered at a given position.

Also, pygame’s surface supports get_width() and get_height():

https://www.pygame.org/docs/ref/surface.html#pygame.Surface.get_width

https://www.pygame.org/docs/ref/surface.html#pygame.Surface.get_height

moving platform here. So entities :grin: