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!
Related
I'm trying to learn OOP but my pygame window wont update with the background I'm trying to put in. The gameObject class is in another file. Filling it with white color also isn't working and I don't know why. I was able to display a background on another project I did but I cant now and I have no idea what's different. I have compared the code and they seem like they should be doing the same thing.
gameObject.py
import pygame
class GameObject:
def __init__(self, x, y, width, height, image_path):
self.background= pygame.image.load(image_path)
self.background = pygame.transform.scale(self.background, (width, height))
self.x = x
self.y = y
self.width = width
self.height = height
main.py
import pygame
from gameObject import GameObject
pygame.init()
class Player(GameObject):
def __init__(self, x, y, width, height, image_path, speed):
super().__init__(x, y, width, height, image_path)
self.speed = speed
def move(self, direction, max_height):
if (self.y >= max_height - self.height and direction > 0) or (self.y <= 0 and direction < 0):
return
self.y += (direction * self.speed)
class Game:
def __init__(self):
self.width = 800
self.height = 800
self.color = (255, 255, 255)
self.game_window = pygame.display.set_mode((self.width, self.height))
self.clock = pygame.time.Clock()
self.background = GameObject(0, 0, self.width, self.height, 'assets/background.png')
self.player1 = Player(375, 700, 50, 50, 'assets/player.png', 10)
self.level = 1.0
def draw_objects(self):
self.game_window.fill(self.white_color)
self.game_window.blit(self.background.image, (self.background.x, self.background.y))
pygame.display.update()
def run_game_loop(self):
gameRunning = True
while gameRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameRunning = False
if gameRunning == False:
pygame.quit()
self.draw_objects()
self.clock.tick(60)
game = Game()
game.run_game_loop()
quit()
I have tried basic research on it and looking at other code that uses a custom background with pygame
It is a matter of indentation. self.draw_objects() must be called in the application loop not after the application loop:
class Game:
# [...]
def run_game_loop(self):
gameRunning = True
while gameRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameRunning = False
if gameRunning == False:
pygame.quit()
# INDENTATION
#-->|
self.draw_objects()
self.clock.tick(60)
Your loop never actually does anything but clear the event queue looking for pygame.QUIT.
You need to indent the calls to self.draw_objects() and self.clock.tick(60) so they are inside the loop.
I have a problem with my code, after running, it said that " pygame.sprite.Sprite.add() argument after * must be an iterable, not int" in the line charS1=CharS(100,100,50,50)
i was expecting a red rect in my window after, but i had those problem
here my code, and yes, almost copy from Youtube, but it went wrong
import pygame, os , sys , math
from os import listdir
from os.path import isfile, join
pygame.init()
pygame.display.set_caption("Group 5: Female house from Ẻuope")
icon = pygame.image.load(join("img","good-icon.png"))
pygame.display.set_icon(icon)
WIDTH, HEIGHT = 1000, 600
FPS = 40
PLAYER_VEL = 3
window=pygame.display.set_mode((WIDTH, HEIGHT))
def get_background(name):
background = pygame.image.load(join("img",name))
return background
class CharS(pygame.sprite.Sprite):
COLOR = (255,0,0)
def __init__(self,x,y, width, heigth):
self.rect=pygame.Rect(x,y,width,heigth)
self.x_vel=0
self.y_vel=0
self.mask= None
self.direction= "right"
self.animation_count = 0
def move (self, dx, dy):
self.rect.x += dx
self.rect.y += dy
def move_right(self, vel):
self.x_vel = vel
if self.direction != "left":
self.direction = "left"
self.animation_count= 0
def loop(self, fps):
self.move( self.x_vel, self.y_vel)
def draw(self, win):
pygame.draw.rect(win, self.COLOR, self.rect)
def draw(window, background,char):
window.blit(background, (0,0))
char.draw(window)
pygame.display.update()
def main(window):
clock = pygame.time.Clock()
background= get_background("backgrd.png")
charS1=CharS(100,100,50,50) #the problem went here
run= True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
break
draw(window, background, charS1)
pygame.quit()
quit()
if __name__ == '__main__' :
main(window)
how can i fix that?
You get this error, because the base class pygame.sprite.Sprite is not initialized. You didn't invoke the constructor of the base class of (super().__init__() ). Also see class super.
class CharS(pygame.sprite.Sprite):
COLOR = (255,0,0)
def __init__(self,x,y, width, heigth):
super().__init__() # <---
self.rect=pygame.Rect(x,y,width,heigth)
# [...]
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)
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()
I'm using PyGame to make my own 'game engine' in Python 3.7. I want to make a class that uses the pygame.rect() function but when I run it it gives me this error or a similar one every time.
main.py (./pyseed/)
# Imports
import pygame
pygame.init()
# class
class Shape:
def __init__(self, width, height, color):
self.width = width
self.height = height
self.color = color
self.SHAPE = pygame.rect(self, width, height, color)
# RunApp() function
def runApp(width, height):
screen = pygame.display.set_mode((width, height))
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
pygame.display.flip()
testing.py (import main will change to import pyseed.main)
# PySeed Testing Zone
import main as pyseed
myShape = pyseed.Shape(90, 90, (0, 100, 255))
pyseed.runApp(400, 300)
Thank you for any help.
My New Code:
main.py
# Made by DeBeast591
# Enjoy!
# Imports
import pygame
# Getting PyGame ready...
pygame.init()
print("Welcome to PySeed!\nMade By DeBeast591\nEnjoy!")
def setUp(width, height):
global screen
screen = pygame.display.set_mode((width, height))
# class
class Shape:
def __init__(self, x, y, width, height, color):
global screen
self.width = width
self.height = height
self.x = x
self.y = y
self.color = color
self.SHAPE = pygame.draw.rect(screen, self.color,pygame.Rect(self.x, self.y, self.width, self.height))
# RunApp() function
def runApp():
global screen
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
pygame.display.flip()
testing.py
# PySeed Testing Zone
import main as pyseed
pyseed.setUp(400, 300)
myShape = pyseed.Shape(30, 30, 90, 90, (0, 100, 255))
pyseed.runApp()
Thank you for the help.