File name based on random numbers


#1

Sorry to be a pain again guys, but I’m not sure how to approach my problem.

Let me explain quickly:
I create 2 random numbers, but I want to build a filename based on that and then need to blit that to the screen, for example:

rand1 = random.getrandbits(2)
rand2 = random.getrandbits(3)
filename = "graphic" + rand1 + "_" + rand2

So the real filename would look like:

screen.blit(file.graphic3_5, x, y) etc...

but in my example above, I want to be able to do

screen.blit(file.filename, x, y)

I tried to change the surface object names to:

parts = []
parts[0, 0] = upygame.surface.Surface(12, 12, parts0_0Pixels)

but then I get an error “int object doesn’t support item assignment”

Then I tried:

parts[0][0] = upygame.surface.Surface(12, 12, parts0_0Pixels)

but then I get an error “list object isn’t callable” or something to that effect.

As it is right now, it works like this:

parts0_0 = upygame.surface.Surface(12, 12, parts0_0Pixels)

and I can blit it with screen.blit(file.parts0_0, x, y)

Just so you know, the “file” bit is the include at the top as I keep my graphics separate from code.

Hope this makes sense to someone. If this can’t be done, any other solutions?


#2

I assume you’re using Python.

So you want a 2 dimensional list, which is a list that contains lists that contain your items.

parts = [] will only let you create the first layer, aka the list of list.
Then you’ll have to create the individual list of items.

parts[0] = [] - you’ll have to do this once before, for each index. For example, you could check if a list exist at that index, and add it on the fly. Remember, once, or you’ll erase the previous version!
Then after parts[0][0] = item will work.


#3

Thanks for your reply carbonacat. I’m not sure I follow what you are saying. Can you provide a simple example?

At the end of the day, all I’m trying to do is create an array and each index needs to be assigned to a surface object/image. In other languages this is possible, for example:

partsArray = []
partsArray[0] = []
partsArray[0][0] = upygame.surface.Surface(12, 12, parts0_0Pixels)
partsArray[0][1] = upygame.surface.Surface(12, 12, parts0_1Pixels)

That way I can use the random numbers to display the relevant image on screen as they will relate to those multidimensioned array indexes.


#4

I’m confused. Is your question about how to generate file names based on random numbers or about how to make a ‘2D array’ in Python?


#5

Not a 2D array I think?
Like I said, instead of calling each image by a unique filename reference:

parts0_0Pixels = b'\
\x00\x49\xa8\x88\x88\x88\
'
parts0_0 = upygame.surface.Surface(12, 12, parts0_0Pixels)

I want to use a 2d array filename, if that makes any sense now?

Ok let me give you an example. You have 24 unique images (as above). You want to show an image at random using your random number generator.
Are you going to use 24 if statements to see if the random number matches a string value like the filename or something like that, or would it rather be easier to display the correct image using the random number directly in the filename…

[More editing - pseudo code, not real…]

This is what I’ve done in the past:

image1 = loadimage("blah1.png")
image2 = loadimage("blah2.png")
image3 = loadimage("blah3.png")

imageArray = [image1, image2, image3]

randNumber = Rnd(3)

// Say the result was 2

Display.Image(imageArray[randNumber]) // This will then display image2.

#6

Neither.
I’d generate a random number and use it to index the array/list, then the ‘filename’ doesn’t matter at all.

Edit:
I forgot to use .append instead of just indexing.
I think this is what @carbonacat’s answer was missing too.
You can’t just go indexing a list without appending items first.

Which in Python I think would be something like:

import upygame

image_pixels_0 = b'\
\x00\x49\xa8\x88\x88\x88\
'
image_pixels_1 = b'\
\x00\x49\xa8\x88\x88\x88\
'
image_pixels_2 = b'\
\x00\x49\xa8\x88\x88\x88\
'
image_pixels_3 = b'\
\x00\x49\xa8\x88\x88\x88\
'

def generate_image_list():
	result = []
	result.append(upygame.surface.Surface(12, 12, image_pixels_0))
	result.append(upygame.surface.Surface(12, 12, image_pixels_1))
	result.append(upygame.surface.Surface(12, 12, image_pixels_2))
	result.append(upygame.surface.Surface(12, 12, image_pixels_3))
	return result
	
images = generate_image_list()

def get_random(n):
	return urandom.getrandbits(32) % n

def select_random(list):
	return list[get_random(len(list))]

Then to get a random image it’s just a matter of select_random(images).

I don’t know for definite if that code works because I don’t know Python or the Pokitto’s version of pygame very well, but something like that should work fine.


Technically in micropython on the Pokitto the images aren’t stored in files so there aren’t any filenames.
Instead they’re stored in variables, which have variable names (or ‘identifiers’ to be more technical).


#7

Thank you Pharap.
I think that generating an image list like yours will be the way to get it to work.
Because in that case, the ‘images’ variable now holds the array of identifiers, so if I were to say screen.blit(images[randomvalue]), x, y) it will do what I need. (I think)

I’m also brand new to Python/upygame, so I’m not sure about many things yet.


#8

It took me a lot of fiddling around but I made a demo that sort of works:

import upygame
import urandom

image_pixels_0 = b'\
\x00\x49\xA8\x88\x88\x88\
'
image_pixels_1 = b'\
\x88\x88\x88\x88\x88\x88\
'
image_pixels_2 = b'\
\x49\x49\x49\x88\x88\x88\
'
image_pixels_3 = b'\
\xA8\xA8\xA8\x88\x88\x88\
'

def generate_image_list():
	result = []
	result.append(upygame.surface.Surface(6, 2, image_pixels_0))
	result.append(upygame.surface.Surface(6, 2, image_pixels_1))
	result.append(upygame.surface.Surface(6, 2, image_pixels_2))
	result.append(upygame.surface.Surface(6, 2, image_pixels_3))
	return result
	
images = generate_image_list()

def get_random(n):
	return urandom.getrandbits(30) % n

def select_random(list):
	return list[get_random(len(list))]

screen = upygame.display.set_mode()
	
image = select_random(images)
	
while True:
	event = upygame.event.poll()
	
	if event != upygame.NOEVENT:
		if event.type == upygame.KEYDOWN:
			image = select_random(images)
		if event.type == upygame.KEYUP:
			pass
	
	screen.blit(image, 0, 0)

	upygame.display.flip()

For some reason if I using something more than 30 as the argument to getrandbits it throws an overflow exception.

Anyway, if you run this, you should find that pressing a button picks a new random image.

Pretty much.

Technically what happens is that the global variables image_pixels_0 et cetera reference the actual image data and then generate_image_list creates a list, appends references to the generated ‘surfaces’ to the list and then returns that list.

So images ends up holding references to the created surfaces,
which internally hold references to the image data.

Hopefully that makes sense, and hopefully I’ve got that right.
Like I say, I don’t really know Python very well because I don’t use it much.
I tend to stick to C++ for many reasons.


#9

Thanks for helping Pharap.
I got it working, albeit slightly differently, and most likely a bit ugly code-wise, but hey, it works for now.

I’m learning Python for more than just game dev reasons, so it’s to my benefit. Starting small and working up.
I’m now having to tackle keypress issues whereby the resultant keypress triggers multiple times a second and I need it to trigger only once, until the person triggers a keyup event on the same key. But that’s another story for another day and it’s almost 4am here and I need to sleep :slight_smile:


#10

I think I’m on the same timezone as you.
What is ‘sleep’? :P