What's the best way to add title to a menu screen in pygame - pygame

So, for a school assignment, I need to make a game on Adult Education and so I did but just for the basics, I cannot figure out how to add a title on my menu screen in this game. I have tried many other tutorials and some are pretty easy to understand but for some reason, it ends up not working in my program. What is the best way to add a simple title in pygame?
Heres the code(If you would like to check for any errors I have made):
# 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)
size = (1080, 720)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("MiniConomy Trivia, for Adults")
#Loop until the user clicks the close button
done = False
# -------- Main Program Loop -----------
while done == False:
for event in pygame.event.get(): # 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)
pygame.display.flip()
# 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 = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)

The code you have here is mostly syntactically correct (except for a couple of variable names which don't exist) but it isn't in the right order.
the "Creating a title screen" section should be out of the loop, the first two lines:
TextSurf, TextRect = text_objects("MiniConomy", largeText)
TextRect.center = ((display_width/2),(display_height/2))
should be placed before the game loop and then the blit function:
gameDisplay.blit(TextSurf, TextRect)
should be at the end of the game loop but instead of "gameDisplay" write "screen" instead as that is what you called your display at the start of the program.
The function "text_objects" should also go at the start of the program otherwise it cannot be called.
Here's the full modified code: https://pastebin.com/hQDbD2ya
Which produces this title screen:

Related

Trying to a get a movable image with a PNG background using pygame [duplicate]

This question already has an answer here:
How can I move the ball instead of leaving a trail all over the screen in pygame?
(1 answer)
Closed 6 months ago.
We are trying to create a program using pygame that allows preset image files to be dragged around over another PNG image as the background. Used some code from a tutorial for pygame and tweaked it to fit our specific needs. We have gotten the images to populate and are movable but only with a white background. When importing the PNG file for the background instead, the moveable image disappears behind the background. I have replace the the two filepaths with just "filepath." Still fairly new to python so sorry for ugly code.
Code:
# Import the library pygame
import pygame
from pygame.locals import *
##background
bg = pygame.image.load(filepath)
# Take colors input
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLACK = (0, 0, 0)
# Construct the GUI game
pygame.init()
# Set dimensions of game GUI
w, h = 1280, 720
screen = pygame.display.set_mode((w, h))
# Take image as input
img = pygame.image.load(filepath)
img.convert()
# Draw rectangle around the image
rect = img.get_rect()
rect.center = w//2, h//2
# Set running and moving values
running = True
moving = False
# Setting what happens when game
# is in running state
while running:
screen.blit(bg, (320,0))
for event in pygame.event.get():
# Close if the user quits the
# game
if event.type == QUIT:
running = False
# Making the image move
elif event.type == MOUSEBUTTONDOWN:
if rect.collidepoint(event.pos):
moving = True
# Set moving as False if you want
# to move the image only with the
# mouse click
# Set moving as True if you want
# to move the image without the
# mouse click
elif event.type == MOUSEBUTTONUP:
moving = False
# Make your image move continuously
elif event.type == MOUSEMOTION and moving:
rect.move_ip(event.rel)
# Set screen color and image on screen
screen.fill(WHITE)
screen.blit(img, rect)
# Construct the border to the image
pygame.draw.rect(screen, BLACK, rect, 2)
# Update the GUI pygame
pygame.display.update()
##trying to draw the background
# Quit the GUI game
pygame.quit()
I tried out your code and through a bit of experimentation, came up with some refinements that display the image in front of the background. Following is your program with a few tweaks.
# Import the library pygame
import pygame
from pygame.locals import *
##background
bg = pygame.image.load("background.png") # Just a sky blue background
bg = pygame.transform.scale(bg, (1280, 720)) # Made it fit the screen size
# Take colors input
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLACK = (0, 0, 0)
# Construct the GUI game
pygame.init()
# Set dimensions of game GUI
w, h = 1280, 720
screen = pygame.display.set_mode((w, h))
# Take image as input
img = pygame.image.load("car.png")
img.convert()
# Draw rectangle around the image
rect = img.get_rect()
rect.center = w//2, h//2
# Set running and moving values
running = True
moving = False
# Setting what happens when game
# is in running state
while running:
screen.blit(bg, (0,0)) # Start the background at the upper left
for event in pygame.event.get():
# Close if the user quits the
# game
if event.type == QUIT:
running = False
# Making the image move
elif event.type == MOUSEBUTTONDOWN:
if rect.collidepoint(event.pos):
moving = True
# Set moving as False if you want
# to move the image only with the
# mouse click
# Set moving as True if you want
# to move the image without the
# mouse click
elif event.type == MOUSEBUTTONUP:
moving = False
# Make your image move continuously
elif event.type == MOUSEMOTION and moving:
rect.move_ip(event.rel)
# Set screen color and image on screen
#screen.fill(WHITE)
screen.blit(img, rect) # Changing the indentation seems to make it visible
# Construct the border to the image
#pygame.draw.rect(screen, BLACK, rect, 2)
# Update the GUI pygame
pygame.display.update()
##trying to draw the background
# Quit the GUI game
pygame.quit()
Following are the highligts.
I utilized a "png" file I had for a sky blue background which was loaded and then transformed to fill the entire 1280 x 720 screen.
The placement of the background was set to start at the upper left; if your background image needs to be centered or oriented differently, keep that in mind.
The indentation of the load of the image to be moved (in my case a "car") was revised to be a part of the "while" loop and not a part of the "for" loop; otherwise, the image only flashes and appears during the handling of the mouse events.
After those tweaks, the image appeared and was moved around by the mouse.
The takeaway from this is that you would want your image to be handled within your drawing/blit cycle. That appears to be where you got tripped up.
Give that a try.

How do I make autonomous movement in pygame?

I'm new to pygame and I'm trying to do the simplest thing ever here really, I just want to have a circle move across the screen with no input from the user. I only seem to find advice online on how to move an object using the keys which isn't what I want I just want it to move on its own and so that the user can watch it move.
Here's what I was trying to use to do this.
Code Start Here:
import pygame module in this program
import pygame
pygame.init()
white = (255, 255, 255)
green = (0, 255, 0)
blue = (0, 0, 128)
black = (0, 0, 0)
red = (255, 0, 0)
X = 400
Y = 400
display_surface = pygame.display.set_mode((X, Y ))
pygame.display.set_caption('Drawing')
display_surface.fill(white)
x,y=[300,50]
pygame.draw.circle(display_surface,green, (x, y), 20, 0)
clock = pygame.time.Clock()
def move():
global y
y=y+1
while True :
clock.tick(30)
move()
for event in pygame.event.get() :
# if event object type is QUIT
# then quitting the pygame
# and program both.
if event.type == pygame.QUIT :
pygame.quit()
quit()
pygame.display.update()
Code End Here:
You have to redraw the scene in every frame:
import pygame
pygame.init()
white = (255, 255, 255)
green = (0, 255, 0)
blue = (0, 0, 128)
black = (0, 0, 0)
red = (255, 0, 0)
X = 400
Y = 400
display_surface = pygame.display.set_mode((X, Y))
pygame.display.set_caption('Drawing')
clock = pygame.time.Clock()
x,y=[300,50]
def move():
global y
y=y+1
# application loop
run = True
while run:
# limit the frames per second
clock.tick(30)
# event loop
for event in pygame.event.get() :
if event.type == pygame.QUIT:
run = False
# update the position of the object
move()
# clear disaply
display_surface.fill(white)
# draw scene
pygame.draw.circle(display_surface,green, (x, y), 20, 0)
# update disaply
pygame.display.update()
pygame.quit()
quit()
The typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()

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()

How to cycle 3 images on a rect button?

Just started learning Python/Pygame watching videos and reading to learn . I would like to see a example code to cycle 3 images on a rect button from a mouse press and return to first image. Really I want the pictures to be three options and return different results. So be able to cycle image be able to select option and option when triggered execute choice.
Example
import pygame
pygame.init()
screen = pygame.display.set_mode((300,200))
# three images
images = [
pygame.Surface((100,100)),
pygame.Surface((100,100)),
pygame.Surface((100,100)),
]
images[0].fill((255,0,0))
images[1].fill((0,255,0))
images[2].fill((0,0,255))
# image size and position
images_rect = images[0].get_rect()
# starting index
index = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
# check mouse position and pressed button
if event.button == 1 and images_rect.collidepoint(event.pos):
# cycle index
index = (index+1) % 3
screen.blit(images[index], images_rect)
pygame.display.flip()
pygame.quit()
Example using class - to create many buttons
import pygame
class Button(object):
def __init__(self, position, size):
self._images = [
pygame.Surface(size),
pygame.Surface(size),
pygame.Surface(size),
]
self._images[0].fill((255,0,0))
self._images[1].fill((0,255,0))
self._images[2].fill((0,0,255))
self._rect = pygame.Rect(position, size)
self._index = 0
def draw(self, screen):
screen.blit(self._images[self._index], self._rect)
def event_handler(self, event):
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1 and self._rect.collidepoint(event.pos):
self._index = (self._index+1) % 3
pygame.init()
screen = pygame.display.set_mode((320,110))
button1 = Button((5, 5), (100, 100))
button2 = Button((110, 5), (100, 100))
button3 = Button((215, 5), (100, 100))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
button1.event_handler(event)
button2.event_handler(event)
button3.event_handler(event)
button1.draw(screen)
button2.draw(screen)
button3.draw(screen)
pygame.display.flip()
pygame.quit()
If I understood the question correctly, you need a single button that changes the look every time you click on it, and changes its relative function accordingly.
You should be able to solve your problem by creating a class that takes two list and a counter
1) list of images
2) list of functions
3) the counter tells you which image/function is selected.
The functions needs to be built in the class, but you can provide the image that you want in the class argument (actually, you could pass them as arguments, but I don't think is worth it).
Here is the code, I commented some lines with their intended meaning (in line comments)
import pygame
import sys
pygame.init()
width = 600
height = 400
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Magic Buttons")
background = pygame.Surface(screen.get_size())
clock = pygame.time.Clock()
class Buttons:
def __init__(self, posX, posY, image1, image2, image3):
self.image_list = [image1, image2, image3] # static list of images
self.function_list = [self.button_function_1,self.button_function_2,self.button_function_3 ]
self.rect_position = (posX, posY) # this is a tuple to identify the upper left corner of the rectangle of the image
self.button_type = 0 # initial value of the button, both for the function and the image
self.image = pygame.image.load(self.image_list[0]) #default image, index number 0 of image_list
self.rect = pygame.Rect(posX, posY, self.image.get_width(), self.image.get_height()) # create a rectangle object same size of the images
def check(self, pos):
if self.rect.collidepoint(pos) ==True:
self.change_button()
else:
pass
def change_button(self):
self.button_type = (self.button_type +1)%3
self.image = pygame.image.load(self.image_list[self.button_type ]) # load the image relative to button_type
self.function_list[self.button_type -1]() # execute the function relative to the new value of button_type
self.draw_button()
def draw_button(self):
screen.blit(self.image, self.rect_position) # blit the new button image
def button_function_1(self):
print ("function 1 in action")
def button_function_2(self):
print ("function 2 in action")
def button_function_3(self):
print ("function 3 in action")
multibutton = Buttons(100,100,"button1.png","button2.png","button3.png") # create an istance of the button in the x=100, y = 100, with the three image button
while True:
background.fill((0,0,0))
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos() # fetch the position of the mouse
multibutton.check(pos) # check if the mouse is on the button
multibutton.draw_button()
pygame.display.flip()

Pygame: Why is my circle not being drawn onto my sprite's surface?

This is probably so simple, but I cannot see my error. Why is my ball not being drawn onto my sprite's surface and thus not appearing on the screen? When I change the 'draw ellipse' line in the class so that it is drawn onto the screen (instead of onto the surface), it shows. What am I doing wrong?
import pygame
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
class Ball(pygame.sprite.Sprite):
"""This class represents the ball."""
def __init__(self, width, height):
""" Constructor. Pass in the balls x and y position. """
# Call the parent class (Sprite) constructor
super().__init__()
# Create the surface, give dimensions and set it to be transparent
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
# Draw the ellipse onto the surface
pygame.draw.ellipse(self.image, (255,0,0), [0,0,width,height], 10)
# Initialize Pygame
pygame.init()
# Set the height and width of the screen
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode((screen_width, screen_height))
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# Loop until the user clicks the close button.
done = False
# -------- Main Program Loop -----------
while not done:
# --- Events code goes here (mouse clicks, key hits etc)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Clear the screen
screen.fill((255,255,255))
# --- Draw all the objects
ball = Ball(100,100)
# --- Update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
pygame.quit()
The circle is drawn onto your sprite's surface, but you never draw the sprite onto the screen.
Also, you should probably only create one instance of Ball, not one on every iteration of your main loop.
You usually put your sprites into groups and call draw on those to actually draw the sprites, like
...
# Loop until the user clicks the close button.
done = False
# --- Create sprites and groups
ball = Ball(100,100)
g = pygame.sprite.Group(ball)
# -------- Main Program Loop -----------
while not done:
# --- Events code goes here (mouse clicks, key hits etc)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Clear the screen
screen.fill((255,255,255))
# --- Draw all the objects
g.draw(screen)
# --- Update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
pygame.quit()
Note that your sprite needs also a rect attribute for this to work:
...
# Create the surface, give dimensions and set it to be transparent
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
# this rect determinies the position the ball is drawn
self.rect = self.image.get_rect()
# Draw the ellipse onto the surface
pygame.draw.ellipse(self.image, (255,0,0), [0,0,width,height], 10)
...