User input recorded from multiple text boxes and put into MySQL - mysql

I'm running into a brick wall and have spent multiple hours trying to research how to do this and I'm at the point I'm not sure if I'm asking the right question.
I have a page for recording user input in multiple boxes. I've made a separate file for my text box function which feeds into the main page. I want to be able to click next and record all the use input from the text boxes into a MySQL database.
The problem I'm running into seems to be that the main page doesn't know there's user input just that there is a text box, so I can't record anything, while if I change the text input file it defeats the purpose of creating one so that I can use text boxes anywhere.
Main page
import pygame
import Test
import button
import sys
import mysql.connector
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Main Page")
icon = pygame.image.load('icons8-robber-32.png')
pygame.display.set_icon(icon)
colour_active = pygame.Color('orange')
colour_inactive = pygame.Color('Yellow')
font = pygame.font.Font(None, 32)
start_image = pygame.image.load('play.png').convert_alpha()
exit_image = pygame.image.load('exit.png').convert_alpha()
menu_image = pygame.image.load('menu.png').convert_alpha()
back_image = pygame.image.load('back.png').convert_alpha()
next_image = pygame.image.load('next.png').convert_alpha()
def register():
input_box1 = Test.inputBox(210, 105, 140, 32, "First Name: ")
input_box2 = Test.inputBox(210, 160, 140, 32)
input_boxes = [input_box1, input_box2]
back_button = button.Button(100, 450, back_image, 0.2)
next_button = button.Button(450, 450, next_image, 0.2)
done = False
while not done:
for event in pygame.event.get():
for box in input_boxes:
box.handle_event(event)
for box in input_boxes:
box.update()
screen.fill((30, 30, 30))
for box in input_boxes:
box.draw(screen)
if back_button.draw(screen):
print("no")
if next_button.draw(screen):
sys.exit()
pygame.display.update()
start_button = button.Button(100, 150, start_image, 0.2)
exit_button = button.Button(250, 150, exit_image, 0.2)
menu_button = button.Button(400, 150, menu_image, 0.2)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((150, 255, 100))
if start_button.draw(screen):
print("no")
if exit_button.draw(screen):
sys.exit()
if menu_button.draw(screen):
register()
pygame.display.update()
pygame.QUIT()
sys.exit()
Text box file
import pygame
pygame.init()
colour_active = pygame.Color('orange')
colour_inactive = pygame.Color('Yellow')
font = pygame.font.Font(None, 32)
class inputBox():
def __init__(self, x, y, w, h, text=''):
self.rect = pygame.Rect(x,y,w,h)
self.color = colour_inactive
self.text = text
self.text_surface = font.render(text, True, self.color)
self.active = False
def handle_event(self,event):
if event.type == pygame.MOUSEBUTTONDOWN:
if self.rect.collidepoint(event.pos):
self.active = not self.active
else:
self.active = False
self.color = colour_active if self.active else colour_inactive
if event.type == pygame.KEYDOWN:
if self.active:
if event.key == pygame.K_RETURN:
print(self.text)
elif event.key == pygame.K_BACKSPACE:
self.text = self.text [:-1]
else:
self.text += event.unicode
self.text_surface = font.render(self.text, True, self.color)
def update(self):
self.rect.w = max(100, self.text_surface.get_width() + 10)
def draw(self, screen):
screen.blit(self.text_surface, (self.rect.x+5, self.rect.y+5))
pygame.draw.rect(screen, self.color, self.rect, 2)

You do not need the self.text file in the main code. So instead of writing input_box1.self.text, it was just input_box1.text.

Related

why doesn't play_button.rect.collidepoint(mouse_x , mouse_y) function?

This is a typing game in Python. Click the 'Play' button and the game is supposed to start. Random letters will fall down and each letter will disappear when you strike the corresponding key. However, it failed to begin when I click on the button. I think the problem must be related to the if statements if play_button.rect.collidepoint(mouse_x , mouse_y): in method check_play_button() of game_functions.py since if the if statement is removed, the stats.game_active is changed to True. On the other hand, if the if statement is removed, then click anywhere on the screen would change the value of stats.game_active to True. I am quite puzzled about the malfunction of the if statement. Please shed light on it.
Here are my codes( a bit long but a challenge:P):
alphabet_zoo.py
import pygame
import time
from pygame.locals import *
from settings import Settings
import game_functions as gf
from game_stats import GameStats
from button import Button
def run_game():
pygame.init()
az_settings =Settings()
screen = pygame.display.set_mode((0,0), RESIZABLE)
pygame.display.set_caption("Alphabet Zoo")
play_button = Button(screen, "Play")
stats = GameStats(az_settings)
letters = pygame.sprite.Group()
start = time.time()
sleepTime = 3
while True:
now = time.time()
gf.check_events(letters, stats, play_button)
if stats.game_active:
gf.update_screen(az_settings, stats, screen, letters, play_button)
if now - start >sleepTime:
gf.letter_generator(az_settings ,screen, letters)
start = now
else:
gf.update_screen(az_settings, stats, screen, letters, play_button)
run_game()
button.py
import pygame.font
class Button():
def __init__(self, screen, msg):
self.screen = screen
self.screen_rect = screen.get_rect()
self.width, self.height = 200, 50
self.button_color = (0, 0, 255)
self.text_color = (255, 255, 255)
self.font = pygame.font.SysFont(None, 48)
self.rect = pygame.Rect(0, 0, self.width, self.height)
self.rect.center = self.screen_rect.center
self.prep_msg(msg)
def prep_msg(self, msg):
self.msg_image = self.font.render(msg, True, self.text_color,
self.button_color)
self.msg_image_rect = self.msg_image.get_rect()
self.msg_image_rect.center = self.rect.center
def draw_button(self):
self.screen.fill(self.button_color, self.rect)
self.screen.blit(self.msg_image, self.msg_image_rect)
settings.py
class Settings():
def __init__(self):
self.bg_color = (0, 0, 0)
self.letter_speed_factor = 10
self.lives_limit = 10
game_stats.py
class GameStats():
def __init__(self, az_settings):
self.az_settings = az_settings
self.reset_stats()
self.game_active = False
def reset_stats(self):
self.lives_left = self.az_settings.lives_limit
letter.py
import pygame
import random
from pygame.sprite import Sprite
class Letter(Sprite):
def __init__(self, az_settings, screen):
super().__init__()
self.screen = screen
self.az_settings = az_settings
a = random.randint(97, 122)
c = chr(a)
self.image = pygame.image.load('images/' + c.upper() + '.png')
self.ascii = a
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
self.rect.centerx = random.randint(0, self.screen_rect.right)
self.rect.top = self.screen_rect.top
self.center = float(self.rect.centerx)
def update(self):
if self.rect.bottom < self.screen_rect.bottom:
self.rect.centery += self.az_settings.letter_speed_factor
game_functions.py
import sys
import pygame
from letter import Letter
def letter_generator(az_settings, screen, letters):
new_letter = Letter(az_settings, screen)
letters.add(new_letter)
def check_events(letters, stats, play_button):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
check_play_button(stats, play_button, mouse_x, mouse_y)
print(stats.game_active) # for test
elif event.type == pygame.KEYDOWN:
for ltr in letters:
if ltr.ascii == event.key:
letters.remove(ltr)
def check_play_button(stats, play_button, mouse_x, mouse_y):
if play_button.rect.collidepoint(mouse_x , mouse_y):
stats.game_active = True
def letter_fallen(stats):
if stats.lives_left > 0:
stats.lives_left -= 1
else:
stats.game_active = False
def check_letter_bottom(screen, letters, stats):
screen_rect = screen.get_rect()
for ltr in letters.sprites():
if ltr.rect.bottom > screen_rect.bottom: # there might be some problems
ltr.rect.bottom = screen_rect.bottom
letter_fallen(stats)
def update_screen(az_settings, stats, screen, letters, play_button):
screen.fill(az_settings.bg_color)
check_letter_bottom(screen, letters, stats)
letters.draw(screen)
letters.update()
if not stats.game_active:
play_button.draw_button()
pygame.display.flip()
Obviously I cannot test this but I think your problem is that you are not assigning position to your play_button.rect. By default, rect's positions values are (0, 0). I had the same problem a little while ago, so you are read some more details in answer to this question. One way to fix the problem - in button class make a getRect method:
class Button:
def getRect(self):
return pygame.Rect(x, y, width, height) # Since you will
#be using this rect for collision, enter the arguments accordingly
Then,
if play_button.getRect().collidepoint(mouse_x , mouse_y):
Other option is to directly assign position to the button rect but I prefer the first solution, its just a personal preference:
class Button():
def __init__(self, screen, msg):
self.rect.topleft = #your button position

What's the most convenient way to add buttons in pygame with text

Following up my last question, for my school assignment, I am developing a game. My concept includes the uses of buttons in this game so I was wondering what is the most convenient way to add buttons in pygame? Also, if you have suggestions for resources which can help me in cases like this, please let me know. Thanks
Here's my Code:
# Program: Import Library, Pygame, for initialization of this program
import pygame
# Initialize the game engine
pygame.init()
# Define Colours
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
BLUE = ( 0, 0, 255)
display_width = 1080
display_height = 720
size = (display_width, display_height)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("MiniConomy Trivia, for Adults")
# Button Program
class Button:
def __init__(self, size, text, pos, bgColor=(0, 255, 0), textColor=(0, 0, 0)):
self.pos = pos
self.size = size
self.text = text
self.font = pygame.font.Font(pygame.font.get_default_font(), size[1])
self.textSurf = self.font.render(f"{text}", True, textColor)
self.button = pygame.Surface((size[0], size[1])).convert()
self.button.fill(bgColor)
def render(self, window):
window.blit(self.button, (self.pos[0], self.pos[1]))
window.blit(self.textSurf, (self.pos[0]+1, self.pos[1]+5))
def clicked(self, events):
mousePos = pygame.mouse.get_pos()# get the mouse position
for event in events:
if self.button.get_rect(topleft=self.pos).collidepoint(mousePos[0], mousePos[1]):
if event.type == pygame.MOUSEBUTTONDOWN:
return True
return False
# Setting a Title Screen
def text_objects(text, font):
textSurface = font.render(text, True, BLACK)
return textSurface, textSurface.get_rect()
largeText = pygame.font.Font('freesansbold.ttf', 90)
# Creating a Title Screen
TextSurf, TextRect = text_objects("MiniConomy", largeText)
TextRect.center = (540,150)
# Play Button
button = Button([280,50], "Let's Begin", [380,302])
button2 = Button([280, 50], "Second Button", [380, 302])
#Loop until the user clicks the close button
done = False
# -------- Main Program Loop -----------
while done == False:
events = pygame.event.get()
for event in events: # User did something
if event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
# Set the screen background
screen.fill(BLUE)
screen.blit(TextSurf, TextRect)
while True:
# Button 1 Control
button.render(screen)
if button.clicked(events):
print("Game Logic goes here")
pygame.display.flip()
button2.render(screen)
if button2.clicked(events):
print("Game Logic Here")
pygame.display.flip()
pygame.quit()
quit()
The most convenient way to add a button would be to make a button class. I know you are not using OOP with your code, but taking a class approach would allow you to make multiple buttons with a single class acting as a template for each button.
Lets start by making a class.
Fist we will make an init function to initialise all the attribute variables of our button.
class Button:
def __init__(self, size, text, pos):
self.pos = pos
self.size = size
self.text = text
self.font = pygame.font.Font(pygame.font.get_default_font(), size/2)
self.button = pygame.Surface(size[0], size[1]).convert()
Then we will add methods to our class to give our class some behaviour. We want to render our button, then we want to be able to click our button.
def render(self, window):
window.blit(self.button, (self.pos[0], self.pos[1]))
window.blit(self.textSurf, (self.pos[0]+1, self.pos[1]+5))
def clicked(self, events):
mousePos = pygame.mouse.get_pos()# get the mouse position
for event in events:
if self.button.get_rect(topleft=self.pos).collidepoint(mousePos[0], mousePos[1]):
if event.type == pygame.MOUSEBUTTONDOWN:
return True
return False
With this implemented, your code becomes:
# Program: Import Library, Pygame, for initialization of this program
import pygame
# Initialize the game engine
pygame.init()
# Define Colours
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
BLUE = ( 0, 0, 255)
display_width = 1080
display_height = 720
size = (display_width, display_height)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("MiniConomy Trivia, for Adults")
class Button:
def __init__(self, size, text, pos, bgColor=(255, 255, 255), textColor=(0, 0, 0)):
self.pos = pos
self.size = size
self.text = text
self.font = pygame.font.Font(pygame.font.get_default_font(), size[1])
self.textSurf = self.font.render(f"{text}", True, textColor)
self.button = pygame.Surface((size[0], size[1])).convert()
self.button.fill(bgColor)
def render(self, window):
window.blit(self.button, (self.pos[0], self.pos[1]))
window.blit(self.textSurf, (self.pos[0]+1, self.pos[1]+5))
def clicked(self, events):
mousePos = pygame.mouse.get_pos()# get the mouse position
for event in events:
if self.button.get_rect(topleft=self.pos).collidepoint(mousePos[0], mousePos[1]):
if event.type == pygame.MOUSEBUTTONDOWN:
return True
return False
# Setting a Title Screen
def text_objects(text, font):
textSurface = font.render(text, True, BLACK)
return textSurface, textSurface.get_rect()
largeText = pygame.font.Font('freesansbold.ttf', 100)
# Creating a Title Screen
TextSurf, TextRect = text_objects("MiniConomy", largeText)
TextRect.center = (540,150)
# Play Button
button = Button([250, 50], "A button", [50, 50])
#Loop until the user clicks the close button
done = False
# -------- Main Program Loop -----------
while done == False:
events = pygame.event.get()
for event in events: # User did something
if event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
# Set the screen background
screen.fill(BLUE)
screen.blit(TextSurf, TextRect)
button.render(screen)
if button.clicked(events):
print("Your game start logic goes here")
pygame.display.flip()
Now obviously, there is a lot of potential to add extra features to our button class, like color changing when mouse is over the button and things like that. Just to show you the benefits of using a class. Now if you want another button, you can simply make another instance of button class
anotherButton = Button([300, 500], "Second Button", [500, 500])
and in main loop call:
while True:
anotherButton.render(screen)
anotherButton.clicked(events)
And BOOM, you have a second button. Hope i could help.
Edit: Answer to the difficulties you were having. Couple of things.
First, Both buttons are in the same position. Change that.
button = Button([280,50], "Let's Begin", [380,302])
button2 = Button([280, 50], "Second Button", [380, 302])
Third argument is position and as you can see, they are the same.
Second, You already have a while True loop so there is no reason why you should add another while True loop. Just use the first while loop, that is why it is called a game loop
Third, You call pygame.display.flip() twice. This function is responsible for updating the screen every frame. Calling it twice means you are trying to update it twice every frame, which can cause unwanted problems.
while not done:
events = pygame.event.get()
for event in events: # User did something
if event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
# Set the screen background
screen.fill(BLUE)
screen.blit(TextSurf, TextRect)
# Button 1 Control
button.render(screen)
if button.clicked(events):
print("Game Logic goes here")
button2.render(screen)
if button2.clicked(events):
print("Game Logic Here")
pygame.display.flip()

TypeError: Rect argument is invalid pygame

i am new to pygame and wanted to make a game i found a playlist online at https://www.youtube.com/playlistlist=PLQVvvaa0QuDdLkP8MrOXLe_rKuf6r80KO t i followed it but i got a error like this
Traceback (most recent call last):
File "/home/pi/firstgamepyg.py", line 78, in <module>
game_loop()
File "/home/pi/firstgamepyg.py", line 65, in game_loop
things(thing_startx, thing_starty, thing_width, thing_height, black)
File "/home/pi/firstgamepyg.py", line 15, in things
pygame.draw.rect(gamedisplay, color,(thingx, thingy, thingw, thingh))
TypeError: Rect argument is invalid
this is my code
import pygame
import time
import random
pygame.init()
dw = 800
dh = 600
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
cw = 96
gamedisplay = pygame.display.set_mode((dw,dh))
cimg = pygame.image.load('/home/pi/Downloads/car.jpeg')
def things(thingx, thingy, thingw, color, thingh):
#error on next line
pygame.draw.rect(gamedisplay, color,(thingx, thingy, thingw, thingh))
def car(x,y):
gamedisplay.blit(cimg,(x,y))
def text_objects(text, font):
textsurface = font.render(text, True, red)
return textsurface, textsurface.get_rect()
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf',115)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((dw/2),(dh/2))
gamedisplay.blit(TextSurf, TextRect)
pygame.display.update()
time.sleep(2)
game_loop()
def crash():
message_display('wasted')
def game_loop():
x = (dw * 0.45)
y = (dh * 0.65)
x_change = 0
thing_startx = random.randrange(0,800)
thing_starty = -600
thing_speed = 7
thing_width = 100
thing_height = 100
pygame.display.set_caption('A bit Racey')
clock = pygame.time.Clock()
gameexit = False
while not gameexit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameexit = True
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key==pygame.K_RIGHT:
x_change = 0
x += x_change
gamedisplay.fill(white)
things(thing_startx, thing_starty, thing_width, thing_height, black)
thing_starty += thing_speed
car(x,y)
if x > dw - cw or x < 0:
crash()
gameexit = True
pygame.display.update()
clock.tick(100)
game_loop()
pygame.quit()
quit()
i was trying to make a game where you are a car and avoid blocks but i cant add the blocks because i get an error
your things function is formatted incorrectly. you have the parameter list as (thingx, thingy, thingw, color, thingh) but then you call it as (thingx, thingy, things, thingh, color). to make the errors go away all that you need to do is in the function definition switch color with thingh

Change colour of sprite rect from group

I have a group of rects, they display in a row. I want them to change their colour when they have been clicked, until they are clicked again
I have this code so far to create the sprites:
class DrawableRect(pygame.sprite.Sprite):
def __init__(self,color,width,height,value=0):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(color)
self.rect = self.image.get_rect()
self.value = value
self.x = 0
self.y = 0
def change_value(self,color,value):
self.image.fill(color)
self.value=value
def DrawRects(start_x, start_y, rect_spacing, colour_list):
current_x_pos = start_x
for rect_num in range(0,8):
rect = DrawableRect(colour_list[rect_num], boxW, boxH)
rect.rect.x = current_x_pos
rect.rect.y = start_y
current_x_pos = current_x_pos + rect.rect.width + rect_spacing
rects.add(rect)
rects.draw(screen)
The idea of the app is for each rectangle to represent a bit, and when pressed it alternates between 0 and 1, the makeup of each bit displays the decimal equivalent somewhere.
I read that groups are unordered therefore indexing wouldn't work, is that true?
Here's an example I've modified to suit your purposes. I have a bunch of sprites (coloured rectangles) in a sprite group and I change* the colour of any sprite that collides with the mouse pointer when a mouse button is pressed.
Here's the code, you're probably most interested in the change_color() method and the MOUSEBUTTONUP event handling code.
import random
import pygame
screen_width, screen_height = 640, 480
def get_random_position():
"""return a random (x,y) position in the screen"""
return (random.randint(0, screen_width - 1), #randint includes both endpoints.
random.randint(0, screen_height - 1))
color_list = ["red", "orange", "yellow", "green", "cyan", "blue", "blueviolet"]
colors = [pygame.color.Color(c) for c in color_list]
class PowerUp(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
width, height = 64, 32
self.image = pygame.Surface([width, height])
self.clicked = False # track whether we've been clicked or not
# initialise color
self.color = random.choice(colors)
self.image.fill(self.color)
# Fetch the rectangle object that has the dimensions of the image
self.rect = self.image.get_rect()
# then move to a random position
self.update()
def update(self):
#move to a random position
self.rect.center = get_random_position()
def random_color(self):
# randomise color
self.clicked = not self.clicked
if self.clicked:
color = random.choice(colors)
else:
color = self.color
self.image.fill(color)
if __name__ == "__main__":
pygame.init()
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Sprite Color Switch Demo')
clock = pygame.time.Clock() #for limiting FPS
FPS = 60
exit_demo = False
pygame.key.set_repeat(300, 200)
#create a sprite group to track the power ups.
power_ups = pygame.sprite.Group()
for _ in range(10):
power_ups.add(PowerUp()) # create a new power up and add it to the group.
# main loop
while not exit_demo:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit_demo = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
exit_demo = True
elif event.key == pygame.K_SPACE:
power_ups.update()
elif event.type == pygame.MOUSEBUTTONUP:
# check for collision
for p in power_ups:
if p.rect.collidepoint(event.pos): # maybe use event?
p.random_color()
screen.fill(pygame.Color("black")) # use black background
power_ups.draw(screen)
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
Let me know if you have any questions. Obviously this doesn't do row alignment of the sprites, I think you have a handle on that. I would suggest that you have all of your screen drawing operations in one place so your code can be clearer.
*The new colour is randomised from a short list, so there's a 14% chance it won't change from the starting colour.

Pygame making a selection like in stategy games

So I made this in order to select an area like in strategy games, however
the screen keeps blinking, is there a way to solve this?
import pygame
from pygame.locals import *
WHITE = (255,255,255)
BLUE = (0,0,255)
pygame.init()
window = pygame.display.set_mode((640, 480))
window.fill(WHITE)
pygame.display.flip()
LEFT_CLIC = 1
mouse_tracking = False
draw_area = False
while True:
for event in pygame.event.get():
if event.type == QUIT:
continuer = 0
if event.type == MOUSEBUTTONDOWN:
if event.button == LEFT_CLIC:
x_start, y_start = event.pos
x_end, y_end = event.pos
mouse_tracking = True
draw_area = True
if event.type == MOUSEMOTION and mouse_tracking:
x_end, y_end = event.pos
if event.type == MOUSEBUTTONUP:
if event.button == LEFT_CLIC:
x_end, y_end = event.pos
mouse_tracking = True
draw_area = False
if draw_area:
width = x_end-x_start
height = y_end-y_start
pygame.draw.rect(window, BLUE, (x_start, y_start, width, height))
pygame.display.flip()
window.fill(WHITE)
pygame.display.flip()
So it's pretty simple, record coordinates when there is a clic, then follow the mouse until the clic is done.
Thanks.
There should be only one pygame.display.flip() call per frame, otherwise you get this flickering, so remove one of them. Also, fill the screen before you draw the rect.
window.fill(WHITE)
if draw_area:
width = x_end-x_start
height = y_end-y_start
pygame.draw.rect(window, BLUE, (x_start, y_start, width, height))
pygame.display.flip()