I recently started exploring classes and I have made my first class (sort of) but it doesn't seem to be working. I have code creating the class and function, then takes the values and blits an image to certain coordinates. for some reason It takes the values from inside the class instead of what I told it to have. I am new to classes so I'm not sure what to do, please help, thanks!
import pygame
pygame.init()
Screen = pygame.display.set_mode((800, 400))
TC = pygame.image.load("TC.png").convert_alpha()
ANUM = 0
class MTC() :
def __init__(self,) :
self.Tx = 0
self.Ty = 0
Screen.blit(TC,(self.Tx,self.Ty))
TMTC = MTC()
TMTC.Tx = 800
TMTC.Ty = 800
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
pygame.display.update()
The image is blit in the constructor. At this point the coordinates are not yet changed. You have add a method that blits the object:
class MTC() :
def __init__(self,) :
self.Tx = 0
self.Ty = 0
def dra():
Screen.blit(TC,(self.Tx,self.Ty))
Call the draw method in the application loop:
TMTC = MTC()
TMTC.Tx = 800
TMTC.Ty = 800
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
Screen.fill((0, 0, 0))
TMTC.draw()
pygame.display.update()
You are calling Screen.blit in the class constructor which is executed when your class is instantiated (TMTC = MTC()).
You are then setting the tx and ty after Screen.blit has already run
Related
So I'm trying to implement a class for a basic game. It woked without the class but now instead of spawning the "coin" it pops up and then immediatly dissapears. No idea as it's in the main loop. I have a moving "player" that works fine.
Here's my code:
class Coin_Class:
def __init__(self):
coin_1 = pygame.Rect(425, 30, 40, 40)
pygame.draw.rect(WIN, YELLOW, coin_1)
pygame.display.update()
# def coin_collect():
# if player.colliderect():
# coin_1.x = random.randint(0, 800)
# coin_1.y = random.randint(0, 250)
# pygame.event.post(pygame.event.Event(coin_collected))
# global score
# score += 1
# print(score)
coin_class = Coin_Class()
# main function loop
def main():
score_check = 0
clock = pygame.time.Clock()
run = True
while run:
# game speed
clock.tick(FPS)
# initialise pygame
pygame.init()
# checking all the events in pygame and looping them
for event in pygame.event.get():
# checking quit function is pressed
if event.type == pygame.QUIT:
run = False
pygame.quit()
exit()
keys_pressed = pygame.key.get_pressed() # recognise key presses
player_movement(keys_pressed, player) # movement function
draw_window() # create window function
coin_class
main()
# runs the main file
if __name__ == "__main__":
main()
Add a draw method to the coin class (also class names per PEP 8 should be in CapitalCase not Capital_Snake_Case so CoinClass):
class Coin_Class:
def __init__(self):
self.coin_1 = pygame.Rect(425, 30, 40, 40)
...
def draw(self):
pygame.draw.rect(WIN, YELLOW, self.coin_1)
And in the loop instead of using
coin_class
you would now use
coin_class.draw()
The rest can stay the same, except remove pygame.init() from the loop and put it somewhere at the start of the code after imports
I wanted to have a marker icon appear at the position of the cursor and stay there, but I have been running through the issue of the marker icon always following the position of the cursor and disappearing when the Z key is not pressed down
Since I already know that the issue is that the pin and cursor position is updating with every frame, I wanted to ask how I can make the marker icon static, so that it would be placed in that one location and wouldn't move around with the cursor.
Here is my code for marker placement:
def drop_mark(self, screen, cursorx, cursory):
Mark = pygame.image.load("Pin.Png").convert_alpha()
if pygame.key.get_pressed()[pygame.K_z]:
markx = cursorx
marky = cursory
screen.blit(Mark, (markx, marky))
And Here is the use of the function in the code:
def main():
screen = pygame.display.set_mode((848, 480))
clock = pygame.time.Clock()
CursorSprite = pygame.image.load("WorldMapReticle.png").convert_alpha()
WorldMapCursor = cursor(CursorSprite, 0, 0)
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
createScreen(screen)
WorldMapCursor.render(screen)
WorldMapCursor.move_right()
WorldMapCursor.move_left()
WorldMapCursor.move_down()
WorldMapCursor.move_up()
WorldMapCursor.drop_mark(screen, WorldMapCursor.x, WorldMapCursor.y)
pygame.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()
The problem is that you are defining markx and marky in the function, all you need to do is define them out of the function. Then update those variables once. Personally, i wouldn't put the if pygame.key.get_pressed()[pygame.K_z]: in the function but to do it this way i would do the following:
markx = 0
marky = 0
updated = false
def drop_mark(self, screen, cursorx, cursory):
global markx, marky, updated
Mark = pygame.image.load("Pin.Png").convert_alpha()
if pygame.key.get_pressed()[pygame.K_z]:
if updated == False:
markx = cursorx
marky = cursory
updated = True
screen.blit(Mark, (markx, marky))
WorldMapCursor is an instance of the class cursor. You don't need the cursorx and cursory argument at all, because WorldMapCursor has the attributes x and y and you can access them by self.x and self.y in any instance method:
(See Method Objects,
Instance Objects and instance attribute)
def drop_mark(self, screen):
Mark = pygame.image.load("Pin.Png").convert_alpha()
screen.blit(Mark, (self.x, self.y))
Move the cursor when Z is pressed:
WorldMapCursor = cursor(CursorSprite, 0, 0)
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
createScreen(screen)
WorldMapCursor.render(screen)
if pygame.key.get_pressed()[pygame.K_z]:
WorldMapCursor.move_right()
WorldMapCursor.move_left()
WorldMapCursor.move_down()
WorldMapCursor.move_up()
WorldMapCursor.drop_mark(screen)
pygame.display.flip()
clock.tick(60)
I want to draw a box to my screen, however when I call the function to do so it says I'm missing the argument for "surface"
As seen in the code below, the function is in a class. The function contains two parameters: "self" and "surface", and I'm passing the variable "screen" in place of "surface" so I can draw the box:
import pygame
import time
pygame.init()
(width, height) = (600, 400)
bg_colour = (100, 20, 156)
class infoBox(object):
def __init__(self, surface):
self.box = pygame.draw.rect(surface, (255,255,255),(0,400,400,100),2)
def draw(self, surface):
surface.blit(self.box)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("battle EduGame")
clock = pygame.time.Clock()
pygame.display.flip()
gameRun = True
while gameRun:
event = pygame.event.poll()
if event.type == pygame.QUIT: #if the "x" is pressed
pygame.quit() #quit game
gameRun = False #break the loop.
quit()
screen.fill(bg_colour)
infoBox.draw(screen)
pygame.display.update()
clock.tick(60)
I've done things exactly like this in previous codes however it's choosing not to work here.
Note your calling technique:
class infoBox(object):
def draw(self, surface):
surface.blit(self.box)
...
infoBox.draw(screen)
draw is an instance method, but you've invoked it as a class method. Therefore, you have only one argument, screen. You haven't provided the required self instance ... which will be needed immediately.
You need to create the object and use that to invoke the routine, something like
game_box = InfoBox(screen)
...
game_box.draw(screen)
I'm making a basic game where I have a surface and everytime I click on the surface it moves 5 pixels to the right. The program is working just fine without the checkCollide(event) function, but when I put the that condition it doesn't move. What is wrong?
My code until now is this
import pygame, sys
from pygame.locals import *
pygame.init()
DISPLAYSURF = pygame.display.set_mode((300,300))
def checkCollide(event):
k = 0
a,b = event.pos
x = P1[0].get_rect()
if x.collidepoint(a,b):
return True
return False
CP1 = [(150, 150)
,(155, 150)
,(160, 150)
,(165, 150)
,(170, 150)
,(175, 150)
,(180, 150)
,(185, 150)
,(190, 150)]
statp1_1 = 0
WHITE = (255,255,255)
DISPLAYSURF.fill(WHITE)
while True: # the main game loop
P1 = [pygame.image.load('PAzul.png'),CP1[statp1_1],statp1_1]
DISPLAYSURF.blit(P1[0], P1[1])
e = pygame.event.get()
for event in e:
if event.type == MOUSEBUTTONUP:
a = checkCollide(event)
if a:
DISPLAYSURF.fill(WHITE)
statp1_1 +=1
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
Thank you
Check your logic in these lines of your function:
x = P1[0][0].get_rect()
if x.collidepoint(a,b):
return True
return False
Your code hinges on this bit:
a = checkCollide(event)
if a:
DISPLAYSURF.fill(WHITE)
So you're never evaluating this piece to be true.
I just realized what was wrong. When I do x = P1[0].get_rect() it creates a surface with topleft at (0,0).
What I needed to do was change the position of the rectangle using x.topleft = P1[1]
I've got some tips for you. First store the rect in the P1 list (it contains only the image and the rect in the following example, but maybe you could also add the statp1_1 index to it). Now we can just move this rect, if the user clicks on it (in the example I set the topleft attribute to the next point). Read the comments for some more tips. One thing you need to fix is to prevent the game from crashing when the statp1_1 index gets too big.
import sys
import pygame
pygame.init()
DISPLAYSURF = pygame.display.set_mode((300, 300))
WHITE = (255, 255, 255)
# Don't load images in your while loop, otherwise they have to
# be loaded again and again from your hard drive.
# Also, convert loaded images to improve the performance.
P1_IMAGE = pygame.image.load('PAzul.png').convert() # or .convert_alpha()
# Look up `list comprehension` if you don't know what this is.
CP1 = [(150+x, 150) for x in range(0, 41, 5)]
statp1_1 = 0
# Now P1 just contains the image and the rect which stores the position.
P1 = [P1_IMAGE, P1_IMAGE.get_rect(topleft=CP1[statp1_1])]
clock = pygame.time.Clock() # Use this clock to limit the frame rate.
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONUP:
if P1[1].collidepoint(event.pos):
print('clicked')
statp1_1 += 1
# Set the rect.topleft attribute to CP1[statp1_1].
P1[1].topleft = CP1[statp1_1]
DISPLAYSURF.fill(WHITE)
DISPLAYSURF.blit(P1[0], P1[1]) # Blit image at rect.topleft.
pygame.display.update()
clock.tick(30) # Limit frame rate to 30 fps.
hello im new to python/pygame and tried to make a basic project. it did not turn out as planned as i don't understand this error if you can tell my why my image is not loading it will very much appreciated. Traceback (most recent call last):
File "C:\Users\Nicolas\Desktop\template\templat.py", line 15, in <module>
screen.fill(background_colour)
NameError: name 'background_colour' is not defined
this is the error i was speaking of however i have fixed now. how ever now the screen opens displayes the background and crashes.
import pygame, sys
pygame.init()
def game():
background_colour = (255,255,255)
(width, height) = (800, 600)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Tutorial 1')
pygame.display.set_icon(pygame.image.load('baller.jpg'))
background=pygame.image.load('path.png')
target = pygame.image.load('Player.png')
targetpos =target.get_rect()
screen.blit(target,targetpos)
screen.blit(background,(0,0))
pygame.display.update()
while True:
screen.blit(background,(0,0))
screen.blit(target,targetpos)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if__name__==('__main__')
game()
You missed the __init__ definition!
While your code does run, it is not what you want. There's an infinite loop inside the definition of the class, which means, however you are running this, there's something missing. You should put this code (most of it at least) inside the __init__ function, and then create an instance of the class.
This is what I assume you want:
import pygame, sys
class game():
width, height = 600,400
def __init__(self):
ball_filename = "Ball.png"
path_filename = "path.png"
self.screen = pygame.display.set_mode((self.width, self.height))
pygame.display.set_caption('Star catcher')
self.background = pygame.image.load(path_filename)
self.screen.blit(self.background,(0,0))
self.target = pygame.image.load(ball_filename)
def run(self):
while True:
self.screen.blit(self.background, (0,0))
targetpos = self.target.get_rect()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if __name__ == "__main__":
# To run this
pygame.init()
g = game()
g.run()
UPDATE:
I made more modifications than what you must do, but they could be useful. I did not test this, but it should be fine.
The error of width and height not being defined is because they are not local/global variables, but bound to the class and/or the instance of the class, therefore in their namespace. So you need to access these either via game.width (per class) or self.width (per instance, only inside a method defined in the class) or g.width (per instance, if you are outside the class definition and g is an instance of game class).
I hope I'm clear. :)