I made a background music ingame, i put a volume muted & unmuted sprite and made it clickable,
When you mute the music, i want screen.blit(unmute) to disappear.
Source Code:
...
x = 0
pygame.mixer.music.load("soundtrack.wav")
volume = pygame.image.load("volume.png")
mute = pygame.image.load("mute.png")
resized_volume = pygame.transform.scale(volume, (100, 100))
resized_mute = pygame.transform.scale(mute, (100,100))
pygame.mixer.music.play(-1,0.0)
while Loop: # main game loop
...
if event.type == MOUSEBUTTONDOWN:
if event.button == 1: # 1 == left
vol_rect = volume.get_rect(topleft = (700,500))
if vol_rect.collidepoint(event.pos):
x += 1
if x > 2:
x = 1
if x == 1:
screen.blit(mute,(700,500))
pygame.mixer.music.pause()
else:
if x == 2:
screen.blit(volume, (700,500))
pygame.mixer.music.unpause()
...
pygame.quit()
sys.exit()
You have to redraw the scene in every frame. Draw the sprites depending on the value of the variable x. e.g.:
while Loop: # main game loop
# [...]
if event.type == MOUSEBUTTONDOWN:
if event.button == 1: # 1 == left
# [...]
# [...]
if x == 0:
# [...] draw something different
elif x == 1:
screen.blit(mute,(700,500))
elif x == 2:
screen.blit(volume, (700,500))
# [...]
I didn't try but I hope it works:
class MuteUnmute_Button:
def __init__(self):
self.x = 500
self.y = 400
self.state = True
self.mute_image = pygame.image.load("mute_image.png")
self.unmute_image = pygame.image.load("unmute_image.png")
self.image = mute_image
self.screen = screen
def redraw(self):
self.screen.blit(self.image,(self.x,self.y))
def checkCollision(self):
rect = self.image.get_rect()
return rect.collidepoint(pygame.mouse.pos)
def changeImage(self):
if self.state:
self.image = self.mute_image
else:
self.image = self.unmute_image
mute_unmute_button = MuteUnmuteButton()
while Loop:
for event in pygame.event.get():
if event.type == MOUSEBUTTONDOWN:
if event.button == 1:
if mute_unmute_button.checkCollision():
if mute_unmute_button.state:
mute_unmute_button.state = False
mute_unmute_button.changeImage()
pygame.mixer.music.pause()
else:
mute_unmute_button.state = True
mute_unmute_button.changeImage()
pygame.mixer.music.unpause()
screen.fill((255,255,255)) #Fills background
mute_unmute_button.redraw()
pygame.display.flip()
I gave a example, you can change code for your program.
Related
I want to have my background alternate between night and day (sprites) every 15 seconds or so, but I want this to happen only while the game is running (True), I've placed it in every place in my while loop, can't seem to get it going. The code we're looking at is the following:
if event.type == BACKCHANGE:
screen.blit(back_change,(0,0))
else:
screen.blit(bg_image,(0,0))
Here's how it fits into my game:
import pygame, sys, time, random
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((500, 800))
pygame.display.set_caption('FALLING MAN')
#Game elements
gravity = 0.15
mov_of_man_x = 0
mov_of_man_y = 0
right_mov = 50
left_mov = 50
game_active = True
#day background
bg_image = pygame.image.load("/Users/apple/Downloads/Python Projects/Climbing_Game/bckwall.jpg").convert()
bg_image = pygame.transform.scale(bg_image,(500, 900))
#night background
bg_image2 = pygame.image.load("/Users/apple/Downloads/Python Projects/Climbing_Game/bckwall2.jpg").convert()
bg_image2 = pygame.transform.scale(bg_image2,(500, 900))
#background swap
back_changer = [bg_image, bg_image2]
back_change = random.choice(back_changer)
#the player
man = pygame.image.load("/Users/apple/Downloads/Python Projects/Climbing_Game/man.png").convert_alpha()
man = pygame.transform.scale(man, (51, 70))
man_rec = man.get_rect(center = (250, -500))
#the platforms player moves on
platform = pygame.image.load("/Users/apple/Downloads/Python Projects/Climbing_Game/platform.png").convert_alpha()
platform = pygame.transform.scale(platform,(300,60))
platform_rec = platform.get_rect(center = (250,730))
#game over screen
game_over_screen = pygame.image.load("/Users/apple/Downloads/Python Projects/Climbing_Game/End_screen.png").convert_alpha()
game_over_screen = pygame.transform.scale(game_over_screen,(500,800))
#moving platforms
def create_plat():
random_plat_pos = random.choice(plat_pos)
new_plat = platform.get_rect(center = (random_plat_pos, 800))
return new_plat
def mov_plat(plats):
for plat in plats:
plat.centery -= 4
return plats
def draw_plat(plats):
for plat in plats:
screen.blit(platform, plat)
#collison detection
def detect_plat(plats):
for plat in plats:
if man_rec.colliderect(plat):
global mov_of_man_y
mov_of_man_y = -4
return
def detect_man(mans):
for man in mans:
if man_rec.top <= -700 or man_rec.bottom >= 900:
return False
if man_rec.left <= -100 or man_rec.right >= 500:
return False
else:
return True
#score
def display_score():
pass
#moving platforms
plat_list = []
PLATMOV = pygame.USEREVENT
pygame.time.set_timer(PLATMOV, 1200)
plat_pos = [100,200,300,400]
#back change
BACKCHANGE = pygame.USEREVENT
pygame.time.set_timer(BACKCHANGE, 1200)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
mov_of_man_x += right_mov
man_rec.centerx += mov_of_man_x
mov_of_man_x -= 50
if event.key == pygame.K_LEFT:
mov_of_man_x += left_mov
man_rec.centerx -= mov_of_man_x
mov_of_man_x -= 50
if event.type == PLATMOV:
plat_list.append(create_plat())
#surfaces
screen.blit(bg_image,(0,0))
if game_active == True:
#gravity
mov_of_man_y += gravity
man_rec.centery += mov_of_man_y
#plats
plat_list = mov_plat(plat_list)
draw_plat(plat_list)
detect_plat(plat_list)
game_active = detect_man(man_rec)
#character
screen.blit(man, man_rec)
"""
if event.type == BACKCHANGE:
screen.blit(back_change,(0,0))
else:
screen.blit(bg_image,(0,0))
"""
else:
screen.blit(game_over_screen, (0,0))
pygame.display.update()
clock.tick(120)
Add a variable that indicates which background to draw:
bg_images = [bg_image, bg_image2]
bg_index = 0
Change the background index when the BACKCHANGE event occurs:
for event in pygame.event.get():
if event.type == BACKCHANGE:
bg_index += 1
if bg_index >= len(bg_images):
bg_index = 0
blit the current background in the application loop:
while True:
# [...]
screen.blit(bg_images[bg_index], (0,0))
# [...]
Application loop:
bg_images = [bg_image, bg_image2]
bg_index = 0
# [...]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
# [...]
if event.type == pygame.KEYDOWN:
# [...]
if event.type == PLATMOV:
# [...]
if event.type == BACKCHANGE:
bg_index += 1
if bg_index >= len(bg_images):
bg_index = 0
if game_active == True:
screen.blit(bg_images[bg_index], (0,0))
# [...]
else:
screen.blit(game_over_screen, (0,0))
pygame.display.update()
clock.tick(120)
I was following this tutorial on how to make a typing speed calculator using pygame and whenever I run the code everything renders out as it should but when I try clicking on the text field to input some text it just freezes and nothing happens. I tried to search online or watch tutorials but everything came up empty.
import sys
import time
import random
import pygame
from pygame.locals import *
"""Python Script for a typing speed test game"""
class Game(object):
def __init__(self):
self.h = 720
self.w = 1280
self.reset = True
self.active = False
self.word = ""
self.input_text = ""
self.time_start = 0
self.total_time = 0
self.accuracy = "0%"
self.wpm = 0
self.results = "Speed(WPM):0 Accuracy:0% Time:0"
self.end = False
self.head_col = (255,213,102)
self.text_col = (255,255,255)
self.result_color = (53,209,29)
pygame.init()
self.open_image = pygame.image.load("splash.jpg")
self.open_image = pygame.transform.scale(self.open_image, (self.w,self.h))
self.background = pygame.image.load("background.jpg")
self.background = pygame.transform.scale(self.background, (self.w, self.h))
self.screen = pygame.display.set_mode((self.w,self.h))
pygame.display.set_caption = "Type Speed Test"
def draw_text(self, screen, msg, y, fsize, color):
font = pygame.font.SysFont("consolas", fsize)
text = font.render(msg, 1, color)
text_rect = text.get_rect(center=(self.w/2, y))
screen.blit(text, text_rect)
pygame.display.update()
def get_sentences(self):
f = open("sentences.txt").read()
sentence = f.split("\n")
sentences = random.choice(sentence)
return sentences
def show_results(self, screen):
if(not self.end):
#Calculate Time
self.total_time = time.Time() - self.time_start
#Calcualte Accuracy
count = 0
for i,c in enumarate(self.word):
try:
if self.input_text[i] == c:
count += 1
except:
pass
self.accuracy = count/len(self.word)*100
#Calculate wpm
self.wpm = len(self.input_text)*60/(5*self.total_time)
self.end = True
print(self.total_time)
self.results = "Time:" + str(round(self.total_time))
+ " secs Accuracy: " + str(round(self.accuracy)) + "%"
+ " WPM: " + str(round(self.wpm))
#restart icon
self.time_img = pygame.image.load("icon.png")
self.time_img = pygame.transform.scale(self.time_img, (80,320))
#screen.blit(self.time_img, (80,320))
screen.blit(self.time_img, (self.w/2-75, self.h-140))
self.draw_text(screen, "Reset", self/h - 70, 26, (100,100,100))
print(self.results)
pygame.display.update()
def run(self):
self.reset_game()
self.running=True
while(self.running):
clock = pygame.time.Clock()
self.screen.fill((0,0,0), (50,250,650,50))
pygame.draw.rect(self.screen,self.head_col, (50,250,650,50), 2)
# update the text of user input
self.draw_text(self.screen, self.input_text, 274, 26,(250,250,250))
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
self.running = False
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP:
x,y = pygame.mouse.get_pos()
# position of input box
if(x>=50 and x<=650 and y>=250 and y<=300):
self.active = True
self.input_text = ''
self.time_start = time.time()
# position of reset box
if(x>=310 and x<=510 and y>=390 and self.end):
self.reset_game()
x,y = pygame.mouse.get_pos()
elif event.type == pygame.KEYDOWN:
if self.active and not self.end:
if event.key == pygame.K_RETURN:
print(self.input_text)
self.show_results(self.screen)
print(self.results)
self.draw_text(self.screen, self.results,350, 28, self.RESULT_C)
self.end = True
elif event.key == pygame.K_BACKSPACE:
self.input_text = self.input_text[:-1]
else:
try:
self.input_text += event.unicode
except:
pass
pygame.display.update()
clock.tick(60)
def reset_game(self):
self.screen.blit(self.open_image, (0,0))
pygame.display.update()
time.sleep(1)
self.reset=False
self.end = False
self.input_text=''
self.word = ''
self.time_start = 0
self.total_time = 0
self.wpm = 0
# Get random sentence
self.word = self.get_sentences()
if (not self.word): self.reset_game()
#drawing heading
self.screen.fill((0,0,0))
self.screen.blit(self.background,(0,0))
msg = "Typing Speed Test"
self.draw_text(self.screen, msg,80, 80,self.head_col)
# draw the rectangle for input box
pygame.draw.rect(self.screen,(255,192,25), (50,250,650,50), 2)
# draw the sentence string
self.draw_text(self.screen, self.word,200, 28,self.text_col)
pygame.display.update()
Game().run()
How can this be fixed?
Your never handeling KEYDOWN Events. because the else if statement is indented to far.
You should change the following.
class Game(object):
...
def run(self):
...
while(self.running):
...
for event in pygame.event.get():
if event.type == QUIT:
...
elif event.type == pygame.MOUSEBUTTONUP:
...
elif event.type == pygame.KEYDOWN:
...
in to this:
class Game(object):
...
def run(self):
...
while(self.running):
...
for event in pygame.event.get():
if event.type == QUIT:
...
elif event.type == pygame.MOUSEBUTTONUP:
...
elif event.type == pygame.KEYDOWN:
...
In Game.reset_game you recusively call Game.reset_game() with no exit.
Remove the call to self.reset_game so the game can be reset.
You also sleep for 1 second in reset_game without listening to events. This will make the pygame window seem inresponsive.
And it lets the process take 1000 seconds or ~ 17 minutes before the RecursionError is triggerd from recursively calling reset_game. Rather then seconds.
This question already has answers here:
How to get keyboard input in pygame?
(11 answers)
How can I make a sprite move when key is held down
(6 answers)
Closed 2 years ago.
I'm starting a grid based game in Pygame, and I've gotten to the point where I have a grid on the screen, and I'm trying to let the user use the arrow keys to move the grid around. I tried to do it by adding a method to my Grid Object, but it doesn't seem to be doing anything. Help would be appreciated
#IMPORTING MODULES
import pygame
from pygame.locals import *
import random
import sys
white = (250,250,250)
black = (0,0,0)
#SETTING UP STUFF
pygame.init()
#ADDING FONTS AND TEXT
myfont = pygame.font.SysFont("monospace", 25)
title = myfont.render("X-COM: UFO DEFENSE", 1, (black))
#MORE SETTING UP
display_width = 800
display_height = 600
SIZE = 25
keys = [False,False,False,False]
scene = "start"
screen = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('X-COM UFO DEFENSE')
#SETTING UP BUTTON CLASS
class Button(object):
def __init__(self, x, y, width, height,text,touching,clicked):
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
self.rect = pygame.Rect([int(self.x),int(self.y),int(self.width),int(self.height)])
self.touching = touching
self.clicked = clicked
def draw(self):
#DRAW FUNCTION(MAY NEED WORK ON THE TEXT FORMULA)
text1 = myfont.render(str(self.text), 1, (black))
pygame.draw.rect(screen,[255,255,255],self.rect,0)
screen.blit(text1, (self.x + self.width/3,self.y + self.height/3))
def click(self):
#EASY CLICK DETECTION
if self.rect.collidepoint(pygame.mouse.get_pos()):
self.touching = True
else:
self.touching = False
#Creating GRID class
class GridSquare(object):
def __init__(self, internal_row, internal_column, touching,clicked):
self.internal_row = internal_row
self.internal_column = internal_column
self.touching = touching
self.clicked = clicked
self.right = 0
self.up = 0
self.rect = pygame.Rect([int(self.internal_row),int(self.internal_column),25,25])
def draw(self):
pygame.draw.rect(screen,[255,0,255],self.rect,0)
def camera(self):
self.internal_row = self.right+self.internal_row
self.internal_column = self.up+self.internal_column
if keys[0] == True:
self.up += 1
elif keys[1] == True:
self.right -= 1
elif keys[2] == True:
self.up -= 1
elif keys[3] == True:
self.right += 1
#BUTTONS
grid = []
for i in range(100,200,26):
for k in range(100,200,26):
grid.append(GridSquare(i,k,False,False))
titlescreen = Button(300,300,200,100,"Start",False,False)
#MAIN LOOP STARTS HERE
while True:
if scene == "start":
screen.fill(white)
screen.blit(title, (300,50))
titlescreen.draw()
titlescreen.click()
#EVENTS
for event in pygame.event.get():
if titlescreen.touching == True and event.type == pygame.MOUSEBUTTONDOWN:
titlescreen.clicked = True
else:
titlescreen.clicked = False
if event.type == KEYDOWN:
if event.key == pygame.K_w:
keys[0] = True
elif event.key == pygame.K_a:
keys[1] = True
elif event.key == pygame.K_s:
keys[2] = True
elif event.key == pygame.K_d:
keys[3] = True
if titlescreen.clicked == True:
scene = "game"
if scene == "game":
screen.fill(black)
for grids in grid:
grids.draw()
for grids in grid:
grids.camera()
pygame.display.flip()
I am currently making a top down racing game and need a way to detect when a vehicle has completed a full lap. I have chosen to do this by adding images around the circuit, acting as checkpoints, which match with the track surface. When driven over, they output true, all must have output true in order for a lap to count. However, I cannot find a way to detect a collision between my vehicles and an image.
I have tried adding rects to the vehicles and checking if an output can be produced when the two vehicles collide but I just get this error:
AttributeError: 'pygame.Surface' object has no attribute 'rect'
Is there any way I can do this? My code can be seen below.
import pygame
from pygame.locals import *
import math
import time
pygame.init()
F1image = pygame.image.load("F1image.png")
sportsimage = pygame.image.load("sportsimage.png")
bikeimage = pygame.image.load("bikeimage.png")
muscleimage = pygame.image.load("muscleimage.png")
truckimage = pygame.image.load("truckimage.png")
screen = pygame.display.set_mode((1280,720))
xpos = 280
xpos_2 = 280
ypos = 50
ypos_2 = 85
keys = [False, False, False, False]
keys_2 = [False, False, False, False]
direction = 0
direction_2 = 0
forward = 0
forward_2 = 0
class Background(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
BackGround = Background('track.png', [0,0])
class Vehicle:
'Base class for all vehicles (Cars and Motorbikes) in the game'
vehicleCount = 0
def __init__(self, max_speed, acceleration, turning_radius, image):
pygame.sprite.Sprite.__init__(self)
self.max_speed = max_speed
self.acceleration = acceleration
self.turning_radius = turning_radius
self.image = image
self.rect = self.image.get_rect()
Vehicle.vehicleCount = Vehicle.vehicleCount + 1
def displayAmount():
print ("Total number of Vehicle enteries: ", Vehicle.vehicleCount)
def displayVehicle(self):
print ("max speed: ", self.max_speed, "acceleration: ", self.acceleration, "turning radius: ", self.turning_radius)
def checkCollision(self, sprite1, sprite2):
col = pygame.sprite.collide_rect(sprite1, sprite2)
if col == True:
print ("True")
F1 = Vehicle(5.0, 0.1, 2.84, F1image)
sportscar = Vehicle(4.5, 0.2, 2.01, sportsimage)
bike = Vehicle(4.0, 0.15, 2.64, bikeimage)
musclecar = Vehicle(3.5, 0.25, 1.76, muscleimage)
truck = Vehicle(3.0, 0.3, 1.20, truckimage)
print (F1.max_speed)
player1choice = input("Input player 1 choice").lower()
player2choice = input("Input player 2 choice").lower()
if player1choice == ("f1"):
choice1 = F1
elif player1choice == ("sports"):
choice1 = sportscar
elif player1choice == ("muscle"):
choice1 = musclecar
elif player1choice == ("truck"):
choice1 = truck
else:
choice1 = bike
if player2choice == ("f1"):
choice2 = F1
elif player2choice == ("sports"):
choice2 = sportscar
elif player2choice == ("muscle"):
choice2 = musclecar
elif player2choice == ("truck"):
choice2 = truck
else:
choice2 = bike
running = True
while running:
pygame.display.set_caption("Speed Wars")
WHITE = (255, 255, 255)
screen.fill(WHITE)
screen.blit(BackGround.image, BackGround.rect)
#Vehicle 1
if keys[0] == True:
direction += (choice1).turning_radius
if keys[1] == True:
direction -= (choice1).turning_radius
if keys[2] == True and forward <= (choice1).max_speed:
forward += (choice1).acceleration
if keys[3] == True and forward >= 0:
forward -= (choice1).acceleration
#Vehicle 2
if keys_2[0] == True:
direction_2 += (choice2).turning_radius
if keys_2[1] == True:
direction_2 -= (choice2).turning_radius
if keys_2[2] == True and forward_2 <= (choice2).max_speed:
forward_2 += (choice2).acceleration
if keys_2[3] == True and forward_2 >= 0:
forward_2 -= (choice2).acceleration
movex = math.cos(direction / 57.29) * forward
movey = math.sin(direction / 57.29) * forward
xpos += movex
ypos -= movey
movex_2 = math.cos(direction_2 / 57.29) * forward_2
movey_2 = math.sin(direction_2 / 57.29) * forward_2
xpos_2 += movex_2
ypos_2 -= movey_2
rotation = pygame.transform.rotate((choice1).image, direction)
rotation_2 = pygame.transform.rotate((choice2).image, direction_2)
screen.blit(rotation, (xpos, ypos))
screen.blit(rotation_2, (xpos_2, ypos_2))
pygame.display.flip()
time.sleep(0.01)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
if event.type == pygame.KEYDOWN:
if event.key == K_LEFT:
keys[0] = True
elif event.key == K_RIGHT:
keys[1] = True
elif event.key == K_UP:
keys[2] = True
elif event.key == K_DOWN:
keys[3] = True
if event.key == K_a:
keys_2[0] = True
elif event.key == K_d:
keys_2[1] = True
elif event.key == K_w:
keys_2[2] = True
elif event.key == K_s:
keys_2[3] = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
keys[0] = False
elif event.key == pygame.K_RIGHT:
keys[1] = False
elif event.key == pygame.K_UP:
keys[2] = False
elif event.key == pygame.K_DOWN:
keys[3] = False
if event.key == pygame.K_a:
keys_2[0] = False
elif event.key == pygame.K_d:
keys_2[1] = False
elif event.key == pygame.K_w:
keys_2[2] = False
elif event.key == pygame.K_s:
keys_2[3] = False
#Collision detection
(choice1).checkCollision((choice2).image, (choice1).image)
The issue is that your code passes in two images into the checkCollision method in your Vehicle class. Then you are passing these two images into the collide_rect function which expects two Sprites.
As a result, you get an error telling you that the two objects passed in(Surfaces in this case), do not contain rects.
To fix this problem:
Use the superclass Sprite for your Vehicle class.
Simply pass in the other sprite into the checkCollision method.
As a result, your checkCollision function should look something like this:
def checkCollision(self, sprite2):
col = pygame.sprite.collide_rect(self, sprite2)
if col == True:
print ("True")
And the call to it should look something like this:
choice1.checkCollision(choice2)
Also, your Vehicle class header should look like this:
class Vehicle(pygame.sprite.Sprite)
Some other issues in your code that should be fixed:
You are receiving input from the keyboard. This is very weird in a game. Instead, you should look at handling this through keyboard input.
You use brackets around choice1 and choice2. This is not needed.
There is code in your main game loop that doesn't need to be ran every frame such as pygame.display.set_caption(). This again is not needed and code like this should go before the main game loop.
The order of you main game loop is different to how it is normally done. First, you should do event handling. Second, do your logic and lastly, do your rendering.
Also, you are making 5 objects and loading many images where only two will be used. Instead, create and load the objects that will be used in the game after the user has decided which car they will play as.
Never use time.sleep() inside a pygame script. This function is evil when used with pygame and causes many errors and bugs. If you would like to use a framerate cap then use a Clock.
I highly recommend you follow these items.
I hope this answer helped you and if you have any further questions please feel free to post a comment below!
To implement checkpoints in a game I would use a solution similar to this: Define a list, group, etc. which contains your checkpoints and set the start point and the active point to the first checkpoint in the list. You can use an itertools.cycle iterator to easily cycle through the points. When the player touches a checkpoint, you set the active_checkpoint to the next point in the iterator and check if it was the start point, if yes, increment your laps counter.
If you want pixel-perfect collision detection, you can give the sprites a self.mask attribute and use pygame.sprite.collide_mask.
Here's a simplified example. I just swap out the images of the sprites here to show which one is active.
import itertools
import pygame as pg
CHECKPOINT_IMG = pg.Surface((120, 20), pg.SRCALPHA)
CHECKPOINT_IMG.fill((120, 60, 0))
CHECKPOINT2_IMG = pg.Surface((120, 20), pg.SRCALPHA)
CHECKPOINT2_IMG.fill((220, 110, 0))
class Player(pg.sprite.Sprite):
def __init__(self, pos, checkpoints):
super().__init__()
self.image = pg.Surface((60, 60), pg.SRCALPHA)
pg.draw.polygon(self.image, (0, 100, 240), [(30, 0), (60, 60), (0, 60)])
self.rect = self.image.get_rect(center=pos)
self.mask = pg.mask.from_surface(self.image)
self.checkpoints = itertools.cycle(checkpoints)
self.active_checkpoint = next(self.checkpoints)
self.start_point = self.active_checkpoint
self.active_checkpoint.image = self.active_checkpoint.image_active
self.laps = -1 # I start at -1 because the start is the first checkpoint.
def handle_event(self, event):
if event.type == pg.MOUSEMOTION:
self.rect.center = event.pos
if pg.sprite.collide_mask(self, self.active_checkpoint):
if self.active_checkpoint == self.start_point: # Completed a round.
self.laps += 1
pg.display.set_caption('Laps: {}'.format(self.laps))
# I change the images of the previous and next checkpoint
# to show which one is active.
self.active_checkpoint.image = self.active_checkpoint.image_inactive
# Switch to the next checkpoint.
self.active_checkpoint = next(self.checkpoints)
self.active_checkpoint.image = self.active_checkpoint.image_active
class Checkpoint(pg.sprite.Sprite):
def __init__(self, pos, angle=0):
super().__init__()
self.image_inactive = pg.transform.rotate(CHECKPOINT_IMG, angle)
self.image_active = pg.transform.rotate(CHECKPOINT2_IMG, angle)
self.image = self.image_inactive
self.rect = self.image.get_rect(center=pos)
self.mask = pg.mask.from_surface(self.image)
class Game:
def __init__(self):
self.screen = pg.display.set_mode((640, 480))
self.done = False
self.clock = pg.time.Clock()
self.checkpoints = (
Checkpoint((100, 200), 0),
Checkpoint((300, 100), 60),
Checkpoint((500, 300), 10),
Checkpoint((200, 300), 30),
)
self.player = Player((20, 20), self.checkpoints)
self.all_sprites = pg.sprite.Group(self.player)
self.all_sprites.add(self.checkpoints)
def run(self):
while not self.done:
self.event_loop()
self.update()
self.draw()
pg.display.flip()
self.clock.tick(60)
def event_loop(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.done = True
self.player.handle_event(event)
def update(self):
pass
def draw(self):
self.screen.fill((30, 30, 30))
self.all_sprites.draw(self.screen)
if __name__ == '__main__':
pg.init()
game = Game()
game.run()
pg.quit()
I just started learning Pygame and I'm doing a little game (school project), where using mouse I can click on the image and drag it. There are a lot of images, so my question is how I can identify what image is chosen. Thank you!
Here are some code:
def Transformation(element):
element = pygame.transform.scale(element,(50,75))
fire = pygame.image.load("ElementIcon/fire.png").convert_alpha()
Transformation(fire)
fire.set_colorkey(BLACK)
fire_rect = fire.get_rect()
earth = pygame.image.load("ElementIcon/earth.png").convert_alpha()
Transformation(earth)
earth.set_colorkey(BLACK)
earth_rect = earth.get_rect()
while not done:
screen.fill(WHITE)
#Update the screen with drawings
screen.blit(fire,(408,450))
screen.blit(earth,(419, 350))
mouse_pos = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
print("User quits the game :(")
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
done = True
print("Game stopped early by user :( ")
if event.type == pygame.MOUSEBUTTONDOWN:
print mouse_pos
print fire_rect
if fire_rect.collidepoint(mouse_pos):
print "over fire"
if earth_rect.collidepoint(mouse_pos):
print "mama"
When I try to print fire_rect I get <0,0,62,75>
Have a play with this code:
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((600,600))
clock = pygame.time.Clock()
FPS = 60
class MovableImage(pygame.Surface):
def __init__(self, image, xpos=0, ypos=0):
self.image = image
self.xpos = xpos
self.ypos = ypos
self.width = image.get_width()
self.height = image.get_height()
self.selected = False
self.rect = pygame.Rect(xpos, ypos, image.get_width(), image.get_height())
def move(self, move):
self.xpos += move[0]
self.ypos += move[1]
self.rect = pygame.Rect(self.xpos, self.ypos, self.width, self.height)
def Transformation(element):
element = pygame.transform.scale(element,(50,75))
def init():
global ImageList
fire = pygame.Surface((50,50))
fire.fill((255,0,0))
#fire = pygame.image.load("ElementIcon/fire.png").convert_alpha()
#Transformation(fire)
#fire.set_colorkey(BLACK)
#fire_rect = fire.get_rect()
earth = pygame.Surface((50,50))
earth.fill((255,255,0))
#earth = pygame.image.load("ElementIcon/earth.png").convert_alpha()
#Transformation(earth)
#earth.set_colorkey(BLACK)
#earth_rect = earth.get_rect()
fire_obj = MovableImage(fire, 408, 450)
earth_obj = MovableImage(earth, 419,350)
ImageList =[]
ImageList.append(fire_obj)
ImageList.append(earth_obj)
def run():
global done
done = False
while not done:
check_events()
update()
clock.tick(60)
def check_events():
global done
global ImageList
mouse_pos = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
print("User quits the game :(")
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
done = True
print("Game stopped early by user :( ")
if event.type == pygame.MOUSEBUTTONDOWN:
for im in ImageList:
if im.rect.collidepoint(mouse_pos):
im.selected = not im.selected
if event.type == pygame.MOUSEBUTTONUP:
for im in ImageList:
if im.rect.collidepoint(mouse_pos):
im.selected = False
if event.type == pygame.MOUSEMOTION:
for im in ImageList:
if im.rect.collidepoint(mouse_pos) and im.selected:
xmv = event.rel[0]
ymv = event.rel[1]
if event.buttons[0]:
if xmv < 0:
if im.xpos > 0:
im.move((xmv,0))
elif event.rel[0] > 0:
if im.xpos < screen.get_width():
im.move((xmv,0))
elif event.rel[1] < 0:
if im.ypos > 0:
im.move((0,ymv))
elif event.rel[1] > 0:
if im.ypos < screen.get_height():
im.move((0,ymv))
def update():
global ImageList
screen.fill((255, 255, 255)) #WHITE)
#Update the screen with drawings
for im in ImageList:
screen.blit(im.image, (im.xpos, im.ypos))
pygame.display.update()
if __name__=="__main__":
init()
run()
You can get the mouse pos and the image rect and check for collision:
pos = pygame.mouse.get_pos()
if image.rect.collidepoint(pos)
# move it
If you want to move the image with the mouse you can get the relative x/y movement with pygame.mouse.get_rel() and use that to change the image location.