FAQ: Python in Pokitto


#61

Like this:
myrect = upygame.Rect(x,y,w,h)


#62

@Hanski if I create a rom pixel data like this:

boxPixel = b'\
\xff\xff\xff\xff\
\xfc\xcc\xcc\xfc\
\xfc\xff\xfc\xfc\
\xfc\xff\xcc\xfc\
\xfc\xfc\xcc\xfc\
\xfc\xcc\xcc\xfc\
\xff\xff\xff\xfc\
\xfc\xcc\xcc\xcc\
'

and then I pass this data to a class like this:

class Tile:
    def __init__(self,pixels,x,y,w,h):
        self.pixels = pixels
        self.surface = upg.surface.Surface(w, h, pixels[0])

in this way

newTile = tile.Tile([td.boxPixels],xp,yp,12,12)

Am I wasting memory? Consider the same tile could be create n-times at different x and y. Is this the correct way to manage it? Data is passed by value or reference?
I keep a reference to the pixel because the tile could be animated (passing an array), and so I create different surface as time elapsed.
Hope I’ve been clear.


#63

opps, I’m an idiot.


#64

I suppose it is passing a reference. You can check that by calling:

gc.collect()
print ("free:",gc.mem_free())

before and after you have created an instance of the class. Put import gc at start of the file.


#65

how “I suppose”? You’re my python guru! You should be sure of it! :wink:
It seems so.:grin:


#66

Sorry to disappoint :wink: I actually know about Python language far less that about C++.


#67

Why do you need to wrap it in []?
Wouldn’t passing boxPixel be enough?
Presumably that creates a copy in a new array?
(Assuming it’s legal syntax.)

It’s passed by value, but references are values.

Comparing it to C++, a Python object reference is like a pointer.
If you pass an object reference to a function, the object that the reference refers to can be manipulated, but if you try to change the reference then you only change the function parameter, the variable that was passed to the function remains the same.

Run this code and hopefully you’ll see what I mean:

def a_function(a_list):
	# Alters the object by appending 2
	a_list.append(2)
	# Reassigns the a_list parameter to a new object
	a_list = [10]
	# Appends a 5 to the new object
	a_list.append(5)
	# Prints [10, 5]
	print(a_list)
	
my_list = [0, 1]

# Prints [0, 1]
print(my_list)

# Prints [10, 5]
a_function(my_list)

# Prints [0, 1, 2]
print(my_list)

(You can try it online here.)


And before anyone asks, I’m not a Python guru either,
I barely know the language and I’m far from its biggest fan,
I’m just relatively good at learning languages and finding information.


#68

I’m passing an array, that way the tile take care of animation loop if it found something to iterate.

Yes it is, python is really smart on array operations (slicing and iteration in primis)

I see. Primitives are also passed by value.

It’s also fun that we are all using python now, but nobody seems to be really used to it. :sweat_smile:


#69

I checked and I was right, you’re actually instantiating a new list.
But instead of copying the contents of boxPixels into the list, it’s actually constructing a new list with boxPixels as its only element.

I.e. tile.pixels[0] is a reference to boxPixels.
As demonstrated by this program:

boxPixels = b'\
\xff\xff\xff\xff\
\xfc\xcc\xcc\xfc\
\xfc\xff\xfc\xfc\
\xfc\xff\xcc\xfc\
\xfc\xfc\xcc\xfc\
\xfc\xcc\xcc\xfc\
\xff\xff\xff\xfc\
\xfc\xcc\xcc\xcc\
'

class Tile:
    def __init__(self,pixels,x,y,w,h):
        self.pixels = pixels
        
a = Tile([boxPixels], 0, 0, 0, 0)
b = Tile([boxPixels], 0, 0, 0, 0)

print("a.pixels == b.pixels: ", a.pixels == b.pixels)
print("a.pixels is b.pixels: ", a.pixels is b.pixels)
print("a.pixels[0]: ", a.pixels[0])
print("a.pixels[0] is boxPixels: ", a.pixels[0] is boxPixels)
print("b.pixels[0]: ", b.pixels[0])
print("b.pixels[0] is boxPixels: ", b.pixels[0] is boxPixels)

Output:

a.pixels == b.pixels:  True
a.pixels is b.pixels:  False
a.pixels[0]:  b'\xff\xff\xff\xff\xfc\xcc\xcc\xfc\xfc\xff\xfc\xfc\xfc\xff\xcc\xfc\xfc\xfc\xcc\xfc\xfc\xcc\xcc\xfc\xff\xff\xff\xfc\xfc\xcc\xcc\xcc'
a.pixels[0] is boxPixels:  True
b.pixels[0]:  b'\xff\xff\xff\xff\xfc\xcc\xcc\xfc\xfc\xff\xfc\xfc\xfc\xff\xcc\xfc\xfc\xfc\xcc\xfc\xfc\xcc\xcc\xfc\xff\xff\xff\xfc\xfc\xcc\xcc\xcc'
b.pixels[0] is boxPixels:  True

I’d like to point out that if you just want something you can index, you can index boxPixels on its own:

boxPixels = b'\
\xff\xff\xff\xff\
\xfc\xcc\xcc\xfc\
\xfc\xff\xfc\xfc\
\xfc\xff\xcc\xfc\
\xfc\xfc\xcc\xfc\
\xfc\xcc\xcc\xfc\
\xff\xff\xff\xfc\
\xfc\xcc\xcc\xcc\
'

class Tile:
    def __init__(self, pixels, x, y, w, h):
        self.pixels = pixels
        
a = Tile(boxPixels, 0, 0, 0, 0)
b = Tile(boxPixels, 0, 0, 0, 0)

print("a.pixels == b.pixels: ", a.pixels == b.pixels)
print("a.pixels is b.pixels: ", a.pixels is b.pixels)
print("a.pixels[0]: ", a.pixels[0])
print("a.pixels[0] is boxPixels: ", a.pixels[0] is boxPixels)
print("b.pixels[0]: ", b.pixels[0])
print("b.pixels[0] is boxPixels: ", b.pixels[0] is boxPixels)

This isn’t slicing or iteration, this is construction.

(Side note: it would be possible to simulate slicing in C++, but you’d have to use a different operator. E.g. you could do array & slice(1, 2), or array | slice(1, 2), or even array, slice(1, 2). Object ownership would be a bit of a conundrum though.)

That’s expected behaviour.

Everything is pass by value, but there aren’t any primitive references, only object references.
(Unless Python supports boxing like C# and Java do.)

Can I have C++ back please? :P

Seriously though, although there’s less code involved I’m really missing enums, constants, function overloading* and static typing.

* Proper automatic function overloading, not manually checking the dynamic types of the arguments

At least there’s operator overloading though, so I guess that’s one up over C and Java.


#70

Probably a typo here? You probably want to check b.pixels[0] instead of a.pixels[0]?
EDIT: probably same error in the previous line aswell.


#71

Yep, fixed it. The output is the same either way.


#72

Is it possible to stop the music from playing?


#73

Yep, there is a pause() -method.


#74

I’m trying to read some buttons, specifically a master system controller, but I have an issue and I don’t know what’s causing it. It seems that ‘down’ (EXT6) and ‘f1’ (EXT7) are registering high when they should be low.
Is there any known issues reading certain pins or something?

# Welcome to Python on Pokitto!
from umachine import *
import upygame as upg
import umachine as pok
import gfx

text = gfx.text()

# Setup the screen.
screen = upg.display.set_mode()

pin1 = Pin( Pin.EXT0, Pin.IN )   # not connected
pin2 = Pin( Pin.EXT2, Pin.IN )   # RIGHT
pin3 = Pin( Pin.EXT4, Pin.IN )   # LEFT
pin4 = Pin( Pin.EXT6, Pin.IN )   # DOWN
pin5 = Pin( Pin.EXT8, Pin.IN )   # UP

pin7 =  Pin( Pin.EXT1, Pin.IN )  # Fire 1
pin9 =  Pin( Pin.EXT5, Pin.OUT ) # 3v
pin10 = Pin( Pin.EXT7, Pin.IN )  # Fire 2

_up = 0
_down = 0
_left = 0
_right = 0
_f1 = 0
_f2 = 0

pin9.on() # power

def readPad():
	global _up
	global _down
	global _left
	global _right
	global _f1
	global _f2

	_up = pin5.value()
	_down = pin4.value()
	_left = pin3.value()
	_right = pin2.value()
	_f1 = pin10.value()
	_f2 = pin7.value()


while True:

	readPad()
	
	text.draw(screen,0,18,_up)
	text.draw(screen,0,24,_down)
	text.draw(screen,0,30,_left)
	text.draw(screen,0,36,_right)
	text.draw(screen,0,44,_f1)
	text.draw(screen,0,50,_f2)

	upg.display.flip()

#75

I do not know any that kind of issues. In PokitTron I was able to read both directions and buttons of the Joyhat correctly, I think.

Edit: In the end I used only the joystick (analog).


#76

Does the same thing happen if you use the equivalent C++ code?

If no then it’s probably a Python problem.
If yes then it’s probably something else.


#77

I haven’t tried yet, but the first thing I would do is make sure the pins are pulled low, but that isn’t (yet?) an option in python, I assume all of the pins internal pullup/down are currently left in whatever state they are left in by pokitto setup.


#78

Right, I have not implemented that in Python.


#79

It might be a pokittolib thing perhaps? I’ve tried setting all pins (EXT0 - EXT17) to DigitalIn and PullDown (in C++) and EXT6(uart rxd) and EXT7(uart txd) both remain high unless grounded externally.


#80

…yet…

When I try to use time_us() I get an error: AttributeError: 'module' object has no attribute 'time_us'

I REALLY need a way to get any kind of time count. The framerate isn’t very accurate as I get different speeds on my PC, the emulator and the real hardware.

I am trying to implement a way of counting down seconds for a game.