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. :)
Related
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
import pygame
import time
# WINDOW SETUP
window = pygame.display.set_mode((900, 500))
pygame.display.set_caption("Pong")
time.sleep(5)
FPS = 60
# RGB VALUE VARIABLES
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
def background(window):
window.fill(WHITE)
pygame.display.update()
# FRAMERATE AND EVENT LOOP INITIALIZATION
def main():
run = True
clock = pygame.time.Clock()
while run:
clock.tick(FPS)
background(window)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if running == False:
pygame.quit()
Above, is my code. I'm trying to make a pong game with pygame. The text editor I am coding with is Visual Studios Code (VSCODE).
Firstly, you need to call the main. You should also make you're code nice and easy to read when possible. I imported pygame as pg which makes typing pygame functions a bit faster as you have less to type. Also, it's better to use global variables to hold variables that won't change through the program, like screen width, height, colours, etc. Then make sure you initialise the module.
As well as that, the only update you have is in background(). You should put the update at the bottom of the loop and remove it from background(). This way everything above will update each loop.
I apologise for not adding you're FPS counter in here as well but I think this should be enough to help you get you're window running with more readable code and a more efficient loop.
import pygame as pg
# Global Variables
screen_width = 900
screen_height = 500
screen = pg.display
window = screen.set_mode((screen_width, screen_height))
colour = 'red'
def main():
# Initialise module
pg.init()
pg.display.set_caption('PONG')
running = True
while running:
# This is a better way of writing your loop
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
# Call background function
background()
# Updates window
# place this inside the loop near the bottom
# so everything is updated at the end of each loop
screen.flip()
def background():
window.fill(colour)
# Remember to call your main function
# This if statement is good practise but not required
# You can just place main() here
if __name__ == '__main__':
main()
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)
When I use the player method, it gives me am error:
TypeError: 'pygame.Surface' object is not callable".
However, I don't have any problems when I use the same thing but then without using the method (see the row above). I don't know why. I am a newbie and could use some help.
Here is the whole code:
import pygame
from pygame.locals import *
from sys import exit
class Plane(object):
def __init__(self,screen_temp):
self.image = pygame.image.load('resources/image/shoot.png')
self.rect = pygame.Rect(0,99,102,126)
self.player = self.image.subsurface(self.rect)
self.player_pos = [200,600]
self.screen = screen_temp
def player(self):
self.screen.blit(self.player,self.player_pos)
def key_press(self):
key_press = pygame.key.get_pressed()
if key_press[K_UP]:
self.player_pos[1]-=5
if key_press[K_DOWN]:
self.player_pos[1]+=5
if key_press[K_LEFT]:
self.player_pos[0]-=5
if key_press[K_RIGHT]:
self.player_pos[0]+=5
def main():
screen = pygame.display.set_mode((480,800))
pygame.display.set_caption("飞机大战")
background = pygame.image.load('resources/image/background.png')
plane = Plane(screen)
while True:
screen.blit(background,(0,0))
#plane.screen.blit(plane.player,plane.player_pos) this can work
plane.player() # this will get a TypeError
pygame.display.update()
plane.key_press()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if __name__ == "__main__":
main()
You are defining Plane.player twice:
as a attribute self.player = self.image.subsurface(self.rect)
as a method def player(self):
Those two are colliding and can be fixed by renaming one of them.
Now below what i did is simply created a sprite as shown..
futher to do something interesting,thought of threading i added a thread which will check the cursor position, hence update global x & y resulting in change of sprite position that is trigered by display.update
I am newbie so i might me wrong in many ways ...so please bear me....
a lot thanks in advance
from pygame import *
from main import *
import threading
import sys
#lets add our sprites
(x,y) = (0, 0)
class threading1(threading.Thread):
def run(self):
global x,y
clockobj1 = pygame.time.Clock()
while (True):
clockobj1.tick(6)
(x,y)=pygame.mouse.get_pos()
display.update()
class sprites(pygame.sprite.Sprite ):
def __init__(self,color= redd, width=120, height=120):
super(sprites,self).__init__()
self.image = pygame.Surface((width,height))
self.image.fill(color)
self.rect=self.image.get_rect()
self.rect.move_ip(x,y)
display.update()
if __name__ == '__main__':
clockobj = pygame.time.Clock()
init()
mainwin = pygame.display.set_mode((720,640))
sprite1 = sprites()
spritegrp = pygame.sprite.Group()
spritegrp.add(sprite1)
spritegrp.update()
mainwin.fill(blue)
spritegrp.draw(mainwin)
threadingobj = threading1()
threadingobj.start()
x = True
while(x):
display.update()
for evt in event.get() :
if (evt.type == QUIT) :
quit()
x=False
clockobj.tick(40)
***BELOW IS MY LATEST CODE----------UPDATED AS PER ANSWERS***PLEASE CHECK
import pygame
from main import *
import threading
import sys
# lets add our sprites
class Sprites(pygame.sprite.Sprite ):
def __init__(self, color=redd, width=120, height=120):
super().__init__()
self.image = pygame.Surface((width, height))
self.image.fill(color)
self.rect = self.image.get_rect()
def updaterect(self):
print("i m in updatereact")
print(pygame.mouse.get_pos())
self.rect.center= pygame.mouse.get_pos()
pygame.display.update()
if __name__ == '__main__':
clockobj = pygame.time.Clock()
pygame.init()
mainwin = pygame.display.set_mode((720,640))
sprite1 = Sprites()
sprite1.updaterect()
spritegrp = pygame.sprite.Group()
spritegrp.add(sprite1)
spritegrp.update()
mainwin.fill(blue)
spritegrp.draw(mainwin)
x = True
while x:
sprite1.updaterect()
pygame.display.update()
for evt in pygame.event.get() :
if evt.type == pygame.QUIT :
quit()
x=False
Threading will only just complicate things. Get rid of it, and take self.rect.move_ip(x,y) and display.update() out of the __init__ for the class. Make a function in the class called update(). This function will move the rect just by saying. self.rect.center = pygame.mouse.get_pos(). Then in the main game loop, put sprite1.update() in there or update it by using the group name instead (as you did with spritegrp.update() ) and then call display.update() there too instead of in the function.
Other things:
super().__init__() doesn't need any args
if and while loops don't need parentheses
you don't need to import main (I may be wrong about this but I don't think so)
from module import * is a bad practice in general, but if you are going to do it (I don't recommend it), you can't put module.method anywhere. You did from pygame import *, but still put pygame.mouse and others like that. Maybe you meant from pygame.locals import * ?
colons don't have a space in between them and the word, i.e. for evt in event.get() : is bad
Indentation should also be the length of a tab, or four spaces. (What IDE are you using? Most do it automatically.)
variables assignments should have spaces: x = False