I keep getting this error whilst loading my program global name 'load_jpeg' is not defined
when running my class code.
class Hero:
def __init__(self,x,y):
self.x=x
self.y=y
self.width=70
self.height=70
self.image = pygame.image.load('ezio.jpg')
self.rect = self.image.get_rect()
The fact that pygame.blit() did not work is very clear and same with load_jpeg. First, the load_jpeg error. Just like how Martijn Pieters said, you can't just create a function that Python did not originally have. Maybe you could have wrote a specific function with that name, but that is not the case. Second, the pygame.blit(). To use this function, you need two arguments inside of it. To be able to do that, you might want to change your class:
class Hero(pygame.sprite.Sprite):
def __init__(self, location, image_file):
pygame.sprite.Sprite.__init__(self)
self.rect.top, self.rect.left = location #The equivalent as self.x and self.y
self.width = 70
self.height = 70
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
And add this line (if you haven't done this already and outside your class and before your while loop):
Heroes = Hero([100, 100], 'ezio.jpg')
This creates an variable that can be used for the pygame.blit() function. It is usually more better to do self.rect.top, self.rect.left = location than defining self.x and self.y. It is usually more of a PyGame style with rects. It looks like you are going to __init__ this into a sprite and define self. After you have done this, pygame.blit() should work. Saying that the variable name of the class is x, you must always do it in this order:
pygame.blit(x.image, x.rect)
With x.image first, then x.rect after. In your case, that line should look like:
pygame.blit(Heroes.image, Heroes.rect) #Assuming the variable name is Heroes
This answer should cancel your error and make the pygame.blit() function working again. I hope this helps you!
Related
This is a the class of a sprite that goes left and right on the screen, when it hits the boundaries, it makes a "boing" sound and goes the opposite direction, everything works perfectly fine except for there is no boing sound when it hits the edge
class MySprite(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("vegetables.gif")
self.image = self.image.convert()
self.rect = self.image.get_rect()
self.rect.left = 0
self.rect.top = 167
self.__direction = 10
def update(self):
self.rect.left += self.__direction
sound = pygame.mixer.Sound("Bounce.mp3")
sound.set_volume(0.5)
if (self.rect.left < 0) or (self.rect.right > screen.get_width()):
sound.play()
self.__direction = -self.__direction
If you want the class to play its own sound, just load it like any attribute on __init__.
class MySprite(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("vegetables.gif")
self.image = self.image.convert()
self.sound = pygame.mixer.Sound("Bounce.mp3") #like this
self.rect = self.image.get_rect()
self.rect.left = 0
self.rect.top = 167
self.__direction = 10
Then whenever it's correct to do so, just call self.sound.play().
def update(self):
self.rect.left += self.__direction
if (self.rect.left < 0) or (self.rect.right > screen.get_width()):
self.sound.play() #as seen here
self.__direction = -self.__direction
For whatever it's worth - if you're going to do it in this way (have the sprite play its own sounds, etc), I would recommend loading them beforehand and then passing them as arguments (perhaps default arguments to avoid errors), such that each instance of the class might call a unique sound if need be.
So in your code prior to these classes, one could do something like:
JumpSound = pygame.Mixer.Sound("jump.wav")
BonkSound = pygame.Mixer.Sound("bonk.wav")
#etc etc etc...
...and then later on, pass the sounds as arguments:
class MySprite(pygame.sprite.Sprite):
def __init__(self, jumpsound, bonksound):
#...your other code precedes...
self.jumpsound = jumpsound
self.bonksound = bonksound
#...your other code continues...
myHero = MySprite(JumpSound, BonkSound)
The names are a little bit lousy b/c they are the same barring the CamelCasing, but forgetting that, this is probably a much cleaner approach. You can set your volume on the sounds way before they are passed into the sprites, along with whatever other changes you feel are necessary before the sprite gets ahold of them.
I'm trying to write a program where the image for the 'enemy' I have changes once its health goes to 0. I have different classes for each element, but I have this under this class.
class Enemy(pygame.sprite.Sprite):
def __init__(self, gs=None):
pygame.sprite.Sprite.__init__(self)
...initialization stuff...
self.image = pygame.image.load("enemy.png") #enemy image
self.rect = self.image.get_rectangle()
self.hp = 40 #initial health
def damage(self):
if self.rect.colliderect(self.user.rect): #collision/how the health goes down
self.hp = self.hp - 5
Now here's the part I'm curious about, I want to load a new image that replaces the old image I have for this enemy. Can I do/add (in the damage function)
if(self.hp == 0):
self.image = pygame.image.load("dead.png")
Will this replace it? Or just load another image on top of it?
Let me know what I'm missing, thank you!
You should load all your images into your init method when you create the object and then you can do the assigning/changing later using lists. Here is an example:
class Enemy(pygame.sprite.Sprite):
def __init__(self, gs=None):
pygame.sprite.Sprite.__init__(self)
self.images = [pygame.image.load("enemy.png"), pygame.image.load("dead.png")]
self.current_image = self.images[0]
self.rect = self.current_image.get_rectangle()
Then later you can do:
if(self.hp == 0):
self.current_image = self.images[1]
This will in fact, as per your concern, replace the current image instead of just drawing over it. Hope that helps.
I have a program that is simply made to move an image around. I try to state the self.rect as part of a load_png() call, but it simply does not like it. THe reason I think this will work is from http://www.pygame.org/docs/tut/tom/games6.html, saying that this should work:
def __init__(self, side):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_png('bat.png')
screen = pygame.display.get_surface()
self.area = screen.get_rect()
self.side = side
self.speed = 10
self.state = "still"
self.reinit()
Here is my code, which according to the pygame tutorial from its own website, should work:
def _init_(self):
pygame.sprite.Sprite._init_(self)
self.state = 'still'
self.image = pygame.image.load('goodGuy.png')
self.rect = self.image.get_rect()
screen = pygame.display.getSurface()
And it gives me this error:
Traceback (most recent call last):
File "C:\Python25\RPG.py", line 37, in <module>
screen.blit(screen, Guy.rect, Guy.rect)
AttributeError: 'goodGuy' object has no attribute 'rect'
If you guys need all of my code, comment blew and I will edit it.
You don't have a load_png function defined.
You need to create the pygame image object before you can access its rect property.
self.image = pygame.image.load(file)
Then you can assign the rect value using
self.rect = self.image.get_rect()
Or you could create the load_png function as per the example you linked.
There is no load_png function built-in to python or pygame. I imagine that the tutorial you are referring to defined it manually somewhere. What you want is pygame.image.load(filename) and then you can call get_rect() on the returned Surface object. The complete code would be as follows:
self.image = pygame.image.load('bat.png')
self.rect = self.image.get_rect()
Your second problem is that you've defined the function _init_, but you need double underscores: __init__.
Also, you need to post the code where the error is actually occurring.
Good day,
I have like 15 images I need to be buttons. I have buttons working with a Box() (Box - looks like this)
class Box(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((35, 30))
self.image = self.image.convert()
self.image.fill((255, 0, 0))
self.rect = self.image.get_rect()
self.rect.centerx = 25
self.rect.centery = 505
self.dx = 10
self.dy = 10
I am trying to make the buttons work with image sprites. So I attempted to copy the class style of the box and do the same for my Icons.. code looks like this...
class Icons(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("images/airbrushIC.gif").convert()
self.rect = self.image.get_rect()
self.rect.x = 25
self.rect.y = 550
the code in the main()
rect = image.get_rect()
rect.x = 25
rect.y = 550
ic1 = Icons((screen.get_rect().x, screen.get_rect().y))
screen.blit(ic1.image, ic1.rect)
pygame.display.update()
This code produces a positional (accepts 1 argument but 2 are there) error or an image is not referenced error (inside the Icon class).
I'm unsure if this is the right way to go about this anyways.. I know for sure that I need to load all the images (as sprites)... store them in an array... and then have my mouse check if it is clicking one of the items in the array using a for loop.
Thanks.
You are trying to pass an argument into Icons(), but your __init__() method takes no arguments. If you wanted to pass those onto the Sprite() constructor, then you probably wanted something like:
class Icons(pygame.sprite.Sprite):
def __init__(self, *args):
pygame.sprite.Sprite.__init__(self, *args)
...
This accepts any number of extra arguments (*args) using the star operator, then passes them into the sprite constructor.
I have a method in a Pygame Sprite subclass, defined as such:
def walk(self):
"""move across screen"""
displacement = self.rect.move((self.move, 0))
if self.rect.left < self.area.left or self.rect.right > self.area.right:
self.move = -self.move
displacement = self.rect.move((self.move, 0))
self.rect = displacement
I modified it, adding a parameter speed_x, and now the program is broken.
def walk(self, speed_x):
"""move across screen"""
displacement = self.rect.move((speed_x, 0))
if self.rect.left < self.area.left or self.rect.right > self.area.right:
speed_x = -speed_x
displacement = self.rect.move((speed_x, 0))
self.rect = displacement
Before I called the method like this:
def update(self):
self.walk()
Now I do:
def update(self):
self.walk(self.move)
Why doesn't this work?
You don't explain how it's "broken", but the main difference is that
speed_x = -speed_x
which you have in your second version, is only changing the local variable (arguments are local variables!) speed_x, so that changed value does not persist.
In the first version,
self.move = -self.move
does alter self (specifically one of its attriubtes) and the alteration "persists" in future method calls on the object which is here accessed as self.
Just one of the many key differences between bare names (like speed_x) and qualified names (line self.move), and, I suspect, what's biting you here (hard as you may make it to guess by not saying how the second version is failing your expectations).
You are no storing the offset back in to self.move.
If you want to use the second version of your code, try adding this line:
self.move = speed_x
At the bottom of your function.
As mentioned by others, you are not changing the value of self.move in your new code. I assume the reason you modified this function was so you could reuse this function for values other than self.move.
If you want to be able to pass different arguments into your function and modify them as well, you could pass the modified value of speed_x back as a return value:
def walk(self, speed_x):
"""move across screen"""
displacement = self.rect.move((speed_x, 0))
if self.rect.left < self.area.left or self.rect.right > self.area.right:
speed_x = -speed_x
displacement = self.rect.move((speed_x, 0))
self.rect = displacement
return speed_x
And call the function like this as:
def update(self):
self.move = self.walk(self.move)
Note: This answer assumes that self.move should not always be updated when calling walk. If this assumption is false and self.move should in fact be updated every time walk is run, then you should instead use Xavier Ho's answer.