Raspberry Pi sending same data? - python

So I am using Pygame to create a display for an quadrature encoder counter. I am using EzText to prompt a user input on the display where I can change the maximum count and send updated value via UART to the microcontroller that is in charge of doing the actual counting. Here is my code (sorry for the length, I marked the part that deals with the user input towards the bottom):
import sys, serial, string, pygame, eztext
import pygame.locals as GAME_GLOBALS
import pygame.event as GAME_EVENTS
windowWidth = 1680
windowHeight = 1050
maxCount New = 32767
posDataStr = " "
rect1 = (1000,350,290,75)
rect2 = (1000,555,290,75)
black = (0,0,0)
white = (248,248,255_
pygame.init()
infoObject = pygame.display.Info()
surface = pygame.display.set_mode((windowWidth,windowHeight), pygame.FULLSCREEN)
background = pygame.image.load("/home/pi/MyProjects/background.png")
myFont = pygame.font.SysFont("monospace",96,1)
surface.blit(background, (0,0))
pygame.mouse.set_visible(0) #hide mouse pointer
def quitGame():
pygame.quit()
sys.exit()
DEVICE = "/dev/ttyAMA0"
ser = serial.Serial(DEVICE, 19200)
#draw Max Count rectangles
pygame.draw.rect(surface, (black), (995,550,300,85))
pygame.draw.rect(surface, (white), (1000,555,290,75))
# draw current count background (black) rectangle (since it doesn't need to update)
pygame.draw.rect(surface, (black), (995,345,300,85))
#draw maxCountNew as text
maxCountText = myFont.render(str(maxCountNew), 1, (black))
surface.blit(maxCountText, (1000,545))
pygame.display.update()
while True:
posData = [0,0,0,0,0,0,0]
i = ser.read()
if i == '*':
for x in range (0,6):
posData[x] = ser.read()
if posData[x] == ',' or posData[x] == '\00'
del posData[x:]
posDataStr = ''.join(posData)
break
#draw posDataStr rectangles
pygame.draw.rect(surface, (white), (1000,350,290,75))
#draw currentCountStr as text
currentCountText = myFont.render(posDataStr,1,(black))
surface.blit(currentCountText, (1000,340))
for event in GAME_EVENTS.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
quitGame()
###################################################################################################
#THIS IS THE PROBLEMATIC SECTION (I think)
if event.key == pygame.K_r:
txtbx = eztext.Input(maxlength=5,color=black,prompt='Enter New Resolution: ')
while True:
events = pygame.event.get()
#blit txtbx on the screen
txtbx.draw(surface)
#update txtbx
txtbx.update(events)
#refresh the display
pygame.display.flip()
if event.key == pygame.K_SPACE:
break
if len(txtbx.value) > 4: #once 5 digits are entered
break
newMax = txtbx.value
#write new position to MCU
ser.write(newMax.encode())
print newMax.encode() //for diagnostic purposes
#max count is resolution - 1
maxCountNewInt = int(newMax) - 1
#convert back to a string
maxCountNew = str(maxCountNewInt)
#refresh the display
surface.blit(background, (0,0))
pygame.draw.rect(surface,(white),(1000,555,290,75))
maxCountText = myFont.render(maxCountNew, 1, (black)) #display new max count txt
surface.blit(maxCountText, (1000,545))
pygame.display.update()
pygame.display.update(rect1)
pygame.display.update(rect2)
When I enter a value using the EzText prompt, the value entered is saved correctly into the newMax variable. The first time I send the data to my microcontroller, I get the correct value. On subsequent inputs on the RasPi, the newMax variable is adjusted correctly but the same value as the first time is sent to the microcontroller. Am I using ser.write() incorrectly?

Can you not just do txtbx.value = ""?

Related

Disable Pygame MOUSEBUTTONDOWN/UP update on a given area/image after it's clicked once

I am new to python and Pygame. I am trying to make a Schulte table game.
Here's what the game is doing:
I have a 5 * 5 grid of total 25 pictures of numbers from 1-25.
(5*5 Schulte grid)
The number position is displayed in random order.
When you tap the correct number's picture, the number changes color. When you click on the wrong number, a sound is played to indicate the wrong click, and the number does not change color.
(Image changing colors or mouse click)
There's a start button and the restart button.
And finally, it displays the total elapsed time it took you to click all the numbers in order.
The program works as intended. Once a button is clicked, the colored number image is updated and a counter for each click is updated. But the problem is, if I click again on an already clicked number image, it keeps updating the counter.
For example, picture 1 is clicked, it turns red and now the click counter is 1. Then if I click again on the same picture 1, the program keep updating the counter. This way, if the counter reaches 25 even though I have not clicked all of the number pictures from 1-25 in order, the game will be over. I have tried to use pygame.event.set_allowed(pygame.MOUSEBUTTONDOWN), but it does not work(perhaps I don't know where in the loop to use it).
I am not sure where and how to exactly include this logic that the Mousebutton click will not update after a single click on the same picture. Please refer to the code below. Any help/tips is greatly appreciated. Thanks!
import pygame # import pygame library
import sys # import sys library
import random # import random library
import numpy as np # import numpy library
import itertools # Import the itertools library
import time # import time library
# Initialize settings
pygame.init() # Initialize pygame
size = width, height = 240, 320 # set the window size
screen = pygame.display.set_mode(size) # display the window
pygame.display.set_caption("Schulte Grid") # Give the window a name
# Image preparation
Xpts = [0, 48, 96, 144, 192]
Ypts = [0, 48, 96, 144, 192]
map = np.array(list(itertools.product(Xpts, Ypts))) # 25 picture coordinates
# load sound
wavFileName = 'sounds/fire.wav'
sndTrack = pygame.mixer.music.load(wavFileName)
# Timer text preparation
myfont = pygame.font.SysFont('Comic Sans MS', 60)
GREEN = (0, 255, 0)
BLUE = (0, 0, 128)
def ready():
global list1
list1 = [[i] for i in range(25)]
random.shuffle(list1)
# start interface
def start(start_page):
while start_page:
for event in pygame.event.get(): # Traverse all events
if event.type == pygame.QUIT: # if click to close the window, exit
sys.exit() # exit
screen.blit(pygame.image.load(
"pic/start-0.png"), (30, 190)) # show start screen
global t_x, t_y
t_x, t_y = pygame.mouse.get_pos() # Get the position of the mouse
if 30 <= t_x <= 200 and 190 <= t_y <= 250: # 18*50 #Mouse over the picture
screen.blit(pygame.image.load("pic/start-1.png"),
(30, 190)) # Get the mouse position and change color when moving to a certain position
if event.type == pygame.MOUSEBUTTONDOWN and 30 <= t_x <= 200 and 190 <= t_y <= 250:
start_page = False # start page
game_page = True # game page
global time_start # Define the global variable to start timing
time_start = time.time() # timing
pygame.display.flip() # update all display
# game interface
def gamepage(game_page):
# A variable is added here to make sure to start with the smallest number.
zero = 0
waiting_for_sleep_to_over = False
# The status of the question interface, it is guaranteed that only one question will be generated.
pic_zero = 1
while game_page:
while pic_zero:
for i in range(25): # must be 25 here
screen.blit(pygame.image.load(
"pic/pic" + str(*list1[i - 1]) + ".png"), map[i])
pic_zero = 0
for event in pygame.event.get(): # Traverse all events
if event.type == pygame.QUIT: # if click to close the window, exit
sys.exit()
for i in range(25):
# Determine the mouse position and whether it is pressed down. :
if event.type == pygame.MOUSEBUTTONDOWN and map[i][0] <= event.pos[0] <= map[i][0] + 48 and map[i][1] <= event.pos[1] <= map[i][1] + 48:
# print(i)
if int(*list1[i-1]) <= zero:
screen.blit(pygame.image.load(
"pic/qic" + str(*list1[i-1]) + ".png"), map[i]) # Display the color map
# waiting_for_sleep_to_over = True
zero = zero + 1
# if event.type == pygame.MOUSEBUTTONDOWN and map[i][0] <= event.pos[0] <= map[i][0] + 48 and map[i][1] <= event.pos[1] <= map[i][1] + 48:
# waiting_for_sleep_to_over = FALSE
# pygame.event.set_blocked(pygame.MOUSEBUTTONDOWN)
# time.sleep(0.5)
# zero = zero
# pygame.event.clear()
# pygame.event.set_allowed(pygame.MOUSEBUTTONDOWN)
print(zero)
if zero == 25:
time_end = time.time() # end timing
time_c = round(
time_end - time_start, 2) # time spent running
print('time cost:', int(time_c), 's')
textImage = myfont.render(
str(time_c) + 's', True, GREEN, BLUE)
screen.blit(textImage, (30, 250))
# screen.blit(pygame.image.load("pic/start-0.png"), (30, 210))
if event.type == pygame.MOUSEBUTTONDOWN and 30 <= t_x <= 210 and 200 <= t_y <= 250:
start_page = True
game_page = False
pygame.display.flip() # update all display
else:
pygame.mixer.music.play() # play music on error
pygame.display.flip() # update all display
# main loop
start_page = True
game_page = True
while True:
ready()
start(start_page)
gamepage(game_page)
The line if int(*list1[i-1]) <= zero: should be if int(*list1[i-1]) == zero:.

Is there a way to get pygame to detect what color my cursor is on

I'm trying to make a game where it spawns another circle every time you click on a circle. And the error i'm getting is "TypeError: 'bool' object is not callable". I'm looking for a solution that doesn't completly change the code since i'm new and want to understand the code myself. But at this point i'll take any help.
import pygame
import random
import time
from pygame.math import Vector2
# Define some colors
BLACK = (0, 0, 0)
WHITE = (247, 247, 247)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
YELLOW = (225,225,0)
tuple1 = (247, 247, 247, 255)
# Setup
pygame.init()
# Set the width and height of the screen [width,height]
surface = pygame.display.set_mode( (2560, 1440) )
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# Hide the mouse cursor
pygame.mouse.set_visible(0)
# Speed in pixels per frame
x_speed = 0
y_speed = 0
# Current position
cursor = pygame.image.load('cursor.png').convert_alpha()
pygame.image.load("pattern.jpg")
background_image = pygame.image.load("pattern.jpg").convert()
circposy = 770
circposx = 1280
# -------- Main Program Loop -----------
while done ==False:
# --- Event Processing
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.MOUSEBUTTONDOWN:
done = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Drawing Code
surface.fill(WHITE)
# First, clear the screen to WHITE. Don't put other drawing commands
# above this, or they will be erased with this command.\
player_position = pygame.mouse.get_pos()
a = 0
b = 1
p=player_position[a]
o=player_position[b]
player_position = (p,o)
pygame.draw.circle(surface,RED,[circposx,circposy], 40)
tuple2 = surface.get_at(pygame.mouse.get_pos())
print (tuple2)
q = p - 2545
w = o - 2545
surface.blit( cursor, (q, w) )
a=0
result = tuple(map(int, tuple2)) > tuple1
print (result)
while event.type == pygame.MOUSEBUTTONDOWN:
done = True
if result == True():
a+1
surface.fill(WHITE)
pygame.draw.circle(surface,RED,[circposx + randint, circposy+randint],40)
print (a)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Limit frames per second
clock.tick(144)
# Close the window and quit.
pygame.quit()
cursor.png
The short answer is that the code is trying to call True(), which isn't a function.
while event.type == pygame.MOUSEBUTTONDOWN:
done = True
if result == True(): # <<-- HERE
a+1
surface.fill(WHITE)
pygame.draw.circle(surface,RED,[circposx + randint, circposy+randint],40)
Simply change this to True.
But you will also need to define what randint is a few lines lower. Did you mean random.randint( 0, 500 ) or suchlike? And fixing this leads to another error, because the surrounding loop to this code, is an infinite loop:
while event.type == pygame.MOUSEBUTTONDOWN: # <<-- HERE
done = True
if result == True:
a+1
surface.fill(WHITE)
rand_x = random.randint( 0, 500 )
rand_y = random.randint( 0, 500 )
pygame.draw.circle(surface,RED,[circposx + rand_x, circposy+rand_y],40)
Because there is no way event.type can ever change inside that loop. This should probably read:
if event.type == pygame.MOUSEBUTTONDOWN:
If I may make some suggestions:
Put all your event handling to a single place.
There's some doubling-up of event handling, and it would have prevented that infinite loop.
Move your screen dimensions into variables
SCREEN_WIDTH = 2560
SCREEN_HEIGHT = 1440
Instead of having constant numbers through the code (e.g.: 2545) make these functions of the screen size.
SCREEN_MARGIN = SCREEN_WIDTH - round( SCREEN_WIDTH * 0.10 )
q = p - SCREEN_MARGIN
If you want to detect what color your cursor is on, you can use pyautogui. Make sure you have pyautogui installed. type pip install pyautogui. If it doesn't install successfully, you already have it installed.
# Import everything
import pygame
import pyautogui
from pyautogui import *
# Initialize
pygame.init()
# Get mouse position
mouse_pos = pygame.mouse.get_pos()
x = mouse_pos[0]
y = mouse_pos[1]
# Get Color
r = pyautogui.pixel(x,y)[0]
g = pyautogui.pixel(x,y)[1]
b = pyautogui.pixel(x,y)[2]
color = [r,g,b]
Hopefully, you found this helpful!

How to Interact with an item of a List in Pygame?

i Started creating a game and i stumbled into a little problem:
*When pressing "SPACE Bar" Red Squares keep Spawning randomly on Display
Question
How can i make the Red Squares into obstacles?
im a total begginer and im sorry for asking such a simple question.. :/
The Code might give you an idea:
import pygame, sys
from random import randint
from pygame.locals import*
"List the Stores the Squares"
red_square_list = []
gameDisplay_width = 800
gameDisplay_height = 600
pygame.init()
gameDisplay = pygame.display.set_mode((gameDisplay_width, gameDisplay_height))
pygame.display.set_caption("Square-it")
clock = pygame.time.Clock()
red_color = pygame.Color("red")
"White Square"
white_x = 400
white_y = 300
white_width = 10
white_height = 10
white_color = pygame.Color("white")
white = pygame.Rect(white_x, white_y, white_width, white_height)
"Red Squares"
def create_red_square(x, y):
red_width = 10
red_height = 10
red = pygame.Rect(x, y, red_width, red_height)
return red
while True:
clock.tick(60)
gameDisplay.fill((0, 20, 5))
gameDisplay.fill(white_color, white)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
for each in red_square_list:
gameDisplay.fill(red_color, each)
pygame.display.update()
'''White Square Movement'''
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
white.left = white.left - 4
if keys[K_RIGHT]:
white.right = white.right + 4
if keys[K_UP]:
white.top = white.top - 4
if keys[K_DOWN]:
white.bottom = white.bottom + 4
"when Space key Pressed, Spawns red Squares"
if keys[K_SPACE]:
x = randint(0, gameDisplay_width)
y = randint(0, gameDisplay_height)
red_square_list.append(create_red_square(x, y))
With your current system, as long as Space is being held down, a red square will be added to the list. This means that a square will be placed every FRAME the button is being pressed. Too much! What you want to do is add the following into your event loop. This will activate ON the frame that you press the key, not any more than that.
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
x = randint(0, gameDisplay_width)
y = randint(0, gameDisplay_height)
red_square_list.append(create_red_square(x, y))

Pygame not responding to variable updates

I'm trying to build a program that will change each individual pixel within a Pygame surface to a random colour.
For a fixed and constant surface size (eg. 1300 x 700) this works and the whole surface is filled with random colours, however I'm trying to resize the surface with the pygame.RESIZABLE feature of Pygame on the fly (by updating the computed X and Y values that the program works from), every time the surface is resized, however, the Pygame surface only outputs randomly coloured pixels for pixels within the programs initial surface width and height (in this case 1300 x 700) and the rest of the surface is left black (the defult background colour I set), even though when I print the variables that respond to the screen height and width (and are being used to iterate through all the pixel) to the program log, they update as expected.
I don't understand how the surface is not responding to thees updated variables and I don't know how to fix this issue.
Any help is much appreciated and any questions about my code are welcome, thanks!
import pygame
import random
pygame.init() #initiates pygame
Comp_X = 1300
Comp_Y = 700
Window = pygame.display.set_mode((Comp_X, Comp_Y), pygame.RESIZABLE) #defines the window size (the varible doesnt have to be called window)
pygame.display.set_caption("Random Colours") #sets the title of the window
clock = pygame.time.Clock() #sets the refresh rate of the program
def GameLoop():
global Comp_X #computed pixles for the X axis
global Comp_Y #computed pixles for the Y axis
Comp_Tot = Comp_X * Comp_Y #total pixles on the screen
print("initial computed total pixles = " + str(Comp_Tot))
#setting x and y position
x = 0
y = 0
GameExit = False #sets the defult value of this varible to true
while not GameExit: #this is effectivly a "while true" loop, unless the varible "crashed" is set to false
for event in pygame.event.get(): #this for loop will listen for events
print(event.type)
print("X = " + str(Comp_X))
print("Y = " + str(Comp_Y))
if event.type == pygame.QUIT: # this if statement checks to see if the X in the top right of the window was pressed
GameExit = True # this will break the while loop if the condition is met
print("X = " + str(Comp_X))
print("Y = " + str(Comp_Y))
if event.type == 16: #event type 16 is the window resizing event
Comp_X = event.dict['size'][0]
Comp_Y = event.dict['size'][1]
Comp_Tot = Comp_X * Comp_Y
print("current computed total pixles = " + str(Comp_Tot))
#Creating the colours
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
for pixle in range (0, Comp_Tot):
if x == Comp_X:
print("Computed X = " + str(Comp_X))
print("Computed Y = " + str(Comp_Y))
x = 0
y += 1
pygame.draw.rect(Window, (random.randint(0,255), random.randint(0,255), random.randint(0,255)), [x, y, 2, 2])# draws a red square
x += 1
#Drawing the frame
pygame.display.update() #This updates the frame
clock.tick(60) # this defines the FPS
GameLoop()
pygame.quit() # this will close the window if the "while GameLoop" loop stops running
quit()
Using defult height and width of 1300 x 700
Resizing surface to 1457 x 992 - not all of the surface is filled!
There are actually two problems with the code that cause the error. The first is not having the
Window = pygame.display.set_mode((Comp_X, Comp_Y), pygame.RESIZABLE)
line inside of the if event.type == 16: as already mentioned.
The other problem is very minor but causes it to not work properly if resized after filling the screen once already and that is that you are never resetting the values of x or y back to 0 after you fill the screen.
Fixed section of code:
if event.type == pygame.VIDEORESIZE:
Comp_X = event.w
Comp_Y = event.h
Comp_Tot = Comp_X * Comp_Y
print("current computed total pixles = " + str(Comp_Tot))
Window = pygame.display.set_mode((Comp_X, Comp_Y), pygame.RESIZABLE)
#Creating the colours
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
for pixle in range (0, Comp_Tot):
if x == Comp_X:
#print("Computed X = " + str(Comp_X))
#print("Computed Y = " + str(Comp_Y))
x = 0
y += 1
pygame.draw.rect(Window, (random.randint(0,255), random.randint(0,255), random.randint(0,255)), [x, y, 2, 2])# draws a red square
x += 1
x = 0
y = 0
I also changed event.type == 16 to event.type == pygame.VIDEORESIZEas it's more readable.
When the window resize event fires, you need to call pygame.display.set_mode((w, h)) again to allocate a new surface of that size. Otherwise you're still writing to the original 1300x700 Surface instance.

How to display player's score on Pygame?

I'm a new programmer working on a memory game for my computer science summative.The game goes like this: the computer displays random boxes at random positions and then the user has to guess where the boxes are and click on it.
I'm basically done, except right now I'm trying to create 5 different levels that range in level of difficulty. eg level 1 will display 2 boxes and level 2 will display 5, etc. And then if the user gets through all levels they can play again. I know its a lot but I really want to get an A on this.
But right now I'm stuck because it doesn't really work until I try to close the window, and even then it only goes halfway. Any help would be appreciated.
import pygame , sys
import random
import time
size=[500,500]
pygame.init()
screen=pygame.display.set_mode(size)
# Colours
LIME = (0,255,0)
RED = (255, 0, 0)
BLACK = (0,0,0)
PINK = (255,102,178)
SALMON = (255,192,203)
WHITE = (255,255,255)
LIGHT_PINK = (255, 181, 197)
SKY_BLUE = (176, 226, 255)
screen.fill(BLACK)
# Width and Height of game box
width=50
height=50
# Margin between each cell
margin = 5
rows = 20
columns = 20
# Set title of screen
pygame.display.set_caption("Spatial Recall")
# Used to manage how fast the screen updates
clock=pygame.time.Clock()
coord=[]
# Create a 2 dimensional array. A two dimesional
# array is simply a list of lists.
def resetGrid():
grid = []
for row in range(rows):
# Add an empty array that will hold each cell
# in this row
grid.append([])
for column in range(columns):
grid[row].append(0) # Append a cell
return grid
def displayAllPink(pygame):
for row in range(rows):
for column in range(columns):
color = LIGHT_PINK
pygame.draw.rect(screen,color,[(margin+width)*column + margin,(margin+height)*row+margin,width,height])
pygame.display.flip()
def displayOtherColor(pygame,grid):
coord = []
for i in range(random.randint(2,5)):
x = random.randint(2, rows-1)
y = random.randint(2, columns-1)
color = LIME
pygame.draw.rect(screen,color,[(margin+width)*y + margin,(margin+height)*x+margin,width,height])
coord.append((x,y))
grid[x][y] = 1
pygame.display.flip()
time.sleep(1)
return coord
def runGame(gameCount,coord,pygame,grid):
pygame.event.clear()
pygame.display.set_caption("Spatial Recall: Level "+ str(gameCount))
pygame.time.set_timer(pygame.USEREVENT,1000)
time = 0
#clock.tick(
# -------- Main Program Loop -----------
#Loop until the user clicks the close button.
done = False
while done==False:
event = pygame.event.wait() # User did something
if event.type == pygame.QUIT: # If user clicked close
done=True # Flag that we are done so we exit this loop
pygame.event.clear()
print "Game ",gameCount, "ends"
elif event.type == pygame.USEREVENT:
time = time + 1
pygame.display.set_caption("Spatial Recall: Level "+ str(gameCount) + " Time: "+ str(time))
if time == 100:
done = True
pygame.display.set_caption("Time out, moving to next level")
pygame.event.clear()
return False
elif event.type == pygame.MOUSEBUTTONDOWN:
# User clicks the mouse. Get the position
pos = pygame.mouse.get_pos()
# Change the x/y screen coordinates to grid coordinates
column=pos[0] // (width+margin)
row=pos[1] // (height+margin)
if (row,column) in coord:
print coord
coord.remove((row,column))
print coord
color = LIME
pygame.draw.rect(screen,color,[(margin+width)*column + margin,(margin+height)*row+margin,width,height])
if coord == []:
done=True
pygame.display.set_caption("Time out, moving to next level")
pygame.event.clear()
return True
else:
color = RED
pygame.draw.rect(screen,color,[(margin+width)*column + margin,(margin+height)*row+margin,width,height])
pygame.display.flip()
def startTheGame(gameCount):
grid = resetGrid()
displayAllPink(pygame)
coord = displayOtherColor(pygame,grid)
displayAllPink(pygame)
runGame(gameCount,coord,pygame,grid)
for i in range(2):
startTheGame(i+1)
pygame.quit ()
You may want to use the pygame.font module. http://pygame.org/docs/ref/font.html
First, load a font, either from a file or from one of the system font functions.
Call YourFontObject.render(your_text_string). That'll return a Surface that contains the string rendered in the given font. Note, you can't use newline (\n) characters! You'll have to do the spacing yourself.
Blit this Surface onto the screen after everything else so nothing will obscure it.
Also, you don't need the pygame parameter in your functions.
Hope this helps.

Categories