Delete draw when clicking - python

I did a lot of research on how to delete a drawing on the screen after clicking it, and I couldn't do that
Try1 how to remove draw objects from pygame window?
Try2 How to remove a drawn circle in pygame? (without "going over" other things)
When clicked on the circle it will remove itself, and thus create another circle to be able to click.
import pygame, sys
from pygame.locals import *
from pygame import mixer
pygame.init()
musica = 'circles.mp3'
mixer.music.load(musica)
mixer.music.play()
pygame.init()
screen = pygame.display.set_mode((500, 500))
pygame.display.set_caption("OSU DA DEEP WEB")
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
screen.fill(WHITE)
#posição
width = 500 -30
height = 500 - 30
widthposition = random.randrange(width)
heightposition = random.randrange(width)
#sistema de pontos
points = 0
circle = pygame.draw.circle(screen, (0, 0, 0), (400, 300), 25)
def draw():
print('CLicked')
circle = pygame.draw.circle(screen, (0, 0, 0), (400, 300), 25)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
pygame.display.flip()

You have to check event to catch when left button was click and then you can draw white background and draw circle
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == pygame.BUTTON_LEFT:
screen.fill(WHITE)
draw(screen)
But this still doesn't check if you clicked on circle.
Minimal working code.
import sys
import random
import pygame
# --- constants ---
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
WIDTH = 500
HEIGHT = 500
# --- functions ---
def draw(screen):
print('Clicked')
x = random.randrange(30, WIDTH-30)
y = random.randrange(30, HEIGHT-30)
pygame.draw.circle(screen, (0, 0, 0), (x, y), 25)
# --- main ---
musica = 'circles.mp3'
pygame.init()
pygame.mixer.music.load(musica)
pygame.mixer.music.play()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
screen.fill(WHITE)
draw(screen)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == pygame.BUTTON_LEFT:
screen.fill(WHITE)
draw(screen)
pygame.display.flip()
draw.circle gives object pygame.Rect() with rectangle area used by circle and you could use it to "check collision" with mouse position
circle_rect = pygame.draw.circle(...)
#... code ...
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == pygame.BUTTON_LEFT:
if circle_rect.collidepoint(even.pos):
screen.fill(WHITE)
draw(screen)
and it check position in rectangle area so it works better but not ideal
import sys
import random
import pygame
# --- constants ---
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
WIDTH = 500
HEIGHT = 500
# --- functions ---
def draw(screen):
print('Clicked')
x = random.randrange(30, WIDTH-30)
y = random.randrange(30, HEIGHT-30)
circle_rect = pygame.draw.circle(screen, (0, 0, 0), (x, y), 25)
return circle_rect
# --- main ---
musica = 'circles.mp3'
pygame.init()
pygame.mixer.music.load(musica)
pygame.mixer.music.play()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
screen.fill(WHITE)
circle_rect = draw(screen)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == pygame.BUTTON_LEFT:
if circle_rect.collidepoint(event.pos):
screen.fill(WHITE)
circle_rect = draw(screen)
pygame.display.flip()
There is function to check collicion in cicle area but it works for two pygame.sprite.Sprite, not for single pygame.Rect and mouse position (single point). You would have to convert mouse position and pygame.Rect to pygame.sprite.Sprite but it is to complex for this problem.
Doc: pygame.sprite.collide_circle()
OR you can use pygame.math.Vector2.distance_to() to calculate distance between mouse position and center of circle - it has to be equal or smaller then 25
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == pygame.BUTTON_LEFT:
pos = pygame.math.Vector2(event.pos)
if pos.distance_to(circle_rect.center) <= 25:
screen.fill(WHITE)
circle_rect = draw(screen)
import sys
import random
import pygame
# --- constants ---
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
WIDTH = 500
HEIGHT = 500
# --- functions ---
def draw(screen):
print('Clicked')
x = random.randrange(30, WIDTH-30)
y = random.randrange(30, HEIGHT-30)
circle_rect = pygame.draw.circle(screen, (0, 0, 0), (x, y), 25)
return circle_rect
# --- main ---
musica = 'circles.mp3'
pygame.init()
pygame.mixer.music.load(musica)
pygame.mixer.music.play()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
screen.fill(WHITE)
circle_rect = draw(screen)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == pygame.BUTTON_LEFT:
pos = pygame.math.Vector2(event.pos)
if pos.distance_to(circle_rect.center) <= 25:
screen.fill(WHITE)
circle_rect = draw(screen)
pygame.display.flip()
EDIT:
If you will want to add other object which will move then you will have to organize it in different way. In while True in every loop you will have to clear screen and draw again all object. And this needs more changes
import sys
import random
import pygame
# --- constants ---
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
WIDTH = 500
HEIGHT = 500
FPS = 25
# --- classes ---
class Circle():
def __init__(self, x, y, r, color, random=False):
self.x = x
self.y = y
self.r = r
self.color = color
# vector to check collision
self.center = pygame.math.Vector2((x, y))
if random:
self.set_random_position()
def draw(self, screen):
#pygame.draw.circle(screen, self.color, (self.x, self.y), self.r)
pygame.draw.circle(screen, self.color, self.center, self.r)
def check_collision(self, position):
return self.center.distance_to(position) <= self.r
def set_random_position(self):
self.x = random.randint(30, WIDTH-30) # `randint` better then `randrange`
self.y = random.randint(30, HEIGHT-30) # `randint` better then `randrange`
# vector to check collision
self.center = pygame.math.Vector2(self.x, self.y)
def move_random(self):
dx = random.randint(-5, 5) # `randint` better then `randrange`
dy = random.randint(-5, 5) # `randint` better then `randrange`
self.x += dx
self.y += dy
if self.x < self.r:
self.x = self.r
if self.x > WIDTH-self.r:
self.x = WIDTH-self.r
if self.y < self.r:
self.y = self.r
if self.y > HEIGHT-self.r:
self.y = HEIGHT-self.r
self.center = pygame.math.Vector2(self.x, self.y)
# --- functions ---
# ... empty ...
# --- main ---
musica = 'circles.mp3'
pygame.init()
#pygame.mixer.music.load(musica)
#pygame.mixer.music.play()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
# create circle
circle = Circle(0, 0, 25, RED, random=True)
# create other objects and keep on list
others = [Circle(0, 0, 10, GREEN, random=True) for _ in range(100)]
clock = pygame.time.Clock()
while True:
# - events - (without draws)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == pygame.BUTTON_LEFT:
if circle.check_collision(event.pos):
# only change `x,y` without drawing
circle.set_random_position()
# - updates - (without draws)
# move other objects from list
for item in others:
item.move_random()
# - draws - (without events and updates)
# clear screen
screen.fill(WHITE)
# draw circle
circle.draw(screen)
# draw other objects from list
for item in others:
item.draw(screen)
# send on monitor
pygame.display.flip()
# - FPS -
# to keep the same speed on different computers (with different CPU speed)
clock.tick(FPS)

Related

Detect when my mouse is on 2 rect and choose the action

I don't know how to detect when my mouse is on 2 rect and choose (if two rect has an action) the action. For example, in Windows, when two windows are one over the other, it's the first window that will be selected. I want to do exactly the same thing.
import pygame
class Rectangle(pygame.sprite.Sprite):
def __init__(self, screen, rect, x, y, color, name):
super().__init__()
self.screen = screen
self.name = name
self.screen_str = str(screen)
self.rect = rect
self.color = color
self.x, self.y = x, y
self.r = pygame.Surface((self.rect[2], self.rect[3]), pygame.SRCALPHA)
self.rect = self.r.get_rect()
self.rect.x, self.rect.y = x, y
self.r.fill(self.color)
pygame.init()
screen = pygame.display.set_mode((1280, 720))
pygame.display.set_caption("PyStoneTest")
width, height = screen.get_size()
background_default = "image\Settings\Wallpaper\default_1.jpg"
D = {}
D["Rect2"] = Rectangle(screen, (0, 200, width, 70), 0,
50, (255, 255, 0), "Rect2")
D["Rect1"] = Rectangle(screen, (0, 100, width-200, 200), 0,
100, (255, 0, 255), "Rect1")
Programme = ["Rect1", "Rect2"]
while True:
background = pygame.image.load(background_default).convert()
background = pygame.transform.scale(background, (width, height))
for event in pygame.event.get():
x,y = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
pygame.quit()
for element in Programme:
if D[element].rect.collidepoint(x,y) and event.type == pygame.MOUSEBUTTONDOWN:
del Programme[Programme.index(D[element].name)]
Programme.append(D[element].name)
print(Programme)
screen.blit(background, (0, 0))
for element in Programme:
screen.blit(D[element].r, D[element].rect)
pygame.display.update()
You should first run for-loop to check all windows and use last one which collides with mouse.
elif event.type == pygame.MOUSEBUTTONDOWN:
last = None
for element in Programme:
if D[element].rect.collidepoint(event.pos):
last = element
if last:
Programme.remove(last)
Programme.append(last)
print(Programme)
Or you would have to check in reverse order - from last to first - and break loop on first matching rectangle.
elif event.type == pygame.MOUSEBUTTONDOWN:
last = None
for element in reversed(Programme):
if D[element].rect.collidepoint(event.pos):
last = element
break
if last:
Programme.remove(last)
Programme.append(last)
print(Programme)
Minimal working code with other changes
import pygame
# --- classes ---
class Rectangle(pygame.sprite.Sprite):
# I skip `x,y` because I have it in `rect`
def __init__(self, screen, rect, color, name):
super().__init__()
self.screen = screen
self.color = color
self.name = name
self.rect = pygame.Rect(rect)
self.image = pygame.Surface(self.rect.size, pygame.SRCALPHA)
self.image.fill(self.color)
def draw(self):
self.screen.blit(self.image, self.rect)
# --- functions ---
# empty
# --- main ---
pygame.init()
screen = pygame.display.set_mode((1280, 720))
screen_rect = screen.get_rect() # it can be useful to center elements on screen - `d[name].rect.center = screen_rect.center`
pygame.display.set_caption("PyStoneTest")
# raw string
background_default = r"image\Settings\Wallpaper\default_1.jpg"
# load and rescale before `while`-loop
background = pygame.image.load(background_default).convert()
background = pygame.transform.scale(background, screen_rect.size)
d = {} # PEP8: `lower_case_names` for variable
d["Rect2"] = Rectangle(screen, (0, 0, screen_rect.width-100, 70), (255, 255, 0), "Rect2")
d["Rect2"].rect.center = screen_rect.center
d["Rect1"] = Rectangle(screen, (0, 0, 70, screen_rect.height-100), (255, 0, 255), "Rect1")
d["Rect1"].rect.center = screen_rect.center
programme = ["Rect1", "Rect2"] # PEP8: `lower_case_names` for variable
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit() # to skip rest of while-loop
elif event.type == pygame.MOUSEBUTTONDOWN:
selected = None
for name in programme:
if d[name].rect.collidepoint(event.pos):
selected = name
if selected and selected != programme[-1]:
programme.remove(selected)
programme.append(selected)
print('after replace:', programme)
screen.blit(background, (0, 0))
for name in programme:
d[name].draw()
pygame.display.update()
I cannot help with your code since I cannot understand what you are doing but I can offer my own solution. Since pygame renders thigs that are drawn later on the top, you can change the rendering order of your rectangles by checking which rectangle is being clicked and swapping it with the last rectangle in your list.
Here is an example. The colors in my example change weirdly but that's because I am generating them on the fly just to be able to tell the different between the different rects. You shouldn't have this problem.
import pygame
pygame.init()
screen = pygame.display.set_mode((1280, 720))
pygame.display.set_caption("PyStoneTest")
rects = []
for i in range(10):
rects.append(pygame.Rect(i * 25, 100, 30, 30))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
screen.fill((0, 0, 0))
c = 1
for rect in rects:
pygame.draw.rect(screen, (c, 100, 100), rect)
c += 20
clicked = pygame.mouse.get_pressed()
x,y = pygame.mouse.get_pos()
for rect in rects:
if (rect.collidepoint(x, y) and clicked[0]):
#swap it
rects[-1][:], rect[:] = rect[:], rects[-1][:]
pygame.display.update()

How to Fill a rectangle with color every time the user clicks it? pygame

I know that there are several similar questions online, but none of them really helped me. I simply want to draw a grid and give the user the option to click into those grid cells. Every time the user clicks, the color/fill of the cell should change from black to white.
What I'm doing at the moment is the following:
BLACK = (0, 0, 0)
WHITE = (200, 200, 200)
def drawGrid(h, w, blocksize):
for x in range(w):
for y in range(h):
rect = pygame.Rect(x*blocksize, y*blocksize,
blocksize, blocksize)
pygame.draw.rect(SCREEN, WHITE, rect, 1)
def handle_events():
col = WHITE
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
col = WHITE
# determine mouse position
mpos_x, mpos_y = event.pos
# determine cell number
coord = mpos_x // blocksize, mpos_y // blocksize
rect = pygame.Rect(coord[0]*blocksize, coord[1]*blocksize,
blocksize, blocksize)
pygame.draw.rect(SCREEN, col, rect, 1)
pygame.display.update()
def main():
global SCREEN, CLOCK, blocksize
w = int( sys.argv[1] )
h = int( sys.argv[2] )
blocksize = int( sys.argv[3] )
pygame.init()
SCREEN = pygame.display.set_mode((h, w))
CLOCK = pygame.time.Clock()
SCREEN.fill(BLACK)
drawGrid(h,w,blocksize)
handle_events()
if __name__ == "__main__":
main()
The program is printing the grid. However, when I click somewhere nothing happens. I know this is not the best code, so I would appreciate for any suggestion.
I changed the code a little and it worked properly, pygame.draw.rect(SCREEN, col, rect, 1) you draw same thing and you can't see the change. You should use pygame.draw.rect(SCREEN, col, rect):
import pygame
import sys
BLACK = (0, 0, 0)
WHITE = (200, 200, 200)
# WINDOW_HEIGHT = 400
# WINDOW_WIDTH = 400
def drawGrid(h, w, blocksize):
#blockSize = 20 #Set the size of the grid block
for x in range(w):
for y in range(h):
rect = pygame.Rect(x*blocksize, y*blocksize,
blocksize, blocksize)
pygame.draw.rect(SCREEN, WHITE, rect, 1)
def handle_events():
#coords_list = []
col = WHITE
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
col = WHITE
# determine mouse position
mpos_x, mpos_y = event.pos
# determine cell number
coord = mpos_x // 32, mpos_y // 32
rect = pygame.Rect(coord[0]*32, coord[1]*32,
32, 32)
pygame.draw.rect(SCREEN, col, rect)
#coords_list.append(coord)
pygame.display.update()
#return coords_list
def main():
global SCREEN, CLOCK, blocksize
pygame.init()
SCREEN = pygame.display.set_mode((480, 640))
CLOCK = pygame.time.Clock()
SCREEN.fill(BLACK)
drawGrid(480,640,32)
handle_events()
if __name__ == "__main__":
main()
As a suggestion, I think you should use sprite for every cell. For example like this:
class Cell(pygame.sprite.Sprite):
def __init__(self, sprite_group, x, y, cell_dimension, color=BLACK):
self.groups = sprite_group
pygame.sprite.Sprite.__init__(self, self.groups)
self.image = pygame.Surface((cell_dimension, cell_dimension))
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.x = x * cell_dimension
self.rect.y = y * cell_dimension
self.clicked = False
def update(self):
if self.clicked:
self.image.fill(WHITE)

Click and drag a rectangle with pygame

I'm new to pygame and I'm writing a program that allows the user to click and drag a rectangle around the pygame window, then sends it's coordinates through a socket. I can move the rectangle on mouse click, but I've been messing around with it for a while and still can't figure out how to implement click and drag. Any help would be appreciated. Here's the relevant code:
from pygame.locals import *
import socket, pygame, time
#define variables
x = y = 0
screen = pygame.display.set_mode((430, 410))
targetRectangle = pygame.draw.rect(screen, (255, 0, 0), (176, 134, 7, 7))
pygame.display.flip()
#define smaller functions
#define function to start pygame window
def startPygame():
pygame.display.set_caption(option + " Tracking System")
pygame.mouse.set_visible(True)
screen.fill((255, 255, 255))
targetRectangle = pygame.draw.rect(screen, (255, 0, 0), (176, 134, 7, 7))
pygame.display.flip()
#define function to update pygame window
def updateWindow():
screen.fill((255, 255, 255))
global targetRectangle
global xPosition
global yPosition
targetRectangle = pygame.draw.rect(screen, (255, 0, 0), (xPosition, yPosition, 7, 7))
pygame.display.flip()
#define main functions
def collectMouseData():
startPygame()
print "\n"
print "mouse tracking system"
#wait until a mouse button is clicked
running = 1
while running == 1:
event = pygame.event.poll()
if event.type == pygame.QUIT:
c.send("quit")
pygame.quit()
running = 0
#see if a mousebutton is down
elif event.type == pygame.MOUSEBUTTONDOWN:
xMouse = event.pos[0]
yMouse = event.pos[1]
#see if mouse click collides with targetRectangle
if targetRectangle.collidepoint(xMouse, yMouse):
global xPosition
xPosition = event.pos[0]
global yPosition
yPosition = event.pos[1]
updateWindow()
global targetRectangle
sendData(targetRectangle)
You have to use
MOUSEBUTTONDOWN to check if object was clicked and set drag = True (and remember offset between mouse position and rectangle top-left corner)
MOUSEBUTTONUP to set drag = False
MOUSEMOTION to move object when drag == True using mouse position and offset.
Working example
import pygame
# --- constants --- (UPPER_CASE names)
SCREEN_WIDTH = 430
SCREEN_HEIGHT = 410
#BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
FPS = 30
# --- classses --- (CamelCase names)
# empty
# --- functions --- (lower_case names)
# empty
# --- main ---
# - init -
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
#screen_rect = screen.get_rect()
pygame.display.set_caption("Tracking System")
# - objects -
rectangle = pygame.rect.Rect(176, 134, 17, 17)
rectangle_draging = False
# - mainloop -
clock = pygame.time.Clock()
running = True
while running:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if rectangle.collidepoint(event.pos):
rectangle_draging = True
mouse_x, mouse_y = event.pos
offset_x = rectangle.x - mouse_x
offset_y = rectangle.y - mouse_y
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
rectangle_draging = False
elif event.type == pygame.MOUSEMOTION:
if rectangle_draging:
mouse_x, mouse_y = event.pos
rectangle.x = mouse_x + offset_x
rectangle.y = mouse_y + offset_y
# - updates (without draws) -
# empty
# - draws (without updates) -
screen.fill(WHITE)
pygame.draw.rect(screen, RED, rectangle)
pygame.display.flip()
# - constant game speed / FPS -
clock.tick(FPS)
# - end -
pygame.quit()
EDIT: other examples with many rectangles or circles and buttons on GitHub:
furas/python-examples/pygame/drag-rectangles-circles

How to make a block move back and forth in pygame

I am trying to make a moving platform so when the platforms reaches a curtain point it is supposed to reverse direction and go back but from what I can see it looks like it is vibrating back and fort
program link: https://drive.google.com/file/d/0BzvvQCByWwmAQThfdkEtSlRKa1k/view?usp=sharing
here is my code:
class lbuild(pygame.sprite.Sprite):
#This class represents alevel builder. It derives from the "Sprite" class in Pygame.
def __init__(self, color, width, height,x,y):
# Call the parent class (Sprite) constructor
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
# Draw the car (a rectangle!)
pygame.draw.rect(self.image, color, [0, 0, width, height])
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
self.rect.x=x
self.rect.y=y
all_sprites_list = pygame.sprite.Group()
movblock=pygame.sprite.Group()#sprite group
def level1():
global all_sprites_list
global movblock
xpos=0
for x in range(50):
all_sprites_list.add(lbuild(GREY,20,20,xpos,680))
xpos =xpos+20
ypos=660
xpos2 =40
for x in range(2):
all_sprites_list.add(lbuild(black,60,20,xpos2,ypos))
ypos=ypos-20
mblk=lbuild(RED,100,20,120,600)#draws the block
movblock.add(mblk)#adds it to the sprite group
clock=pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
#Game Logic
all_sprites_list.update()
#Drawing on Screen
screen.fill(WHITE)
#Draw The Road
spd=5
if mblk.rect.x>200:#supposed to cheak if the block x postion a has reached 200 and the reverse its direction but instead it looks like it is vibrating
spd= -spd
if mblk.rect.x<100:
spd= -spd
mblk.rect.x+=spd
#Now let's draw all the sprites in one go. (For now we only have 1 sprite!)
all_sprites_list.draw(screen)
movblock.draw(screen)
#Refresh Screen
pygame.display.flip()
#Number of frames per secong e.g. 60
clock.tick(60)
Your problem is spd = 5 inside while True.
You change direction using
spd = -spd
but after that you overwrite it using
spd = 5
You have to use spd = 5 before while True
Full version with other modifications.
import pygame
import sys
# --- constants --- (UPPER_CASE names)
WHITE = (255, 255, 255)
GREEN = (20, 255, 140)
GREY = (210, 210 ,210)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
PURPLE = (255, 0, 255)
BLACK = (0,0,0)
SCREEN_WIDTH=1000
SCREEN_HEIGHT=700
# --- classes --- (CamelCase names)
class LBuild(pygame.sprite.Sprite):
def __init__(self, color, width, height, x, y):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
# Draw the car (a rectangle!)
pygame.draw.rect(self.image, color, [0, 0, width, height])
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# --- functions --- (lower_case names)
def level_1(screen, all_sprites_list, movblock):
x = 0
for _ in range(50):
all_sprites_list.add(LBuild(GREY, 20, 20, x, 680))
x += 20
y = 660
x2 = 40
for _ in range(2):
all_sprites_list.add(LBuild(BLACK, 60, 20, x2, y))
y -= 20
mblk = LBuild(RED, 100, 20, 120, 600)
movblock.add(mblk)
spd = 5
# - mainloop -
clock = pygame.time.Clock()
#current_time = pygame.time.get_ticks()
# change something after 2s
#change_time = current_time + 2000 # 2000ms = 2s
while True:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
# False = exit game
return False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
# True = go to next level
return True
# - updates (without draws) -
#current_time = pygame.time.get_ticks()
#if current_time >= change_time:
# TODO: change something
# # change something again after 2s
# change_time = current_time + 2000
all_sprites_list.update()
if mblk.rect.x > 200:
spd = -spd
if mblk.rect.x < 100:
spd = -spd
mblk.rect.x += spd
# - draws (without updates) -
screen.fill(WHITE)
all_sprites_list.draw(screen)
movblock.draw(screen)
pygame.display.flip()
# - FPS -
clock.tick(60)
# --- main ---
# - init -
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Car Racing")
# - game -
all_sprites_list = pygame.sprite.Group()
movblock = pygame.sprite.Group()
goto_next_level = level_1(screen, all_sprites_list, movblock)
#if goto_next_level:
# goto_next_level = level_2(screen, all_sprites_list, movblock)
#if goto_next_level:
# goto_next_level = level_3(screen, all_sprites_list, movblock)
# - exit -
pygame.quit()
sys.exit()

Move polygon with move_ip in pygame

I can't get to move a polygon with the function move_ip() in pygame, the code works good if I draw a rectangle, but not with polygon. It doesn't respond when I press any arrow key.
I think I don't need spaceship rectangle because polygons are rects with pygame, but it seems not right, I don't know, i've got a mess.
This is my pygame code:
import sys, os
import pygame
from pygame.locals import *
import numpy as np
if sys.platform in ["win32","win64"]: os.environ["SDL_VIDEO_CENTERED"]='1'
width_screen = 600
height_screen = 480
screen_size = (width_screen, height_screen)
positionx_screen = 0
positiony_screen = 32
title_window = 'ASTEROIDS'
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
spaceship = pygame.Rect(200, 475, 120, 20)
def quit_screen(event):
if event.type == QUIT:
pygame.quit()
sys.exit()
class Spaceship():
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.colour = WHITE
self.thickness = 0
self.movex = 20
def draw_nave(self):
vertices = np.array([[screen_size[0]/2, screen_size[1] /2 - 30],[screen_size[0]/2 + 15, screen_size[1]/2],
[screen_size[0]/2-15, screen_size[1] / 2]])
pygame.draw.polygon(screen_game, self.colour, vertices, self.thickness)
def move_spaceship_right(self):
spaceship.move_ip(self.movex, 0)
def move_spaceship_left(self):
spaceship.move_ip(- self.movex, 0)
def game():
pygame.init()
running = True
global screen_game
screen_game = pygame.display.set_mode(screen_size,
positionx_screen, positiony_screen)
pygame.display.set_caption(title_window)
clock = pygame.time.Clock()
my_spaceship = Spaceship(200, 475, 120, 20)
screen_game.fill(BLACK)
while running:
screen_game.fill(BLACK)
for event in pygame.event.get():
quit_screen(event)
if event.type == pygame.KEYDOWN:
if event.key == K_RIGHT:
my_spaceship.move_spaceship_right()
if event.key == K_LEFT:
my_spaceship.move_spaceship_left()
my_spaceship.draw_nave()
pygame.display.flip()
clock.tick(60)
if __name__ == "__main__":
try:
game()
except:
pygame.quit()
Thanks
The problem is that your Rect is in no way related to the polygon you draw. You simply draw it at the same position every time.
Better create a Surface once, draw your polygon on that Surface once, and use spaceship as position when drawing that new Surface.
I recommend subclassing from Sprite, create that Surface in the __init__ function, and save the Rect in self.rect instead of the spaceship variable.
Then either use the draw function of Sprite or put your Sprite into a Group.

Categories