I am trying to build a simple game, but I'm having trouble with the mouse as it's doesn't show that it's coordinates are changing.
Here's my code:
import pygame
pygame.init()
# Colors
white = (255, 255, 255)
black = (0, 0, 0)
blue = (0, 0, 255)
# Game Screen Dimensions
game_layout_length = 500
game_layout_width = 500
# Mouse Positions
pos = pygame.mouse.get_pos()
# Character Attributes
character_length = 10
character_width = 10
game_screen = pygame.display.set_mode((game_layout_width, game_layout_length))
game_close = False
game_lost = False
while not game_close:
while not game_lost:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_close = True
game_lost = True
if event.type == pygame.MOUSEBUTTONDOWN:
print(pos)
game_screen.fill(black)
pygame.display.update()
pygame.quit()
quit()
This is the result after clicking on multiple different parts of the screen:
pygame 2.1.2 (SDL 2.0.18, Python 3.8.2)
Hello from the pygame community. https://www.pygame.org/contribute.html
(0, 0)
(0, 0)
(0, 0)
(0, 0)
(0, 0)
Process finished with exit code 0
Also, is there a way to get a rectangle to follow my mouse? I tried doing pygame.mouse.rect(game_screen, blue, [pos, character_length, character_width]), but that just crashed my program.
So, the problem is that you are not refreshing the mouse position, because is not in the loop. All you need to do is to put the pos variable inside the loop.
Here is how should you do it:
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
print(pos)
game_screen.fill(black)
pygame.display.update()
This is the answer for your second question:
So, the issue there is that after you draw the rectangle, you are filling the screen with black, so, all the rectangles are covered up with the color black.
All you need to do is to delete game_screen.fill(black) and it will work.
Thanks, I successfully set a variable to my x and y coordinates but when I try to make something (like a rectangle) follow my mouse, it doesn't work or even show up. The program just executes a plain black screen.
Here's my code:
import pygame
pygame.init()
# Colors
white = (255, 255, 255)
black = (0, 0, 0)
blue = (0, 0, 255)
# Game Screen Dimensions
game_layout_length = 500
game_layout_width = 500
# Character Attributes
character_length = 10
character_width = 10
game_screen = pygame.display.set_mode((game_layout_width, game_layout_length))
game_close = False
game_lost = False
while not game_close:
while not game_lost:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_close = True
game_lost = True
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
character_x = pos[0]
character_y = pos[1]
pygame.draw.rect(game_screen, blue, [character_x, character_y, character_length, character_width])
game_screen.fill(black)
pygame.display.update()
pygame.quit()
quit()
I used a debug line to see if it was an issue with the variables, but those seemed to be working just fine, so I'm unsure where the issue is.
Related
I am trying to create a pixel-art making program using pygame (yes, I know there are better packages to use). The way that I am drawing pixels is via surface.set_at(). I need to know how to completely delete a pixel from a pygame surface, so that I can have an eraser tool. I do not want to fill the pixel in with the background color of the window, because that would still render when using pygame.image.save() to get an image file from the drawing. Can someone please help? Here is my code:
import pygame
import sys
import math
pygame.init()
clock = pygame.time.Clock()
pygame.display.set_caption("Pixel Studio v1.1")
screen = pygame.display.set_mode((960, 720), pygame.RESIZABLE)
scroll_speed = 5
canvas_size = (32, 16)
color = (255, 255, 255)
canvas_surf = pygame.Surface(canvas_size, pygame.SRCALPHA)
zoom = 12
mouse_down = False
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.image.save(canvas_surf, "canvas.png")
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == pygame.BUTTON_LEFT:
mouse_down = True
if event.button == pygame.BUTTON_WHEELUP:
if zoom > 2:
zoom -= scroll_speed
if event.button == pygame.BUTTON_WHEELDOWN:
zoom += scroll_speed
if event.type == pygame.MOUSEBUTTONUP:
if event.button == pygame.BUTTON_LEFT:
mouse_down = False
if zoom < 2:
zoom = 2
screen.fill((50, 50, 50))
#canvas_surf.fill((200, 200, 200))
canvas_surf_scaled = pygame.transform.scale(canvas_surf,(canvas_surf.get_width() * zoom, canvas_surf.get_height() * zoom))
canvas_rect = canvas_surf_scaled.get_rect(center=(screen.get_width()/2, screen.get_height()/2))
mouse_pos = pygame.mouse.get_pos()
if mouse_down:
canvas_surf.set_at((math.floor((mouse_pos[0] - canvas_rect.x) / zoom), math.floor((mouse_pos[1] - canvas_rect.y) / zoom)), color)
pygame.draw.rect(screen, ( 75, 75, 75), canvas_rect, 1,)
screen.blit(canvas_surf_scaled, canvas_rect)
pygame.display.flip()
clock.tick(60)
As discussed in the comments, you can make a pixel transparent by setting it to a value whose alpha value is zero.
#r #g #b #a
canvas_surf.set_at((x, y), (0, 0, 0, 0))
I an having an error with MOUSEBUTTONDOWN giving an error when used.
Here is the error:
if event.type == MOUSEBUTTONDOWN:
NameError: name 'MOUSEBUTTONDOWN' is not defined
Here is the code that is giving the error:
import pygame
import random
import sys
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
pygame.init()
# Set the width and height of the screen [width, height]
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Game logic should go here
# --- Screen-clearing code goes here
# Here, we clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
# If you want a background image, replace this clear with blit'ing the
# background image.
screen.fill(WHITE)
# --- Drawing code should go here
monospace = pygame.font.SysFont("Berlin Sans FB", 169)
label = monospace.render("test", 1, (0, 0, 0))
screen.blit(label, (100, 100))
button_rect = pygame.Rect(0, 0, 50, 50) # start button rectangle
abort = False
start = False
while not abort and not start:
for event in pygame.event.get():
if event.type == pygame.QUIT:
abort = True
if event.type == MOUSEBUTTONDOWN:
if button_rect.collidepoint(event.pos):
start = True
# draw title screen
# [...]
done = abort
while not done:
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
# Close the window and quit.
pygame.quit()
All the other sources on Stack Overflow about this topic that I can find all talk about errors where MOUSEBUTTONDOWN already works.
Also note that I am using Pycharm.
Either pygame.MOUSEBUTTONDOWN instead of MOUSEBUTTONDOWN or from pygame.locals import *
You need only one application loop:
import pygame
from pygame.locals import *
import random
import sys
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
pygame.init()
# Set the width and height of the screen [width, height]
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("game")
clock = pygame.time.Clock()
monospace = pygame.font.SysFont("Berlin Sans FB", 169)
label = monospace.render("test", 1, (0, 0, 0))
button_rect = pygame.Rect(0, 0, 50, 50) # start button rectangle
abort = False
start = False
while not abort:
for event in pygame.event.get():
if event.type == pygame.QUIT:
abort = True
if event.type == MOUSEBUTTONDOWN:
if not start and button_rect.collidepoint(event.pos):
start = True
screen.fill(WHITE)
if not start:
# draw title screen
pygame.draw.rect(screen, "red", button_rect)
else:
# draw game
# [...]
screen.blit(label, (100, 100))
pygame.display.flip()
clock.tick(60)
pygame.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()
Solution found:
I did not have the needed libraries imported:
For MOUSEBUTTONDOWN to work you need to use:
from pygame.locals import *
Credit to #Rabbid76 for answering in comments.
so i'm coding this pygame for fun just to test my knowledge in this area and i'm facing a minor problem. My character is not appearing on the pygame window except for like a second when i press the X button to close the tab, here is what i've coded so far.
import pygame
pygame.init
window = pygame.display.set_mode((700 , 700))
pygame.display.set_caption("practice")
#Character attributes
x = 50
y = 50
width = 30
height =30
velocity = 5
#quit
run = True
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.draw.rect(window, (0, 0, 255), (x , y, width, height))
pygame.display.update()
pygame.quit()
It's a common problem when people forget to indent code inside nested loops right. Here drawing occurs only when event happens, but it should be done on every frame. To fix this unindent render code
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.draw.rect(window, (0, 0, 255), (x , y, width, height))
pygame.display.update()
I want to make a kind of "level editor" as an exercise.
I've got this code:
import pygame
running = True
pygame.init()
screen = pygame.display.set_mode((800, 500))
class Cube:
def update(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx, self.cy, 50, 50)
def draw(self):
pygame.draw.rect(screen, (255, 0, 0), self.square)
cube = Cube()
drawing_cube = False
drawing_cube2 = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
cube.update()
drawing_cube = True
screen.fill((0, 255, 0))
if drawing_cube:
cube.draw()
pygame.display.flip()
pygame.quit()
However, it doesn't create multiple squares; it just re-locates the already created square.
It's doing exactly what you told it to do: update the one and only Cube object in the game, and then redraw the screen and that one object. If you want multiple cubes, you have to create each one. Perhaps something like this:
cube_list = [] # List of all cubes
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN: # Make a new cube
cube = Cube()
cube.update()
cube_list.append(cube)
drawing_cube = True
screen.fill((0, 255, 0))
if drawing_cube: #New cube made; draw them all.
for cube in cube_list:
cube.draw()
pygame.display.flip()
Now, as an exercise for the student, can you simplify this so that it merely adds the most recent cube to the existing screen, instead of redrawing the entire game area for each new cube?
Thanks, Prune! but for anyone that is reading this after me, here is the full code:
import pygame
cube_list = []
running = True
pygame.init()
screen = pygame.display.set_mode((800, 500))
class Cube:
def update(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx, self.cy, 50, 50)
def draw(self):
pygame.draw.rect(screen, (255, 0, 0), self.square)
cube = Cube()
drawing_cube = False
drawing_cube2 = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN: # Make a new cube
cube = Cube()
cube.update()
cube_list.append(cube)
drawing_cube = True
screen.fill((0, 255, 0))
if drawing_cube: #New cube made; draw them all.
for cube in cube_list:
cube.draw()
pygame.display.flip()
pygame.quit()
Cheers!
P.S I've marked your answer as accepted
How can I detect if an image has been touched in pygame on a touch screen? I have searched but I can not find how to detect if a particular image is touched.
To detect if an image has been touched, you can use the MOUSEBUTTONDOWN event. See Pygame mouse clicking detection.
Load the image with pygame.image.load(). Crate the bounding rectangle (pygame.Rect). Create a pygame.Mask from the image with pygame.mask.from_surface:
image = pygame.image.load('image.png').convert_alpha()
image _rect = image.get_rect(topleft = (x, y))
image_mask = pygame.mask.from_surface(image)
Use the MOUSEBUTTONDOWN event to detect if the mouse is clicked in the rectangular area of the image. Check if the corresponding bit in the image mask is set:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
image_x, image_y = event.pos[0] - image_rect.x, event.pos[1] - image_rect.y
if image_rect.collidepoint(event.pos) and image_mask.get_at((image_x, image_y)):
print("touched")
Minimal example:
import pygame
pygame.init()
window = pygame.display.set_mode((400, 400))
font = pygame.font.SysFont(None, 100)
clock = pygame.time.Clock()
text = font.render("Text", True, (255, 255, 0))
bomb = pygame.image.load('Bomb-256.png').convert_alpha()
bomb_rect = bomb.get_rect(center = window.get_rect().center)
bomb_mask = pygame.mask.from_surface(bomb)
click_count = 0
click_text = font.render('touch: ' + str(click_count), True, "black")
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
image_x, image_y = event.pos[0] - bomb_rect.x, event.pos[1] - bomb_rect.y
if bomb_rect.collidepoint(event.pos) and bomb_mask.get_at((image_x, image_y)):
click_count += 1
click_text = font.render('touch: ' + str(click_count), True, "black")
window.fill((255, 255, 255))
window.blit(bomb, bomb_rect)
window.blit(click_text, click_text.get_rect(topleft = (20, 20)))
pygame.display.flip()
pygame.quit()
exit()
If I run this from the raspberry pi desktop the touch is not detected.
But if I execute this from ssh remote it works fine