Pygame sprite file error - python-2.7

Disclaimer: I'm only 10 years old so please be patient with me please :D
So I'm working on this game in pygame where you play as a balloon and you have to avoid obstacles and collect points. The points add 10 to your score and the obstacles restart your game. You use the arrow keys to move. It's based off Ski-Free. But whenever I run it I don't get an error in my script, but an error in the sprite.py file that pygame comes with. For info, I use Mac OSX Sierra as my OS and IDLE 2.712 as my shell. I use python 2. So, here's my error:
Traceback (most recent call last):
File "/Users/------------/Desktop/Sky Balloon.py", line 75, in <module>
create_map()
File "/Users/------------/Desktop/Sky Balloon.py", line 58, in create_map
obstacles.add(obstacles)
File "/usr/local/lib/python2.7/site-packages/pygame/sprite.py", line 142, in add
self.add(*group)
TypeError: add() argument after * must be an iterable, not ObstacleClass
P.S. I did cover up my but the number of characters is still the same.
Now here's my actual game script. (Sky Balloon.py)
import pygame, sys, random
baloon_images = ["Baloon_gif.gif", "pop.gif"]
class BaloonClass(pygame.sprite.Sprite):
def __init__(self):f
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("Baloon_gif.gif")
self.rect = self.image.get_rect()
self.rect.center = [320, 100]
self.angle = 0
def turn(self, direction):
self.angle = self.angle + direction
if self.angle < -2: self.angle = -2
if self.angle > 2: self.angle = 2
center = self.rect.center
self.image = pygame.image.load(baloon_images[self.angle])
self.rect = self.image.get_rect()
self.rect.center = center
speed = [self.angle, 6 - abs(self.angle) * 2]
return speed
def move(self, speed):
self.rect.centerx = self.rect.centerx + speed[0]
if self.rect.centerx < 20: self.rect.centerx = 20
if self.rect.centerx > 620: self.rect.centerx = 620
class ObstacleClass(pygame.sprite.Sprite):
def __init__(self, image_file, location, type):
pygame.sprite.Sprite.__init__(self)
self.image_file = image_file
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.center = location
self.type = type
self.passed = False
def update(self):
global speed
self.rect.centery -= speed[1]
if self.rect.centery < -32:
self.kill()
def create_map():
global obstacles
locations = []
for i in range(10):
row = random.randint(0, 9)
col = random.randint(0, 9)
location = [col * 64 + 20, row * 64 + 20 + 640]
if not (location in locations):
locations.append(location)
type = random.choice(["cloud", "point"])
if type == "cloud": img = "cloud.png"
elif type == "point": img = "Points.png"
obstacles = ObstacleClass(img, location, type)
obstacles.add(obstacles)
def animate():
screen.fill([0, 255, 255])
obstacles.draw(screen)
screen.blit(baloon.image, baloon.rect)
screen.blit(score_text, [10, 10])
pygame.display.flip()
pygame.init()
screen = pygame.display.set_mode([640, 640])
clock = pygame.time.Clock()
baloon = BaloonClass()
speed = [0, 6]
obstacles = pygame.sprite.Group()
map_position = 0
points = 0
create_map()
font = pygame.font.Font(None, 50)
running = True
while running:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
speed = baloon.turn(-1)
elif event.key == pygame.K_RIGHT:
speed = baloon.turn(1)
baloon.move(speed)
map_position += speed[1]
if map_position >=640:
create_map()
map_position = 0
hit = pygame.sprite.spritecollide(baloon, obstacles, False)
if hit:
if hit[0].type == "cloud" and not hit[0].passed:
points = points - 100
baloon.image = pygame.image.load("pop.gif")
animate()
pygame.time.delay(1000)
baloon.image = pygame.image.load("Baloon_gif.gif")
baloon.angle = 0
speed = [0, 6]
hit[0].passed = True
elif hit[0].type == "point" and not hit[0].passed:
points += 10
hit[0].kill()
obstacles.update()
score_text = font.render("Score: " +str(points), 1, (0, 0, 0))
animate()
pygame.quit
Thank You!

obstacles.add(obstacle) not obstacles.add(obstacles) (extra s)

Related

how exactly adding all particle's speed when i press arrow up

i'm on ideal gas theory simulation project and i want to ask you how exactly adding all particle's speed when i press arrow up. Because in my code, it didn't work.
I tried adding speed at initial process and loop but nothing work.
You can see right away what I'm trying to do.
edited for more understanding
sorry if i didn't put english
import pygame, sys, random, math
from pygame.locals import *
pygame.init()
#colour
white = [255,255,255]
black = [0,0,0]
red = [255,0,0]
green = [0,255,0]
blue = [0,0,255]
#setup window
(width,height)=(800,600)
window=pygame.display.set_mode((width,height))
pygame.display.set_caption('ideal gas')
#setup fps window
FPS=30
clock=pygame.time.Clock()
def bounceparticle(p1,p2):
dx=p1.x-p2.x
dy=p1.y-p2.y
distance=math.hypot(dx,dy)
if distance<p1.size+p2.size:
tangent=math.atan2(dy,dx)
angle=0.5*math.pi+tangent
angle1=2*tangent-p1.angle
angle2=2*tangent-p2.angle
speed1=p2.speed+p2.fire #so that every bounce increases speed
speed2=p1.speed+p1.fire #so that every bounce increases speed
(p1.angle, p1.speed) = (angle1, speed1)
(p2.angle, p2.speed) = (angle2, speed2)
p1.x += math.sin(angle)
p1.y -= math.cos(angle)
p2.x -= math.sin(angle)
p2.y += math.cos(angle)
#partikel
class Partikel:
def __init__(self,(x,y)):
self.x = x
self.y = y
self.size = 4
self.speed = 0
self.angle = 0
self.colour = blue #it need a recursion function to define changing particle's colour
self.fire = 0
def partikel_on_windows(self):
pygame.draw.circle(window,self.colour,[int(self.x),int(self.y)],self.size)
def move(self):
self.x += math.sin(self.angle) * self.speed
self.y -= math.cos(self.angle) * self.speed
#self.speed += self.fire #it can increase the speed but it takes 100 times pressed arrow up keyboard
def bounce(self):
if self.x>=width-self.size:
self.x=2*(width-self.size)-self.x
self.angle=-self.angle
self.speed += self.fire
elif self.x<=self.size:
self.x=2*self.size-self.x
self.angle=-self.angle
self.speed += self.fire
if self.y>=height-50-self.size:
self.y=2*(height-50-self.size)-self.y
self.angle=math.pi-self.angle
self.speed += self.fire
elif self.y<=self.size:
self.y=2*self.size-self.y
self.angle=math.pi-self.angle
self.speed += self.fire
number_of_particles = 200
myparticle = []
for n in range(number_of_particles):
centralpoint = random.randint(10,50)
x = random.randint(centralpoint,width-centralpoint)
y = random.randint(centralpoint,height-centralpoint)
partikel=Partikel((x,y))
partikel.angle=random.uniform(0,math.pi*2)
partikel.speed = 2
#partikel.fire = 0 #it can increase the speed but it takes 100 times pressed arrow up keyboard
#partikel.colour= [0,0,[255-partikel.speed]] #can't change the colour
myparticle.append(partikel)
# main game loop
while True:
for event in pygame.event.get():
pygame.key.set_repeat(1,50)
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == K_UP:
partikel.fire += 5
if event.key == K_DOWN:
partikel.fire -= 5
"""if event.type == pygame.KEYUP:
if event.key == K_UP:
partikel.fire = 0
if event.key == K_DOWN:
partikel.fire = 0"""
window.fill(black)
#partikel.fire = 1 #still can't
for i in range(len(myparticle)):
partikel = myparticle[i]
partikel.move()
partikel.bounce()
partikel.partikel_on_windows()
#partikel.fire = 0 #can't controling from keyboard
#partikel.colour= [0,0,[255-partikel.speed]]
for partikel2 in myparticle[i+1:]:
bounceparticle(partikel,partikel2)
pygame.display.update()
clock.tick(FPS)
You have to add to every particle in list.
I use variable speed which I change using key and later I add it to every particle in loop:
for i in range(len(partikel_ku)):
partikel.cepat += speed
Every click increases/decreases speed.
Full code:
import pygame
import random
import math
import sys
# --- constants ---- (UPPER_CASE_NAMES)
PUTIH = (255, 255, 255)
HITAM = (0, 0, 0)
MERAH = (255, 0, 0)
HIJAU = (0, 255, 0)
BIRU = (0, 0, 255)
LEBAR = 800
TINGGI = 600
FPS = 30
# --- classes --- (CamelCaseNames)
class Partikel:
def __init__(self, pos):
x, y = pos
self.x = x
self.y = y
self.size = 4
self.cepat = 0
self.sudut = 0
self.warna = BIRU
self.api = 0
def partikel_di_layar(self):
pygame.draw.circle(jendela, self.warna, [int(self.x), int(self.y)], self.size)
def gerak(self):
self.x += math.sin(self.sudut) * self.cepat
self.y -= math.cos(self.sudut) * self.cepat
def mantul(self):
if self.x >= LEBAR-self.size:
self.x = 2 * (LEBAR-self.size) - self.x
self.sudut = -self.sudut
elif self.x <= self.size:
self.x = 2 * self.size - self.x
self.sudut = -self.sudut
if self.y >= TINGGI - 50 - self.size:
self.y = 2 * (TINGGI - 50 - self.size) - self.y
self.sudut = math.pi - self.sudut
elif self.y <= self.size:
self.y = 2 * self.size - self.y
self.sudut = math.pi - self.sudut
# --- functions --- (lower_case_names)
def pantulan(p1, p2):
dx = p1.x - p2.x
dy = p1.y - p2.y
jarak = math.hypot(dx,dy)
if jarak < p1.size + p2.size:
tangen = math.atan2(dy, dx)
sudut = 0.5 * math.pi + tangen
sudut1 = 2 * tangen - p1.sudut
sudut2 = 2 * tangen - p2.sudut
cepat1 = p2.cepat + p2.api
cepat2 = p1.cepat + p1.api
p1.sudut = sudut1
p1.cepat = cepat1
p2.sudut = sudut2
p2.cepat = cepat2
p1.x += math.sin(sudut)
p1.y -= math.cos(sudut)
p2.x -= math.sin(sudut)
p2.y += math.cos(sudut)
# --- main ---
bnyk_partikel = 100
partikel_ku = []
# - init -
pygame.init()
jendela = pygame.display.set_mode((LEBAR, TINGGI))
pygame.display.set_caption('Animasi Bola')
pygame.key.set_repeat(1, 50)
# - objects -
for n in range(bnyk_partikel):
cp = random.randint(10, 50)
x = random.randint(cp, LEBAR - cp)
y = random.randint(cp, TINGGI - cp)
partikel = Partikel((x,y))
partikel.sudut = random.uniform(0, math.pi*2)
partikel.cepat = 2
partikel_ku.append(partikel)
speed = 0
# - mainloop -
clock=pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
speed += 1
elif event.key == pygame.K_DOWN:
speed -= 1
elif event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
speed = 0
elif event.key == pygame.K_DOWN:
speed = 0
jendela.fill(HITAM)
#partikel.api = 1 #masih g bisa
for i in range(len(partikel_ku)):
partikel = partikel_ku[i]
partikel.cepat += speed
partikel.gerak()
partikel.mantul()
partikel.partikel_di_layar()
partikel.api = 1 #tak bisa dipanggil dari kontrol keyboard
#partikel.warna= [0,0,[255-partikel.cepat]]
for partikel2 in partikel_ku[i+1:]:
pantulan(partikel,partikel2)
pygame.display.update()
clock.tick(FPS)
BTW: read PEP 8 -- Style Guide for Python Code

Pygame : Controlling two sprites

import pygame, sys
pygame.init()
surf = pygame.display.set_mode((1280, 720))
black = (0, 0, 0)
surf.fill(black)
fps_clock = pygame.time.Clock()
pygame.display.flip()
class Player(pygame.sprite.Sprite):
def __init__(self, name, xx, yy):
self.name = name
self.image = pygame.Surface((22, 22))
self.image.fill((130, 100, 200))
self.rect = self.image.get_rect(x = xx, y = yy)
self.x_vel = 0
self.y_vel = 0
def speed(self, speed):
self.speed = speed
def update(self, keys):
if keys[pygame.K_DOWN]:
self.y_vel = 3
elif keys[pygame.K_UP]:
self.y_vel = -3
else:
self.y_vel = 0
if keys[pygame.K_LEFT]:
self.x_vel = -3
elif keys[pygame.K_RIGHT]:
self.x_vel = 3
else:
self.x_vel = 0
self.rect.x += self.x_vel
self.rect.y += self.y_vel
def update1(self, keys):
if keys[pygame.K_s]:
self.y_vel = 3
elif keys[pygame.K_w]:
self.y_vel = -3
else:
self.y_vel = 0
if keys[pygame.K_a]:
self.x_vel = -3
elif keys[pygame.K_d]:
self.x_vel = 3
else:
self.x_vel = 0
self.rect.x += self.x_vel
self.rect.y += self.y_vel
def draw(self, surface):
surf.fill(black)
surface.blit(self.image, self.rect)
player = Player('Tank', 100, 300)
player2 = Player('Tank2', 200, 500)
def main():
while True:
keys = pygame.key.get_pressed()
player.draw(surf)
player2.draw(surf)
player.update(keys)
player2.update1(keys)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
fps_clock.tick(60)
main()
Trying to create 2 sprites, one which can be controlled using the arrow keys, the other using the WASD keyset. It only blits one sprite on the image, which can be controlled using WASD. The other can be controlled by arrow keys if player2.update1(keys) is commented. Please don't beat down on me that much, still kind of a novice.
The problem is that you fill the whole screen with black before you draw each player. That means that when player two is drawn player one gets drawn over with black. Remove line 52 surf.fill(black) from def draw() and add it to the main game loop so that it is only called once.
def main():
while True:
surf.fill(black)

Can not to draw all rectangles on the list

The problem is next, I have a list "enemy" and I am adding rectangles to it. After I am finished adding rectangles I need everything on the list to be drawn using the .draw() function that is part of the Enemy class.
# Colour
# Created by Niktia Kotter
#!/usr/bin/env python
import pygame, sys, random, time
from pygame.locals import*
# set up pygame
pygame.init()
FPS=60
fpsclock = pygame.time.Clock()
# R G B
WHITE = (255, 255, 255)
GREEN = (78, 255, 87)
YELLOW = (241, 255, 0)
BLUE = (80, 255, 239)
PURPLE = (203, 0, 255)
RED = (237, 28, 36)
SCREEN_W = 800
SCREEN_H = 480
SCREEN = pygame.display.set_mode((SCREEN_W,SCREEN_H),0,32)
snapMult = SCREEN_W / 5
pos0 = 0
pos1 = snapMult
pos2 = pos1 + snapMult
pos3 = pos2 + snapMult
pos4 = pos3 + snapMult
# set up calsses
class Actor:
def __init__ (self,sizeX,sizeY,colour,positionX,positionY):
self.sizeX = sizeX
self.sizeY = sizeY
self.colour = colour
self.positionX = positionX
self.positionY = positionY
def move(self, dx, i):
self.positionX += dx
self.location = i
def draw(self):
pygame.draw.rect(SCREEN, self.colour, (self.positionX, self.positionY, self.sizeX, self.sizeY))
return
class Enemy:
def __init__ (self,sizeX,sizeY,colour,positionX,positionY):
self.sizeX = sizeX
self.sizeY = sizeY
self.colour = colour
self.positionX = positionX
self.positionY = positionY
def move(self, dy, i):
self.positionY += dy
self.location = i
def draw(self):
pygame.draw.rect(SCREEN, self.colour, (self.positionX, self.positionY, self.sizeX, self.sizeY))
return
class Capture(object):
def __init__(self):
self.caption = pygame.display.set_caption('Space Invaders')
self.screen = SCREEN
self.startGame = True
self.gameOver = False
self.enemyCount = 0
def main(self):
clock = pygame.time.Clock()
actor =[]
enemy =[]
#enemy.append(Enemy(snapMult/20,snapMult/20,RED,pos1,SCREEN_H/2))
#print(enemy, sep='\n')
actor.append(Actor(snapMult,snapMult/2,RED,pos2,SCREEN_H-(snapMult/2)))
while True:
if self.startGame:
SCREEN.fill(WHITE)
actor[0].draw()
if self.enemyCount != 5 or self.enemyCount > 5:
num = random.randint(1, 5)
if num == 0:
print (0)
enemy.append(Enemy(snapMult/20,snapMult/20,RED,pos0,SCREEN_H/2))
if num == 1:
print (1)
enemy.append(Enemy(snapMult/20,snapMult/20,RED,pos1,SCREEN_H/2))
if num == 2:
print (2)
enemy.append(Enemy(snapMult/20,snapMult/20,RED,pos2,SCREEN_H/2))
if num == 3:
print (3)
enemy.append(Enemy(snapMult/20,snapMult/20,RED,pos3,SCREEN_H/2))
if num == 4:
print (4)
enemy.append(Enemy(snapMult/20,snapMult/20,RED,pos4,SCREEN_H/2))
print(enemy, sep='\n')
#for i in range(10):
# x = enemy[i]
# x.draw()
#for Enemy in enemy:
# Enemy.draw()
self.enemyCount += 1
for event in pygame.event.get():
if actor[0].positionX != pos4 and (event.type == KEYDOWN) and (event.key == K_d):
actor[0].move(snapMult,0)
if actor[0].positionX != pos0 and(event.type == KEYDOWN) and (event.key == K_a):
actor[0].move(-snapMult,0)
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
fpsclock.tick(FPS)
if __name__ == '__main__':
game = Capture()
game.main()
Use a simple for loop:
for e in enemy:
e.draw()
Another way is to let your classes inherit from Sprite, and use a Group instead of an ordinay list, so you can use the draw() function of the Group.
Also, I don't think you want to call move on every event. You usually update the game state once per loop iteration, since e.g. moving the mouse generates a lot of events.

Pygame - AttributeError: 'int' object has no attribute 'y'

Hello I am currently working on a game in pygame and I am now trying to add a ground, gravity and jump. When I run the code I get an attribute error. Please help if you have a fix, here is the code:
import pygame, sys, time
from pygame.locals import *
pygame.init()
# A few variables
zx = 320
zy = 320
x = 25
y = 320
velX = 0
velY = 0
gravity = .50
ground = 720
clock = pygame.time.Clock()
# Screen
size = 1280, 720
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Moon Survival!')
# Moon
moon = pygame.image.load('images/arena2.jpg')
pygame.display.update()
# Player
class Player(pygame.sprite.Sprite):
global gravity
def __init__(self, x, y):
# Player dimensions and position
self.x = x
self.y = y
self.width = 80
self.height = 80
# Player image and animation
self.i0 = pygame.image.load('images/soldier.png')
self.i1 = pygame.image.load('images/soldier2.png')
self.timeTarget = 10
self.timeNum = 0
self.currentImage = 0
# Jump and gravity
self.vSpeed = 1
self.jumpForce = 8
self.maxVspeed = 3
self.isJumping = False
# Jump inputs
def getInput(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
if not self.isJumping:
self.isJumping = True
# PLayer updates
def update(self):
# Jumping
self.getInput()
self.vSpeed += gravity
if self.vSpeed > self.maxVspeed:
self.vSpeed = self.maxVspeed
self.y += self.vSpeed
if self.y >= ground.y:
self.vSpeed = 0
self.y = ground.y
self.isJumping = False
if self.isJumping:
self.vSpeed += -self.jumpForce
# Animations
#self.timeNum += 1
if (self.timeNum == self.timeTarget):
if (self.currentImage == 0):
self.currentImage = 0
else:
self.currentImage = 0
self.timeNum = 0
self.render()
# Player rendering
def render(self):
if (self.currentImage == 0):
screen.blit(self.i0, (self.x, self.y))
#else:
#screen.blit(self.i1, (self.x, self.y))
# Zombies
zombie = pygame.image.load('images/zombie.png')
pygame.display.update()
# Sprite variables
player = Player(25, 320)
# Game loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Movement
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
velX = -5
if event.key == pygame.K_d:
velX = +5
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
velX = 0
if event.key == pygame.K_d:
velX = 0
# Image blitting
screen.blit(moon, (0,0))
screen.blit(zombie, (zx, zy))
# Movement variables
player.x += velX
player.y += velY
player.update()
# Screen wrap
if player.x >= 1240:
player.x = 1
if player.x <= 0:
player.x = 1240
# Display updating
clock.tick(75)
pygame.display.update()
Any help will be greatly appreciated, thank you.
In some places you try to use int value as object:
ground = 720
self.y = ground.y # error !!!
ground is number int(integer) not object with .y
You could use pygame.Rect()
ground = pygame.Rect(0, 750, 0, 0) # (x, y, width, heigh)
and then you can use ground.x, ground.y, and others - see pygame.Rect().
.
btw: you should move #Movement code, # Movement variablescode, # Screen wrap code into Player class as functions and call that functions in main loop - to make main loop more readable.
# Movement variablescode, # Screen wrap code could be in player.update
# Movement code could be in Player class as event_handler(self, event)
def event_handler(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
velX = -5
elif event.key == pygame.K_d:
velX = +5
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
velX = 0
(you can use elif as above)
Now you can use this in main loop player.event_handler(event)
EDIT:
I made many modifications in your code - but I had no time to finish it.
Player still doesn't jump. But you have 10 moving zombies, pause (press P) and all in classes.
import pygame
import random
# Player
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, gravity):
# Player dimensions and position
self.gravity = gravity
# Player image and animation
self.images = []
self.images.append(pygame.image.load('images/soldier.png'))
self.images.append(pygame.image.load('images/soldier2.png'))
#~ self.images.append(pygame.image.load('ball1.png'))
#~ self.images.append(pygame.image.load('ball2.png'))
self.maxImage = len(self.images)
self.currentImage = 0
#~ self.rect = pygame.Rect(x, y, 80, 80)
self.rect = self.images[0].get_rect()
self.rect.x = x
self.rect.y = y
self.timeTarget = 10
self.timeNum = 0
self.velX = 0
self.velY = 0
# Jump and gravity
self.vSpeed = 1
self.jumpForce = 8
self.maxVspeed = 3
self.isJumping = False
# Jump inputs
def handle_events(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if not self.isJumping:
self.isJumping = True
elif event.key == pygame.K_a:
self.velX = -5
elif event.key == pygame.K_d:
self.velX = +5
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
self.velX = 0
print "isJumping:", self.isJumping
# PLayer updates
def update(self, ground):
# Jumping
self.vSpeed -= self.gravity
if self.vSpeed > self.maxVspeed:
self.vSpeed = self.maxVspeed
self.rect.y -= self.vSpeed
if self.isJumping:
self.vSpeed -= self.jumpForce
if self.rect.bottom >= ground.y:
self.vSpeed = 0
self.rect.bottom = ground.y
self.isJumping = False
# Animations
if self.timeNum == self.timeTarget:
self.currentImage += 1
if self.currentImage >= self.maxImage:
self.currentImage = 0
self.timeNum = 0
self.rect.centerx += self.velX
self.rect.centery += self.velY
# Screen wrap
if self.rect.right > 1280:
self.rect.left = 0
elif self.rect.left < 0:
self.rect.right = 1280
# Player rendering
def render(self, surface):
surface.blit(self.images[self.currentImage], self.rect)
#----------------------------------------------------------------------
class Zombie():
def __init__(self, x, y):
self.image = pygame.image.load('images/zombie.png')
#~ self.image = pygame.image.load('ball2.png')
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.direction_left = True
def update(self, surface_rect):
if self.direction_left:
self.rect.x -= 1
if self.rect.left <= surface_rect.left:
self.direction_left = not self.direction_left
else:
self.rect.x += 1
if self.rect.right >= surface_rect.right:
self.direction_left = not self.direction_left
def render(self, surface):
surface.blit(self.image, self.rect)
#----------------------------------------------------------------------
class Background():
def __init__(self):
self.image = pygame.image.load('images/arena2.jpg')
#~ self.image = pygame.image.load('background.jpg')
self.rect = self.image.get_rect()
def render(self, surface):
surface.blit(self.image, self.rect)
#----------------------------------------------------------------------
class Game():
def __init__(self):
pygame.init()
# A few variables
self.gravity = .50
self.ground = pygame.Rect(0, 720, 0, 0)
# Screen
size = (1280, 720)
self.screen = pygame.display.set_mode(size)
pygame.display.set_caption('Moon Survival!')
# Moon / Background
self.moon = Background()
# Zombies
self.zombies = []
for i in range(10):
self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,720)) )
# Player
self.player = Player(25, 320, self.gravity)
# Font for text
self.font = pygame.font.SysFont(None, 72)
# Pause - center on screen
self.pause_text = self.font.render("PAUSE", -1, (255,0,0))
self.pause_rect = self.pause_text.get_rect(center = self.screen.get_rect().center)
def run(self):
clock = pygame.time.Clock()
# "state machine"
RUNNING = True
PAUSED = False
GAME_OVER = False
# Game loop
while RUNNING:
# (all) Events
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
elif event.key == pygame.K_p:
PAUSED = not PAUSED
# Player/Zomies events
if not PAUSED and not GAME_OVER:
self.player.handle_events(event)
# (all) Movements / Updates
if not PAUSED and not GAME_OVER:
self.player.update(self.ground)
for z in self.zombies:
z.update(self.screen.get_rect())
# (all) Display updating
self.moon.render(self.screen)
for z in self.zombies:
z.render(self.screen)
self.player.render(self.screen)
if PAUSED:
self.screen.blit(self.pause_text, self.pause_rect)
pygame.display.update()
# FTP
clock.tick(75)
# --- the end ---
pygame.quit()
#---------------------------------------------------------------------
Game().run()

Making multiple balls move in pygame

I need to make the balls in this code move around randomly. I am not sure what I am doing wrong. I am new to programming and this may be badly coded so any help would be appreciated. Right now the code makes a character in the middle of the screen that you can move up or down and it makes one ball in the top left corner of the screen that does not move. I want multiple balls on the screen and eventually I want the balls to be moving around randomly and if they collide with the character you lose this simple game.
from pygame import *
import random
class Ball(sprite.Sprite):
def __init__(self, numballs, balls = []):
sprite.Sprite.__init__(self)
self.image = image.load('ball.png')
self.rect = self.image.get_rect()
self.numballs = numballs
self.balls = balls
def multipleBalls(self):
for count in range(self.numballs):
self.balls.append(dict)
self.balls[count] = {'x': 0, 'y': 0, 'xmove': random.randint(1,2), 'ymove':random.randint(1,2)}
def ballMove(self):
for count in range(self.numballs):
self.balls[count]['x'] = self.balls[count]['x'] + self.balls[count]['xmove']
self.balls[count]['y'] = self.balls[count]['y'] + self.balls[count]['ymove']
def ballsOnScreen(self):
for count in range(self.numballs):
self.screen.blit(self.image, (self.balls[count]['x'], self.balls[count]['y']))
def ballBarrier(self):
for count in range(self.numballs):
if self.balls[count]['x'] > 620:
self.balls[count]['xmove'] = random.randint(-2, 0)
if self.balls[count]['x'] < -10:
self.balls[count]['xmove'] = random.randint(0, 2)
if self.balls[count]['y'] > 470:
self.balls[count]['ymove'] = random.randint(-2, 0)
if self.balls[count]['y'] < -10:
self.balls[count]['ymove'] = random.randint(0, 2)
def manageBall(self):
self.multipleBalls()
self.ballsOnScreen()
self.ballMove()
self.ballBarrier()
class Character(sprite.Sprite):
def __init__(self, xy):
sprite.Sprite.__init__(self)
self.image = image.load('character.png')
self.rect = self.image.get_rect()
self.rect.centerx, self.rect.centery = xy
self.movementspeed = 1
self.velocity = 0
def down(self):
self.velocity += self.movementspeed
def up(self):
self.velocity -= self.movementspeed
def characterMove(self, dy):
if self.rect.bottom + dy > 480:
self.rect.bottom = 480
elif self.rect.top + dy < 0:
self.rect.top = 0
else:
self.rect.y += dy
def update(self):
self.characterMove(self.velocity)
class Game(object):
def __init__(self):
init()
key.set_repeat(1, 30)
self.screen = display.set_mode((640, 480))
self.clock = time.Clock()
display.set_caption('Game')
event.set_allowed([QUIT, KEYDOWN, KEYUP])
self.background = Surface((640, 480))
self.background.fill((0,0,0))
self.screen.blit(self.background, (0,0))
display.flip()
self.sprites = sprite.RenderUpdates()
self.character = Character((320, 240))
self.sprites.add(self.character)
self.ball = Ball(5)
self.sprites.add(self.ball)
def run(self):
running = True
while running == True:
self.clock.tick(60)
running = self.handleEvents()
display.set_caption('game %d fps' % self.clock.get_fps())
for sprite in self.sprites:
sprite.update()
self.sprites.clear(self.screen, self.background)
dirty = self.sprites.draw(self.screen)
display.update(dirty)
self.ball.manageBall()
def handleEvents(self):
for e in event.get():
if e.type == QUIT:
return False
elif e.type == KEYDOWN:
if e.key == K_ESCAPE:
return False
if e.key == K_UP:
self.character.up()
if e.key == K_DOWN:
self.character.down()
return True
def main():
game = Game()
game.run()
main()
I've never used the Sprite class before so this was a good exercise. :)
I fixed your code, just change the image paths back to your icon locations and you should be good to go. The print statements might need reformatting if you're running an older version of Python.
I take out the forced call to the Sprite init method in the Ball and Character classes, it won't let me add them to the game.sprites render group. Not sure why.
I'm running Python 3.2.2 and Pygame 1.9.2pre so YMMV. :)
Controls:
UP / DOWN = Move your dude.
R = add a new, random ball.
from pygame import *
import random
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
FPS = 60
class Ball(sprite.Sprite):
def __init__(self, xy = (0,0), xm = 0, ym = 0):
sprite.Sprite.__init__(self)
self.img_load('evil_balloon_32x32.png')
self.rect.centerx, self.rect.centery = xy
self.xmove = xm
self.ymove = ym
def update(self):
self.move()
self.ballBarrier()
def move(self):
self.rect.x += self.xmove
self.rect.y += self.ymove
def img_load(self, filename):
self.image = image.load(filename)
self.rect = self.image.get_rect()
def ballBarrier(self):
"""
Checks to make sure ball is within bounds, adjusts movement speed if it's not
"""
if self.rect.right > SCREEN_WIDTH:
self.xmove = random.randint(-2, 0)
if self.rect.left < 0:
self.xmove = random.randint(0, 2)
if self.rect.bottom > SCREEN_HEIGHT:
self.ymove = random.randint(-2, 0)
if self.rect.top < 0:
self.ymove = random.randint(0, 2)
class ball_manager():
def __init__(self, numballs = 5, balls = []):
self.blist = balls
if numballs > 0:
self.multipleBalls(numballs) # moved this here so balls get init'd only once
def update(self):
"""
Update position of all balls
"""
for ball in self.blist:
self.ballMove(ball)
def add_ball(self, xy = (0,0), xm = 0, ym = 0):
self.blist.append(Ball(xy, xm, ym)) # appends a random ball
def multipleBalls(self, numballs):
for i in range(numballs):
self.add_ball((random.randint(0, SCREEN_WIDTH),
random.randint(0, SCREEN_HEIGHT)),
random.randint(-2,2),
random.randint(-2,2))
class Character(sprite.Sprite):
def __init__(self, xy):
sprite.Sprite.__init__(self)
self.img_load()
self.rect.centerx, self.rect.centery = xy
self.movementspeed = 1
self.velocity = 0
def down(self):
self.velocity += self.movementspeed
def up(self):
self.velocity -= self.movementspeed
def characterMove(self, dy):
if self.rect.bottom + dy > SCREEN_HEIGHT:
self.rect.bottom = SCREEN_HEIGHT
self.velocity = 0
elif self.rect.top + dy < 0:
self.rect.top = 0
self.velocity = 0
else:
self.rect.y += dy
def update(self):
self.characterMove(self.velocity)
def img_load(self):
self.image = image.load("scary_clown_32x32.png")
self.rect = self.image.get_rect()
class Game(object):
def __init__(self):
init()
key.set_repeat(1, 30)
self.screen = display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
self.clock = time.Clock()
display.set_caption('Game')
event.set_allowed([QUIT, KEYDOWN, KEYUP])
self.background = Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
self.background.fill((0,0,0))
self.screen.blit(self.background, (0,0))
display.flip()
self.sprites = sprite.RenderUpdates()
self.character = Character((SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2))
self.sprites.add(self.character)
self.balls = ball_manager(5)
for ball in self.balls.blist:
self.sprites.add(ball)
def run(self):
running = True
while running == True:
self.clock.tick(FPS)
running = self.handleEvents()
display.set_caption('game %d fps' % self.clock.get_fps())
self.sprites.clear(self.screen, self.background)
for sprite in self.sprites:
sprite.update()
dirty = self.sprites.draw(self.screen)
display.update(dirty)
def handleEvents(self):
for e in event.get():
if e.type == QUIT:
return False
elif e.type == KEYDOWN:
if e.key == K_ESCAPE:
return False
if e.key == K_UP:
self.character.up()
if e.key == K_DOWN:
self.character.down()
if e.key == K_r:
self.sprites.add(Ball((random.randint(0, SCREEN_WIDTH),
random.randint(0, SCREEN_HEIGHT)),
random.randint(-2,2),
random.randint(-2,2)))
return True
def main():
game = Game()
game.run()
quit()
main()
sys.exit()