I have been trying to create movement for squares in pygame without controlling it, but I can't seem to do it. My goal was to make the red squares "bounce" the walls. I have cut out the collision in my game to prevent complications.
My code is:
import pygame
r=(255,0,0)
b=(0,0,255)
sort =(0,0,0)
class Block(pygame.sprite.Sprite):
def __init__(self, color=b, width= 40, height= 40):
super(Block, self).__init__()
self.image = pygame.Surface((width, height))
self.image.fill(color)
self.rect = self.image.get_rect()
self.origin_x=self.rect.centerx
self.origin_y=self.rect.centery
def set_position(self, x, y):
self.rect.x=x-self.origin_x
self.rect.y=y-self.origin_y
pygame.init()
pygame.display.set_caption("EsKappa!")
window_size =window_width, window_height = 400, 400
window = pygame.display.set_mode(window_size)
a=(0,201,0)
clock = pygame.time.Clock()
frames_per_second = 60
block_group = pygame.sprite.Group()
a_block= Block(b)
a_block.set_position(window_width/2 -30, window_height/2)
block1=Block()
block2=Block()
block3=Block()
block4=Block()
wall1 = Block(sort,20, 400 )
wall1.set_position(0,200)
wall2= Block(sort,400, 20 )
wall2.set_position(200,0)
wall3=Block(sort,20, 400 )
wall3.set_position(400,200)
wall4=Block(sort,400, 20 )
wall4.set_position(200,400)
block1= Block(r,50, 50 )#here draw
block1.set_position(80, 70)#here place
block2 = Block(r, 50, 40)
block2.set_position(270, 70)
block3 = Block(r,80, 20)
block3.set_position(280, 300)
block4 = Block(r, 30, 70)
block4.set_position(70, 250)
block_group.add(a_block,block1, block2, block3, block4, wall1,wall2,wall3,wall4)
h=pygame.time.get_ticks()/1000
font = pygame.font.SysFont("Times New Roman", 20)
font2 = pygame.font.SysFont("Times New Roman", 50)
text = font.render("Time", True, sort)
speed=[2,0] # here speed
#lukke funktion
running=True
while running:
event = pygame.event.wait ()
if event.type == pygame.QUIT or (event.type== pygame.KEYDOWN) and (event.key == pygame.K_ESCAPE): # Giver lukke funktion fra ikon og ESCAPE
running = False
if event.type == pygame.MOUSEMOTION :
mouse_position = pygame.mouse.get_pos()
a_block.set_position(mouse_position[0],mouse_position[1])
clock.tick(frames_per_second)
window.fill(a)
block1.move_ip(speed) #here error is here
screen.blit(block1) #here
pygame.display.update()
if targetpos[0]+target.get_width()>width or targetpos[0]<0: #here
speed[0]=-speed[0] #here
if pygame.sprite.collide_rect(a_block, block1) or pygame.sprite.collide_rect(a_block, block2) or pygame.sprite.collide_rect(a_block, block3) or pygame.sprite.collide_rect(a_block, block4)or pygame.sprite.collide_rect(a_block, wall1) or pygame.sprite.collide_rect(a_block, wall2) or pygame.sprite.collide_rect(a_block, wall3) or pygame.sprite.collide_rect(a_block, wall4):
time_string = "Du overlevede {} sekunder".format(pygame.time.get_ticks()/1000)
text = font.render(time_string, True, sort)
window.blit(text, (window_width/2-100, window_height/2-100))
if pygame.time.get_ticks()/1000>10:
time_string1 = "Flot!"
text = font2.render(time_string1, True, sort)
window.blit(text, (20, 20))
else:
time_string2 = "Ikke så godt :c"
text = font2.render(time_string2, True, sort)
window.blit(text, window.blit(text, (20, 20)))
pygame.display.update()
pygame.time.wait(5000)
running = False
block_group.draw(window)
pygame.display.update()#opdater skærmen
pygame.quit ()
And the error is:
Traceback (most recent call last):
File "C:\Python33\eskappa1.py", line 81, in <module>
block1.move_ip(speed) #here error is here
AttributeError: 'Block' object has no attribute 'move_ip'
Your Block subclasses Sprite, which per the documentation, doesn't have a move_ip method; this explains the error you are seeing.
I think what you need to do is move the Rect belonging to the Block, which does have that method. Try:
block1.rect.move_ip(speed)
Related
Why do bodies in pymunk keep colliding without actually touching each other even after the position and body shape is correctly set?
You will see from my code below that the bird keeps colliding with the ball without actually touching the ball.
import pygame, pymunk
pygame.init()
WIDTH, HEIGHT = 900, 500
win = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("Flappy OBJ")
color = (255,255,255)
win.fill(color)
fps = 120
fb_img = pygame.image.load("images/flappy-bird.png")#.convert()
fb_img = pygame.transform.rotate(pygame.transform.scale(fb_img, (30,20)), 0)
ball_img = pygame.image.load("images/ball.png")#.convert()
ball_img = pygame.transform.rotate(pygame.transform.scale(ball_img, (60,60)), 0)
def bird_body():
body = pymunk.Body(1, 100, body_type=pymunk.Body.DYNAMIC)
body.position = (50, 0)
shape = pymunk.Poly.create_box(body, (30,20))
space.add(body, shape)
return shape
def ball_body():
body = pymunk.Body(1, 100, body_type = pymunk.Body.KINEMATIC)
body.position = (500, 300)
body.velocity = (-25,0)
shape = pymunk.Circle(body, 60)
shape.color = (0,255,255, 128)
space.add(body, shape)
return shape
space = pymunk.Space()
space.gravity = (0, 20)
fb_body = bird_body()
b_body = ball_body()
def draw_window():
global scroll
win.fill(color)
space.step(0.03)
win.blit(ball_img, (b_body.body.position.x, b_body.body.position.y))
win.blit(fb_img, (fb_body.body.position.x, fb_body.body.position.y))
pygame.display.update()
def main():
w_was_down = True
clock = pygame.time.Clock()
run = True
while run:
clock.tick(fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_w]:
if not w_was_down:
fb_body.body.apply_impulse_at_local_point((0,-50))
w_was_down = True
else:
w_was_down = False
draw_window()
pygame.quit()
main()
Tap w to move the bird up. some more details some more details some more details
The 2nd argument of pymunk.Circle is the radius, but not the diameter:
shape = pymunk.Circle(body, 60)
shape = pymunk.Circle(body, 30)
And the position of the pymuk object is the center of the object:
win.blit(ball_img, (b_body.body.position.x, b_body.body.position.y))
win.blit(fb_img, (fb_body.body.position.x, fb_body.body.position.y))
win.blit(ball_img, (b_body.body.position.x-30, b_body.body.position.y-30))
win.blit(fb_img, (fb_body.body.position.x-15, fb_body.body.position.y-10))
This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Collision between masks in pygame
(1 answer)
Closed 1 year ago.
So, I'm making an app/game in python using pygame module, and my problem is that, I cannot find a way to check if a sprite is entirely touching another sprite or not.
What I mean is
if (sprite is touching anything else that some white rectangle):
do some code
Here is my messy code :
main.py :
import pygame, Classes, Groups, Images, random, time
pygame.init()
pygame.font.init()
# App Variables
run_bool = False
# Fonts
ARAL_20_ITALIC = pygame.font.SysFont('Arial' , 20, italic=True)
# Colors
BG = (30, 30, 30)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
# Window
size = (800, 600)
scr = pygame.display.set_mode(size)
pygame.display.set_caption('Simulation by Cold Fire (0.1)')
# App Loop
while True:
time.sleep(0.01)
# Graphics
scr.fill(BG)
"""TERRAIN"""
terrain_hitbox = pygame.draw.rect(scr, WHITE, (300, 100, size[0] - 350, size[1] - 150))
pygame.draw.rect(scr, BLACK, (300, 100, size[0] - 350, size[1] - 150), width=10)
"""SUBJECTS"""
for subject in Groups.G_Subject:
if run_bool == True:
subject.update__()
scr.blit(subject.img, subject.rect)
"""GUI"""
pygame.draw.line(scr, WHITE, (200, 0), (200, size[1]), width=3)
scr.blit(ARAL_20_ITALIC.render('Subjects' ,False, WHITE), (30, 10))
add_hitbox = scr.blit(Images.add_img.convert_alpha(), (30, 50))
remove_hitbox = scr.blit(Images.remove_img.convert_alpha(), (30, 90))
scr.blit(ARAL_20_ITALIC.render(f'Subjects: {len(Groups.G_Subject)}' , False, WHITE), (30, 130))
if run_bool == False:
run_hitbox = scr.blit(Images.run_img.convert_alpha(), (210, size[1] - 40))
else:
run_hitbox = scr.blit(Images.stop_img.convert_alpha(), (210, size[1] - 40))
# Updating Screen
pygame.display.flip()
# Events
for event in pygame.event.get():
# Quitting App
if event.type == pygame.QUIT:
pygame.quit()
quit()
# Clicking
if event.type == pygame.MOUSEBUTTONDOWN:
mouse = pygame.mouse.get_pos()
if add_hitbox.collidepoint(mouse[0], mouse[1]):
rand_x = random.randint(terrain_hitbox[0], terrain_hitbox[0] + terrain_hitbox[2])
rand_y = random.randint(terrain_hitbox[1], terrain_hitbox[1] + terrain_hitbox[3])
Classes.Subject(rand_x, rand_y, Images.subject0_img.convert_alpha())
if remove_hitbox.collidepoint(mouse[0], mouse[1]) and not 1 > len(Groups.G_Subject):
Groups.G_Subject.remove(random.choice(Groups.G_Subject.sprites()))
if run_hitbox.collidepoint(mouse[0], mouse[1]):
if run_bool == True:
run_bool = False
else:
run_bool = True
Classes.py :
import pygame, Groups, random, math
class Subject(pygame.sprite.Sprite):
def __init__(self, x, y, img=pygame.image.load('assets/img/subject0.png').convert_alpha(pygame.display.set_mode((800, 600))), speed=5):
super().__init__()
self.img = img
self.rect = self.img.get_rect()
self.rect.x = x
self.rect.y = y
self.oldx = self.rect.x
self.oldy = self.rect.y
self.speed = speed
Groups.G_Subject.add(self)
def calculat_new_xy(self, old_xy, speed, angle_in_radians):
new_x = old_xy.x + (speed * math.cos(angle_in_radians))
new_y = old_xy.y + (speed * math.sin(angle_in_radians))
return new_x, new_y
def update__(self):
self.oldx, self.oldy = self.rect.x, self.rect.y
self.rect.x, self.rect.y = self.calculat_new_xy(self.rect, self.speed, random.randint(1, 360))
Images.py :
import pygame
add_img = pygame.transform.scale(pygame.image.load('assets/img/gui/add.png'), (90, 30))
remove_img = pygame.transform.scale(pygame.image.load('assets/img/gui/remove.png'), (90, 30))
subject0_img = pygame.image.load('assets/img/subject0.png')
run_img = pygame.transform.scale(pygame.image.load('assets/img/gui/run.png'), (90, 30))
stop_img = pygame.transform.scale(pygame.image.load('assets/img/gui/stop.png'), (90, 30))
Groups.py :
import pygame
G_Subject = pygame.sprite.Group()
I do know my code is a mess, so if you don't wanna help, it's ok ! Thx in advance :D
I am attempting to add text to class instances of a rect.
I have been able to do this by setting the "font" variable outside of the class and putting the desired text in "font.render_to" within the draw funtion but this means the text will be the same for all buttons as it is set within the class.
I'd like to set different text for each button specified in the class instance (button1, button2, button3) as shown in the below code but im getting the following error:
Traceback (most recent call last):
File "path_to_file/test.py", line 30, in <module>
button1 = Button(10, 10, 100, 50, 'One')
File "path_to_file/test.py", line 23, in __init__
self.font = font.pygame.freetype.SysFont('Arial', 25)
AttributeError: 'str' object has no attribute 'pygame'.
Code:
import pygame
import sys
import pygame.freetype
pygame.display.init()
pygame.freetype.init()
width = 300
height = 350
bg = (255, 255, 255)
# Sets the window size
screen = pygame.display.set_mode((width, height))
# Sets the background colour to white
screen.fill(bg)
# Button class - All buttons are created using the below parameters
class Button:
def __init__(self, rect_x, rect_y, rect_width, rect_height, font):
self.rect_x = rect_x
self.rect_y = rect_y
self.rect_width = rect_width
self.rect_height = rect_height
self.font = font.pygame.freetype.SysFont('Arial', 25)
# Draw function - Creates the rectangle and adds text
def draw(self):
pygame.draw.rect(screen, (200, 200, 200), (self.rect_x, self.rect_y, self.rect_width, self.rect_height))
self.font.render_to(screen, (42, 25), self.font, bg)
# Class instances - Defines button size and location in the PyGame window
button1 = Button(10, 10, 100, 50, 'One')
button2 = Button(10, 70, 100, 50, 'Two')
button3 = Button(10, 130, 100, 50, 'Three')
# game loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
button1.draw()
button2.draw()
button3.draw()
pygame.display.update()
The 5th argument of the constructor is the text. You have to store the text in an attribute and render the text.
font.pygame.freetype.SysFont('Arial', 25) doesn't make any sense. The font object is constructed by pygame.freetype.SysFont('Arial', 25).
The target position of render_to depends on the position of the button:
class Button:
def __init__(self, rect_x, rect_y, rect_width, rect_height, text):
self.rect_x = rect_x
self.rect_y = rect_y
self.rect_width = rect_width
self.rect_height = rect_height
self.text = text
self.font = pygame.freetype.SysFont('Arial', 25)
def draw(self):
pygame.draw.rect(screen, (200, 200, 200),
(self.rect_x, self.rect_y, self.rect_width, self.rect_height))
self.font.render_to(screen, (self.rect_x + 42, self.rect_y + 25), self.text, bg)
Could someone, please, advise me on how to change a code so the screen text and coded button text stays until next click of the mouse button and not dissapear after releasing a mouse button?
For now when I click and hold the mouse button the screen text is changing, but the coded button is not updating. And also after I release the mouse button, text is coming back to the initial state.
I need the text (both on the screen and on the button) to change and stay updated on the screen forever or until mouse button is clicked again.
I made a function to blit the text on the screen and a class for drawing a button on the screen. And they both work. Maybe the problem is somewhere in the main logic with 'if' statements?
pygame.init()
# setting the window size and FPS
SIZE = WIDTH, HEIGHT = (640, 640)
FPS = 30
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()
bgcolor = (54, 54, 54)
# defining the function to draw text on the screen
def draw_text(surface, text, pos):
text_color = (255, 255, 255)
text_font = pygame.font.SysFont('Times New Roman', 24)
x, y = pos
word_surface = text_font.render(text, 1, text_color)
surface.blit(word_surface, (x, y))
# defining a class for buttons
class DrawButton():
def __init__(self, button_text, button_x, button_y):
self.button_text = button_text
self.button_x = button_x
self.button_y = button_y
self.button_color_passive = (89, 89, 89)
self.button_color_active = (212, 200, 235)
self.button_width = 400
self.button_height = 100
self.cur = pygame.mouse.get_pos()
self.click = pygame.mouse.get_pressed()
def text_to_button(self): # defining the method for drawing a text on buttons
bf_passive = pygame.font.SysFont('Times New Roman', 24)
bf_passive_rend = bf_passive.render(self.button_text, 1, self.button_color_active)
bf_passive_rect = bf_passive_rend.get_rect()
bf_active = pygame.font.SysFont('Times New Roman', 28)
bf_active_rend = bf_active.render(self.button_text, 1, self.button_color_passive)
bf_active_rect = bf_active_rend.get_rect()
if self.button_x + self.button_width > self.cur[0] > self.button_x \
and self.button_y + self.button_height > self.cur[1] > self.button_y:
bf_active_rect.center = (int(self.button_x + (self.button_width / 2)), int(self.button_y + (self.button_height / 2)))
screen.blit(bf_active_rend, bf_active_rect)
else:
bf_passive_rect.center = (int(self.button_x + (self.button_width / 2)), int(self.button_y + (self.button_height / 2)))
screen.blit(bf_passive_rend, bf_passive_rect)
def draw_button(self): # defining the method for drawing button rectangle
if self.button_x + self.button_width > self.cur[0] > self.button_x \
and self.button_y + self.button_height > self.cur[1] > self.button_y:
pygame.draw.rect(screen, self.button_color_passive, (self.button_x + 5, self.button_y + 5, self.button_width, self.button_height))
pygame.draw.rect(screen, self.button_color_active, (self.button_x, self.button_y, self.button_width, self.button_height))
if self.click[0] == 1:
pygame.draw.rect(screen, self.button_color_passive, (self.button_x, self.button_y, self.button_width, self.button_height))
else:
pygame.draw.rect(screen, self.button_color_passive, (self.button_x, self.button_y, self.button_width, self.button_height))
text1 = "Text 1"
text2 = "Text 2"
while True:
dt = clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
screen.fill(bgcolor)
text = text1
if text == text1:
button1 = DrawButton('Next', WIDTH - 435, HEIGHT - 150)
button1.draw_button()
button1.text_to_button()
if text == text1 and button1.click[0] == 1:
text = text2
button2 = DrawButton('Next again', WIDTH - 435, HEIGHT - 150)
button2.draw_button()
button2.text_to_button()
draw_text(screen, text, (40, 20))
pygame.display.update()```
You should use text = text1 before loop, not inside. And then it keep new text.
But bigger problem is
button1.click[0] == 1
which is True all time when you keep pressed button so it makes problem to change text from first to second and later from second to first because when you keep pressed button then it changes text again and again and again - and finally you can get the same text when you release mouse button (or you can see how text is changing all the time).
You should use event MOUSEBUTTONDOWN which is created only once - when you start pressing - but it is not created when you keep pressed.
text1 = "Text 1"
text2 = "Text 2"
text = text1
while True:
dt = clock.tick(FPS)
# --- events (without draws) ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if text == text1:
text = text2
else:
text = text1
# --- changes (without draws) ---
if text == text1:
button = DrawButton('Next', WIDTH-435, HEIGHT-150)
else:
button = DrawButton('Next again', WIDTH-435, HEIGHT-150)
# --- draws (without changes) ---
screen.fill(bgcolor)
button.draw_button()
button.text_to_button()
draw_text(screen, text, (40, 20))
pygame.display.update()
Full working code:
import pygame
# --- constants ---
# setting the window size and FPS
SIZE = WIDTH, HEIGHT = (640, 640)
FPS = 30
# --- classes ---
# defining a class for buttons
class DrawButton():
def __init__(self, button_text, button_x, button_y):
self.button_text = button_text
self.button_x = button_x
self.button_y = button_y
self.button_color_passive = (89, 89, 89)
self.button_color_active = (212, 200, 235)
self.button_width = 400
self.button_height = 100
self.cur = pygame.mouse.get_pos()
self.click = pygame.mouse.get_pressed()
def text_to_button(self): # defining the method for drawing a text on buttons
bf_passive = pygame.font.SysFont('Times New Roman', 24)
bf_passive_rend = bf_passive.render(self.button_text, 1, self.button_color_active)
bf_passive_rect = bf_passive_rend.get_rect()
bf_active = pygame.font.SysFont('Times New Roman', 28)
bf_active_rend = bf_active.render(self.button_text, 1, self.button_color_passive)
bf_active_rect = bf_active_rend.get_rect()
if self.button_x + self.button_width > self.cur[0] > self.button_x \
and self.button_y + self.button_height > self.cur[1] > self.button_y:
bf_active_rect.center = (int(self.button_x + (self.button_width / 2)), int(self.button_y + (self.button_height / 2)))
screen.blit(bf_active_rend, bf_active_rect)
else:
bf_passive_rect.center = (int(self.button_x + (self.button_width / 2)), int(self.button_y + (self.button_height / 2)))
screen.blit(bf_passive_rend, bf_passive_rect)
def draw_button(self): # defining the method for drawing button rectangle
if self.button_x + self.button_width > self.cur[0] > self.button_x \
and self.button_y + self.button_height > self.cur[1] > self.button_y:
pygame.draw.rect(screen, self.button_color_passive, (self.button_x + 5, self.button_y + 5, self.button_width, self.button_height))
pygame.draw.rect(screen, self.button_color_active, (self.button_x, self.button_y, self.button_width, self.button_height))
if self.click[0] == 1:
pygame.draw.rect(screen, self.button_color_passive, (self.button_x, self.button_y, self.button_width, self.button_height))
else:
pygame.draw.rect(screen, self.button_color_passive, (self.button_x, self.button_y, self.button_width, self.button_height))
# --- functions ---
# defining the function to draw text on the screen
def draw_text(surface, text, pos):
text_color = (255, 255, 255)
text_font = pygame.font.SysFont('Times New Roman', 24)
x, y = pos
word_surface = text_font.render(text, 1, text_color)
surface.blit(word_surface, (x, y))
# --- main ---
pygame.init()
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()
bgcolor = (54, 54, 54)
text1 = "Text 1"
text2 = "Text 2"
text = text1
while True:
dt = clock.tick(FPS)
# --- events (without draws) ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if text == text1:
text = text2
else:
text = text1
# --- changes (without draws) ---
if text == text1:
button = DrawButton('Next', WIDTH-435, HEIGHT-150)
else:
button = DrawButton('Next again', WIDTH-435, HEIGHT-150)
# --- draws (without changes) ---
screen.fill(bgcolor)
button.draw_button()
button.text_to_button()
draw_text(screen, text, (40, 20))
pygame.display.update()
BTW:
You could do many other changes - ie. use pygame.Rect to keep button size and position and later check rect.collidepoint(mouse.pos) to detect if mouse is over button. And use it to display it blit(screen, image, rect) or to center text on rect - text_rect = text_image.get_rect(center=button_rect.center), etc.
All my changes
import pygame
# --- constants ---
# setting the window size and FPS
SIZE = WIDTH, HEIGHT = (640, 640)
FPS = 30
# --- classes ---
# defining a class for buttons
class DrawButton():
def __init__(self, text, x, y, function=None):
'''Init all needed variables only once'''
self.rect = pygame.Rect(x, y, 400, 100)
self.text = text
self.function = function
self.shadow_rect = self.rect.copy()
self.shadow_rect.x += 5
self.shadow_rect.y += 5
self.color_passive = (89, 89, 89)
self.color_active = (212, 200, 235)
self.color_click = (0, 200, 0)
self.hovered = False
self.clicked = False
self.font_passive = pygame.font.SysFont('Times New Roman', 24)
self.font_active = pygame.font.SysFont('Times New Roman', 28)
self.render_text()
def render_text(self):
'''Render text but don't display it'''
self.passive_text = self.font_passive.render(self.text, 1, self.color_active)
self.passive_rect = self.passive_text.get_rect(center=self.rect.center)
self.active_text = self.font_active.render(self.text, 1, self.color_passive)
self.active_rect = self.active_text.get_rect(center=self.rect.center)
def handle_event(self, event):
'''Check all events and change variables - without drawing and rendering'''
if event.type == pygame.MOUSEMOTION:
self.hovered = self.rect.collidepoint(event.pos)
if event.type == pygame.MOUSEBUTTONDOWN:
if self.hovered:
self.clicked = True
#if self.function:
# self.function()
if event.type == pygame.MOUSEBUTTONUP:
if self.hovered:
self.clicked = False
# run function when button is released
if self.function:
self.function()
def draw(self, screen):
'''Draw rectangle and text but don't render text'''
if self.hovered:
# shadow
pygame.draw.rect(screen, self.color_passive, self.shadow_rect)
# rect
if self.clicked:
pygame.draw.rect(screen, self.color_click, self.rect)
else:
pygame.draw.rect(screen, self.color_active, self.rect)
# text
screen.blit(self.active_text, self.active_rect)
else:
# rect
pygame.draw.rect(screen, self.color_passive, self.rect)
# text
screen.blit(self.passive_text, self.passive_rect)
# --- functions ---
# defining the function to draw text on the screen
def draw_text(surface, text, pos):
color = (255, 255, 255)
font = pygame.font.SysFont('Times New Roman', 24)
image = font.render(text, 1, color)
surface.blit(image, pos)
def on_click_1():
global text
if text == text1:
text = text2
button1.text = 'Next again'
button1.render_text()
else:
text = text1
button1.text = 'Next'
button1.render_text()
def on_click_2():
global text
if text == "Hello":
text = "World"
else:
text = "Hello"
# --- main ---
pygame.init()
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()
bgcolor = (54, 54, 54)
text1 = "Text 1"
text2 = "Text 2"
text = text1
# create button only once and assign function which it has to execute when it is pressed
button1 = DrawButton('Next', WIDTH-435, HEIGHT-150, on_click_1)
button2 = DrawButton('Press', WIDTH-435, HEIGHT-350, on_click_2)
while True:
dt = clock.tick(FPS)
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
button1.handle_event(event)
button2.handle_event(event)
# --- changes (without draws) ---
# empty
# --- draws (without changes) ---
screen.fill(bgcolor)
button1.draw(screen)
button2.draw(screen)
draw_text(screen, text, (40, 20))
pygame.display.update()
I keep getting a Traceback error that says 'pygame.Surface' object is not callable.
Here's the script that I'm working on (it's mostly made by Meloonatic Melons but I'm a beginner trying to learn)
import pygame, sys, time
from Scripts.Textures import *
pygame.init()
cSec = 0
cFrame = 0
FPS = 0
tile_size = 32
FPS_font = pygame.font.Font("C:\\Windows\\Fonts\\Verdana.ttf", 20)
sky = pygame.image.load("Graphics\\Sky.png")
Sky = pygame.Surface(sky.get_size(), pygame.HWSURFACE)
Sky.blit(sky, (0, 0))
del sky
def showFPS():
fps_overlay = FPS_font.render(str(FPS), True, (104, 98, 7))
window.blit(fps_overlay, (0, 0))
def createWindow():
global window, window_width, window_height, window_title
window_width, window_height = 800, 600
window_title = "Mystic RPG"
pygame.display.set_caption(window_title)
window = pygame.display.set_mode((window_width, window_height), pygame.HWSURFACE|pygame.DOUBLEBUF)
def countFPS():
global cSec, cFrame, FPS
if cSec == time.strftime("%S"):
cFrame += 1
else:
FPS = cFrame
cFrame = 0
cSec = time.strftime("%S")
createWindow()
isRunning = True
while isRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
isRunning = False
countFPS()
window.blit(Sky (0, 0))
for x in range(0, 640, tile_size):
for y in range(0, 480, tile_size):
window.blit(Tiles.Grass, (x,y))
showFPS()
pygame.display.update()
pygame.quit()
sys.exit()
The error says
Traceback (most recent call last):
File "C:/Users/Zane/Desktop/Python RPG/Mystic RPG.py", line 52, in <module>
window.blit(Sky (0, 0))
TypeError: 'pygame.Surface' object is not callable
I am using Python 3.6.4
Anyone know whats going wrong and how I can fix it.
I am not familiar with this but in the showFPS() function, you wrote this:
Window.blit(fps_overlay, (0, 0))
While the error line, line 52, you write this:
window.blit(Sky (0, 0))
I believe you need a comma between the parameters.