So I have a player class setup with pygame. Everytime I run my code however it gives me a "type object 'playnode' has no attribute 'image'" error. Any help would be great.
Player Class:
import pygame,random
class playnode(pygame.sprite.Sprite):
def __init__(self, pos):
super().__init__()
self.image = pygame.image.load("amogus png.png")
self.image = pygame.transform.smoothscale(self.image, (15,15))
self.rect = self.image.get_rect()
self.rect.center = pos
self.speed = pygame.math.Vector2(0, 5)
self.speed.rotate_ip(random.randint(0, 360))
self.time = 0
def update(self,x_speed,y_speed):
self.rect.move_ip(x_speed, y_speed)
Main:
import pygame
from pygame.locals import *
pygame.init()
clock = pygame.time.Clock()
on = True
from Level import *
size = (width, height) = 850, 480
import Player
players = pygame.sprite.Group()
color = (54, 96, 230)
screen = pygame.display.set_mode(size, RESIZABLE)
p_v_x = 0
p_v_y = 0
posTuple = tuple((p_v_x, p_v_y))
enemyNum = 10
def innit():
players = pygame.sprite.Group
Enemies = pygame.sprite.Group
players.add(playnode)
def event_processor():
global on, success
for event in pygame.event.get():
if event.type == QUIT:
on = False
def main():
global on
innit()
while on == True:
clock.tick(60)
event_processor()
# screen.fill(color)
screen.blit(Player.playnode.image, Player.playnode.rect)
pygame.display.flip()
if __name__ == '__main__':
main()
Random crap so I can post this ajsodijaoikdjaoijdoisajoidjioajdoisajoidjaosijdiosjasidojoiasdjiodjpiodfjiopjsjfoij;aokjkofjdiaojfopiajiopafjiopajdoipfjdoiojpsjfpoiajfdopijaopidfjopidsajfiopj9uipwhfgioujnwiouonbhgoiunowjnvoiejqwownoivnwe
You are referencing the class variables of the player instead of the instance variables, so you first need to create a instance of the player before referencing it
example:
player = Player(...)
...
screen.blit(player .playnode.image, player .playnode.rect)
Related
I would like to get my pygame character walking. I tried everything but it's not moving. The player().x is not moving. What can I try next?
import pygame
pygame.init()
WIDTH, HEIGHT = 1920, 1080
ground = (69, 30, 6)
main_menu_color = (0, 0, 0)
max_fps = 60
class player:
def __init__(self):
self.x = 100
self.y = 300
self.width = 224
self.height = 224
self.site = "Left"
self.look = pygame.image.load('character/sprite_0.png')
def tick(self):
pass
def walking(self):
self.x = self.x + 10
print(self.x)
def drawscreen(playerpos):
screen.fill((69, 30, 6))
screen.blit(player().look, (player().x, player().y))
pygame.display.update()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Zooombie!")
def main():
playerpos = pygame.Rect(player().x, player().y , player().width, player().height)
clock = pygame.time.Clock()
run = "run"
while run == "run":
clock.tick(max_fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
player().tick()
player().walking()
drawscreen(playerpos)```
You're not creating a persistent instance of player:
p = player()
You should update this rather than an unnamed player. For example:
def drawscreen(p):
screen.fill((69, 30, 6))
screen.blit(p.look, (p.x, p.y))
pygame.display.update()
p.tick()
p.walking()
drawscreen(p)
Read about Classes and Instance Objects.player() creates a new instance of the class player. So every time you call player(), a new player object is created. You must create an instance at the beginning of the program and use that instance throughout the program.
Also see Style Guide for Python Code. Class names should normally use the CapWords convention and variable names should be lower case. So the name of the class should be Player and the name of the instance object can be player.
import pygame
pygame.init()
WIDTH, HEIGHT = 1920, 1080
ground = (69, 30, 6)
main_menu_color = (0, 0, 0)
max_fps = 60
class Player:
def __init__(self):
self.x = 100
self.y = 300
self.width = 224
self.height = 224
self.site = "Left"
self.look = pygame.image.load('character/sprite_0.png')
def tick(self):
pass
def walking(self):
self.x = self.x + 10
def drawscreen(player):
screen.fill((69, 30, 6))
screen.blit(player.look, (player.x, player.y))
pygame.display.update()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Zooombie!")
def main():
player = Player()
clock = pygame.time.Clock()
run = "run"
while run == "run":
clock.tick(max_fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = "end"
player.tick()
player.walking()
drawscreen(player)
pygame.quit()
if __name__ == '__main__':
main()
There are some problems in your code related to how a class and its instantiated objects work. Look at the following code and try to run it:
import pygame
pygame.init()
WIDTH, HEIGHT = 600, 480
ground = (69, 30, 6)
main_menu_color = (0, 0, 0)
max_fps = 60
class player:
def __init__(self):
self.x = 100
self.y = 300
self.width = 224
self.height = 224
self.site = "Left"
self.look = pygame.image.load('character/sprite_0.png')
def tick(self):
pass
def walking(self):
self.x+= 10
print(self.x)
def drawscreen(playerpos):
screen.fill((69, 30, 6))
screen.blit(pygame.image.load('character/sprite_0.png'), (playerpos.x, playerpos.y))
pygame.display.update()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Zooombie!")
def main():
player1 = player()
clock = pygame.time.Clock()
run = "run"
while run == "run":
playerpos = pygame.Rect(player1.x, player1.y , player1.width, player1.height)
clock.tick(max_fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
player1.tick()
player1.walking()
drawscreen(playerpos)
if __name__ == "__main__":
main()
Here are some things to note:
Class methods can not be used directly like that (in this case). You need to instantiate an object of the class like player1 = player(). This means you created an object player1 from the class player that you created.
An object is not callable i.e. to access its properties you need to use the dot operator in Python. Like player1.x and so on.
Lastly, your drawscreen function contains the screen.blit function which takes in parameters source: Surface and dest: list of coordinates. I changed it to the correct parameters in this case. Your source parameter was a callable so was not throwing an error, but what it was returning, that was not the expected type required.
Hope this helps!
This question already has answers here:
How can i shoot a bullet with space bar?
(1 answer)
How do I stop more than 1 bullet firing at once?
(1 answer)
Closed 8 months ago.
So I'm working on a simple game in pygame and I have a file named players.py that contains a Player class and a PlayerAttack class because I want to have the projectiles be their own object. Here is some code from my players.py
import pygame
import gametools
class PlayerAttack(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.bullet_img = gametools.smoothscale2x(pygame.image.load('sprites/player/player-bullet.png')).convert_alpha()
self.image = self.bullet_img
self.rect = self.image.get_rect(center = (400, 300))
class Player(pygame.sprite.Sprite):
'''The Main player class'''
def __init__(self):
super().__init__()
self.player_image_center = gametools.smoothscale2x(pygame.image.load('sprites/player/player.png')).convert_alpha()
self.player_image_left = gametools.smoothscale2x(pygame.image.load('sprites/player/player-left.png')).convert_alpha()
self.player_image_right = gametools.smoothscale2x(pygame.image.load('sprites/player/player-right.png')).convert_alpha()
self.player_image = [self.player_image_left, self.player_image_center, self.player_image_right]
self.player_index = 1
self.image = self.player_image[self.player_index]
self.rect = self.image.get_rect(center = (400, 500))
self.vector = pygame.math.Vector2()
self.velocity = 5
self.bullet = pygame.sprite.Group()
self.bullet.add(PlayerAttack())
def player_input(self):
keys = pygame.key.get_pressed()
# player movement
if keys[pygame.K_UP]:
self.vector.y = -1
elif keys[pygame.K_DOWN]:
self.vector.y = 1
else:
self.vector.y = 0
if keys[pygame.K_LEFT]:
self.vector.x = -1
elif keys[pygame.K_RIGHT]:
self.vector.x = 1
else:
self.vector.x = 0
# attacks
if keys[pygame.K_x]:
return self.bullet.draw(screen)
def move(self, velocity):
if self.vector.magnitude() != 0:
self.vector = self.vector.normalize()
self.rect.center += self.vector * velocity
def update(self):
self.player_input()
self.animation_state()
self.move(self.velocity)
If you look in the __init__() method in the Player class you will see that I define self.bullet as an object belonging to the PlayerAttack class. Now if you look inside the player_input() method in the Player class you see that it draws it to the screen surface defined in main.py
import pygame
import gametools
import players
from sys import exit
# initilaization
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Bullet hell')
clock = pygame.time.Clock()
# Player
player = pygame.sprite.GroupSingle()
player.add(players.Player())
x = pygame.sprite.GroupSingle()
# Background
back_surf = pygame.image.load('sprites/backgrounds/background.png').convert()
# main game loop
while True:
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
# display background
screen.blit(back_surf, (0, 0))
player.draw(screen)
player.update()
pygame.display.update()
clock.tick(60)
This produces an error because screen is defined in main.py and not in the Player class. So my question is how can I draw an object to the screen when receiving input from within the class. Or is there a better way to go about this?
When I run the code the target images overlap each other
so if we shoot the target images which are overlapped are also removed
this is a big issue in my game help me to solve this
Like this:
import pygame, sys
import os
import random
pygame.mixer.init()
pygame.init()
class Crosshair(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load(os.path.join("files", 'crosshair.png'))
self.rect = self.image.get_rect()
self.shot_sound = pygame.mixer.Sound(os.path.join('files','shot.wav'))
def sound(self):
self.shot_sound.play()
pygame.sprite.spritecollide(crosshair,target_group, True)
def update(self):
self.rect.center = pygame.mouse.get_pos()
class Target(pygame.sprite.Sprite):
def __init__(self, target ,x,y):
super().__init__()
self.image = pygame.image.load(target)
self.rect = self.image.get_rect()
self.rect.center = [x,y]
# Screeen
width, height = 1000,700
screen = pygame.display.set_mode((width,height))
clock = pygame.time.Clock()
bg = pygame.transform.scale2x(pygame.transform.scale2x(pygame.image.load(os.path.join('files','bg.png'))))
pygame.display.set_caption("Shotting Game")
pygame.mouse.set_visible(False)
# crosshair
crosshair = Crosshair()
crosshair_group = pygame.sprite.Group()
crosshair_group.add(crosshair)
# Target
target_group = pygame.sprite.Group()
for target in range(20):
draw_target = Target(os.path.join('files','target.png'),random.randint(0,width), random.randint(0,height))
target_group.add(draw_target)
# Main loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
crosshair.sound()
screen.fill((255,255,255))
screen.blit(bg,(0,0))
target_group.draw(screen)
crosshair_group.draw(screen)
crosshair_group.update()
pygame.display.update()
clock.tick(50)
Use pygame.sprite.spritecollide to see if a new target intersects with another. Only add the target if it doesn't overlap:
target_group = pygame.sprite.Group()
while len(target_group) < 20:
draw_target = Target(os.path.join('files','target.png'),random.randint(0,width), random.randint(0,height))
if not pygame.sprite.spritecollide(draw_target, target_group, False):
target_group.add(draw_target)
If you want to generate continuous targets, you can use the application loop:
# Target
target_group = pygame.sprite.Group()
# Main loop
while True:
if len(target_group) < 20:
draw_target = Target(os.path.join('files','target.png'),random.randint(0,width), random.randint(0,height))
if not pygame.sprite.spritecollide(draw_target, target_group, False):
target_group.add(draw_target)
import pygame
from pygame.constants import( QUIT, KEYDOWN, KEYUP, K_LEFT, K_RIGHT, K_ESCAPE, K_SPACE,
MOUSEBUTTONDOWN)
import os
from random import randint
class Settings:
w_width = 800
w_height = 600
w_border = 50
file_path = os.path.dirname(os.path.abspath(__file__))
image_path = os.path.join(file_path, "pictures")
class Background(object):
def __init__(self, filename):
self.imageo = pygame.image.load(os.path.join(Settings.image_path, filename))
self.image = pygame.transform.scale(self.imageo, (Settings.w_width, Settings.w_height)).convert()
self.rect = self.image.get_rect()
def draw(self, screen):
screen.blit(self.image, self.rect)
I have here the bubbles class and i want to do it that when you click a bubble it despawns but i dont know how the bubbles detect the mouse cursor and how the bubbles despawn.
I already tried to add the mouse position function but I dont know hot to use it.
And I searched on the Internet but I found nothing about that.
class Bubble(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.width = 50
self.height = 300
self.image = pygame.image.load(os.path.join(Settings.image_path, "Blase.png ")).convert_alpha()
self.image = pygame.transform.scale(self.image, (25, 25))
self.rect_br = (Settings.w_width//2) + 100, (Settings.w_height//2) + 100
self.rect = self.image.get_rect()
self.mousex, self.mousey = pygame.mouse.get_pos()
self.cx = self.width - 25
self.cy = self.height - 25
self.rect.left = randint(Settings.w_border, Settings.w_width - Settings.w_border)
self.rect.top = randint(Settings.w_border, Settings.w_height - (Settings.w_border * 2))
def update(self):
pass
def scale_up(self):
self.scale["width"] += 2
self.scale["height"] += 2
def scale_down(self):
self.scale["width"] -= 2
self.scale["height"] -= 2
def events(self):
pass
def draw(self, screen):
screen.blit(self.image,self.rect )
Here is where everythings run from the code
class Game(object):
def __init__(self):
self.screen = pygame.display.set_mode((Settings.w_width, Settings.w_height))
self.clock = pygame.time.Clock()
self.runn = False
self.background = Background("Hintergrund.png")
self.bubble = pygame.sprite.Group()
def run(self):
self.runn = True
while self.runn:
self.clock.tick(60)
self.watch_for_events()
self.draw()
self.events()
def events(self):
if len(self.bubble)< 100:
self.bubble.add(Bubble())
time.sleep(0.2)
def draw(self):
self.background.draw(self.screen)
self.bubble.draw(self.screen)
pygame.display.flip()
def watch_for_events(self):
for event in pygame.event.get():
if event.type == QUIT:
self.runn = False
if __name__ == '__main__':
os.environ['SDL_VIDEO_WINDOWS_POS'] = "50, 1100"
pygame.init()
game = Game()
game.run()
pygame.quit()
Thanks for Helping
"Despawn" a bubble by calling pygame.sprite.Sprite.kill. kill remove the Sprite from all Groups. Use the MOUSEBUTTONDOWN event and pygame.Rect.collidepoint to determine if a bubble is clicked:
class Game(object):
# [...]
def watch_for_events(self):
for event in pygame.event.get():
if event.type == QUIT:
self.runn = False
if event.type == MOUSEBUTTONDOWN:
for bubble in self.bubble:
if bubble.rect.collidepoint(event.pos):
bubble.kill()
So im trying to make a game where the character should dodge enemies which are randomly spawned from above. The problem is, I dont know how to make the Random values different without instanciating another class, which I dont want to do. Also, with Screen.fill(), the enemies wont show up since they're being overlapped by the colour every frame, and if I dont use Screen.fill(), my character would leave a trail everytime it moves. Any Suggestions?
import random
pygame.init()
Running = True
Screen = pygame.display.set_mode((800, 600))
player_img = pygame.image.load('/Users/kevinhadinata/Downloads/ufo.png')
player_updated = pygame.transform.scale(player_img,(60,60))
enemy_list = []
enemy_img = pygame.image.load('/Users/kevinhadinata/Downloads/alien.png')
SPAWNENEMY = pygame.USEREVENT
pygame.time.set_timer(SPAWNENEMY,1000)
class Player:
def __init__(self):
self.ypos = 540
self.xpos = 325
self.height = 60
self.width = 60
self.playerUpdated = player_updated
def create_player(self):
Playerss = pygame.Rect(self.xpos,self.ypos,self.height,self.width)
pygame.draw.ellipse(Screen, (0, 0, 0), Playerss)
Screen.blit(player_updated, (Playerss.x, Playerss.y))
sizee = random.randint(10,40)
randomX = random.randint(0,700)
class Enemy:
def __init__(self):
self.xval = random.randint(0,700)
self.size = random.randint(10,40)
def create_enemy(self):
Enemy = pygame.Rect(self.xval, 0, self.size,self.size)
#enemy_updated = pygame.transform.scale(enemy_img,(self.size,self.size))
enemy_list.append(Enemy)
pygame.draw.ellipse(Screen,(255,255,0),Enemy)
Player = Player()
Enemys = Enemy()
while Running:
Screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
Running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
Player.xpos -= 20
if event.key == pygame.K_RIGHT:
Player.xpos += 20
if event.type == SPAWNENEMY:
Enemys.create_enemy()
Player.create_player()
pygame.display.update()
It's a good idea to not instantiate a new enemy, because just recycling it back to the top of the screen is enough. This amounts to simply changing the size & x,y.
Some of your code is occluding the Enemy class name with an Enemy variable name. I've changed this variable name to new_enemy.
class Enemy:
def __init__(self):
self.recycle() # set the position & size initially
def recycle( self ):
# start or re-start an enemy position
self.size = random.randint(10,40)
self.xval = random.randint(0,700)
self.yval = -self.size # off the screen-top
self.rect = pygame.Rect( self.xval, self.yval, self.size, self.size )
def draw( self, screen ):
pygame.draw.ellipse( screen, (255,255,0), self.rect )
def create_enemy(self):
global enemy_list
new_enemy = Enemy() # create a new Enemy
enemy_list.append( new_enemy ) # add it to the list
Then in your main loop, you can recycle() any Enemy that goes off-screen.
[...] # in main loop
# draw all the enemies, and re-position any enemies that moved off the screen
for enemy in enemy_list:
enemy.draw( screen )
if ( enemy.ypos > 600 ): # TODO - don't use a fixed size
enemy.recycle() # move back to top
The drawing an spawning code was mixed-up, I have re-arranged this into a separate .draw() function. Using this solves the problem with clearing the screen too. Each frame, the code clears the screen, then repaints all the items.
You need to create a list of enemies and iterate the list in the main loop to draw each enemy. Use randint to randomly place the enemies.
Try this code:
import random, pygame
pygame.init()
Running = True
Screen = pygame.display.set_mode((800, 600))
player_img = pygame.image.load('/Users/kevinhadinata/Downloads/ufo.png')
player_updated = pygame.transform.scale(player_img,(60,60))
enemy_list = []
enemy_img = pygame.image.load('/Users/kevinhadinata/Downloads/alien.png')
SPAWNENEMY = pygame.USEREVENT
pygame.time.set_timer(SPAWNENEMY,1000)
class Player:
def __init__(self):
self.ypos = 540
self.xpos = 325
self.height = 60
self.width = 60
self.playerUpdated = player_updated
def create_player(self):
self.Playerss = pygame.Rect(self.xpos,self.ypos,self.height,self.width)
pygame.draw.ellipse(Screen, (0, 0, 0), self.Playerss)
Screen.blit(player_updated, (self.Playerss.x, self.Playerss.y))
def draw(self): # draw player
Screen.blit(player_updated, (self.xpos,self.ypos))
sizee = random.randint(10,40)
randomX = random.randint(0,700)
class Enemys:
def __init__(self):
#self.xval = random.randint(0,700)
self.size = random.randint(10,40)
def create_enemy(self):
Enemy = pygame.Rect(random.randint(100,700), 0, self.size,self.size)
#enemy_updated = pygame.transform.scale(enemy_img,(self.size,self.size))
enemy_list.append(Enemy)
pygame.draw.ellipse(Screen,(255,255,0),Enemy)
def draw(self): # draw all enemies
for e in enemy_list:
pygame.draw.ellipse(Screen,(255,255,0),e)
Player = Player() # player object
Enemys = Enemys() # collection of enemies
Player.create_player()
while Running:
Screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
Running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
Player.xpos -= 20
if event.key == pygame.K_RIGHT:
Player.xpos += 20
if event.type == SPAWNENEMY:
Enemys.create_enemy()
Player.draw() # draw player
Enemys.draw() # draw all enemies
pygame.display.update()