I am trying to build a simple "flappy bird" like game. I am trying to sort all the code into classes and methods. How do I fix this problem? Is it the code not working because of calling some method too early or is it because there's something missing? I would really love it if someone would try to explain to me.
sprites.py:
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((50, 50))
self.image.fill((255, 255, 0))
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = (700 / 2)
self.movex = 0
self.movey = 0
def control(self, x, y):
self.movex += x
self.movey += y
def update(self):
self.rect.x += self.movex
self.rect.y += self.movey
def animate(self):
pass
class Obstacle(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.width = width
self.height = height
main.py:
from sprites import *
import pygame
WIDTH = 700
HEIGHT = 700
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
self.clock = pygame.time.Clock()
self.score = 0
self.running = True
def new(self):
pass
def events(self):
self.game_on = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.game_on = False
self.running = False
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_UP:
self.croc.control(0, -20)
def update(self):
self.croc = Player()
self.all_sprites = pygame.sprite.Group()
self.all_sprites.add(self.croc)
self.all_sprites.update()
def draw(self):
self.screen.fill((0, 0, 0))
self.all_sprites.draw(self.screen)
pygame.display.flip()
game = Game()
while game.running:
game.clock.tick(60)
game.new()
game.events()
game.update()
game.draw()
Thank you
There are 2 mistakes. The Player object is recreated in every frame. Create the player in the constructor of Game rather than in the method update:
class Game:
def __init__(self):
# [...]
self.croc = Player() # <--- ADD
self.all_sprites = pygame.sprite.Group() # <--- ADD
self.all_sprites.add(self.croc) # <--- ADD
def update(self):
# self.croc = Player() # <--- DELETE
# self.all_sprites = pygame.sprite.Group() # <--- DELETE
# self.all_sprites.add(self.croc) # <--- DELETE
self.all_sprites.update()
There is a type in the event loop. You've to get the key from the .key attribute rather than the .type attriburte:
if event.type == pygame.K_UP:
if event.key == pygame.K_UP:
Complete code:
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((50, 50))
self.image.fill((255, 255, 0))
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = (700 / 2)
self.movex = 0
self.movey = 0
def control(self, x, y):
self.movex += x
self.movey += y
def update(self):
self.rect.x += self.movex
self.rect.y += self.movey
def animate(self):
pass
class Obstacle(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.width = width
self.height = height
WIDTH = 700
HEIGHT = 700
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
self.clock = pygame.time.Clock()
self.score = 0
self.running = True
self.croc = Player()
self.all_sprites = pygame.sprite.Group()
self.all_sprites.add(self.croc)
def new(self):
pass
def events(self):
self.game_on = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.game_on = False
self.running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
self.croc.control(0, -20)
def update(self):
self.all_sprites.update()
def draw(self):
self.screen.fill((0, 0, 0))
self.all_sprites.draw(self.screen)
pygame.display.flip()
game = Game()
while game.running:
game.clock.tick(60)
game.new()
game.events()
game.update()
game.draw()
Related
This question already has answers here:
Spawning multiple instances of the same object concurrently in python
(1 answer)
Issues with pygame.time.get_ticks() [duplicate]
(1 answer)
How to make instances spawn automatically around the player? [duplicate]
(1 answer)
Closed 1 year ago.
I am creating a game similar to the "Internet T-rex Game", Right now my game creates enemy blocks according to how many I manually create. I want it to be created by itself. My game is not fully completed yet, so please ignore the empty functions.
Heres my main.py
import pygame as pg
import random
from settings import *
from sprites import *
from os import path
class Game(object):
"""docstring for Game"""
def __init__(self):
# initialise game
global points , game_speed
pg.init()
self.screen = pg.display.set_mode((s_HEIGHT , s_WIDTH))
pg.display.set_caption(TITLE)
self.icon = pg.image.load("C:/Users/DELL/Documents/Jump Cube/Img/cube.png")
pg.display.set_icon(self.icon)
self.clock = pg.time.Clock()
self.running = True
self.game_speed = 14
points = 0
font = pygame.font.Font('freesansbold.ttf', 20)
self.load_data()
def load_data(self):
self.dir = path.dirname(__file__)
img_dir = path.join(self.dir, "Img")
#load spritesheet image
self.spritesheet = Spritesheet(path.join(img_dir, SPRITESHEET))
def new(self):
# Stars a new game
self.all_sprites = pg.sprite.Group()
self.platforms = pg.sprite.Group()
self.ene = pg.sprite.Group()
self.player = Player(self)
self.all_sprites.add(self.player)
pl = Platform(0, s_HEIGHT - 230, 800, 40)
en1 = Enemy(700, 517, 50, 50)
en2 = Enemy(600, 517, 50, 50)
en3 = Enemy(500, 517, 50, 50)
self.all_sprites.add(pl)
self.platforms.add(pl)
self.all_sprites.add([en1, en2, en3])
self.ene.add([en1, en2, en3])
self.Run()
def Run(self):
# Game Loop
self.playing = True
while self.playing:
self.clock.tick(FPS)
self.Events()
self.Update()
self.Draw()
self.score()
def Update(self):
# Game Loop - Update
self.all_sprites.update()
hits = pg.sprite.spritecollide(self.player, self.platforms, False)
if hits:
self.player.pos.y = hits[0].rect.top
self.player.vel.y = 0
pass
def score(self):
global points , game_speed
points += 1
if points % 100 == 0:
game_speed += 1
text = font.render("Points : " + str(points), True, WHITE)
textrec = text.get_rect()
textrec.center = (700, 50)
self.screen.blit(text, textrec)
def Events(self):
# Game Loop - Events
for event in pg.event.get():
if event.type == pg.QUIT:
if self.playing:
self.playing = False
self.running = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_SPACE:
self.player.jump()
if event.type == pg.KEYDOWN:
if event.key == pg.K_RIGHT:
self.player.mover()
elif event.key == pg.K_LEFT:
self.player.movel()
def Draw(self):
# Game Loop - Draw
self.screen.fill(BLACK)
self.score()
self.all_sprites.draw(self.screen)
pg.display.update()
pass
def start_screen(self):
# shows the start screen
pass
def end_screen(self):
# shows the end screen
pass
g = Game()
g.start_screen()
while g.running:
g.new()
g.end_screen()
pg.quit()
sprites.py
import pygame as pg
from settings import *
vec = pg.math.Vector2
class Spritesheet():
# utility class for laoding and parsing spritesheets
def __init__(self, filename):
self.spritesheet = pg.image.load(filename).convert()
def get_image(self, x, y, width, height):
# grabs images from large spritesheets
image = pg.Surface((width, height))
image.blit(self.spritesheet, (0,0), (x, y, width, height))
image = pg.transform.scale(image , (50, 85))
return image
class Player(pg.sprite.Sprite):
def __init__(self, game):
pg.sprite.Sprite.__init__(self)
self.game = game
self.image = self.game.spritesheet.get_image(614, 1063, 120, 191)
self.image.set_colorkey(BLACK1)
self.rect = self.image.get_rect()
self.rect.center = (s_WIDTH / 2, s_HEIGHT / 2)
self.pos = vec(100, 600)
self.vel = (0, 0)
self.acc = (0, 0)
def jump(self):
#jump only if standing on plat
self.rect.y += 1
hits = pg.sprite.spritecollide(self, self.game.platforms, False)
self.rect.y -= 1
if hits:
self.vel.y = -8
def mover(self):
#move right
self.vel.x = 5
def movel(self):
#move right
self.vel.x = -5
def update(self):
self.acc = vec(0, PLAYER_GRAV)
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
self.rect.midbottom = self.pos
class Platform(pg.sprite.Sprite):
def __init__(self, x, y, w, h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w, h))
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Enemy(pg.sprite.Sprite):
def __init__(self, x, y, w1, h1):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w1, h1))
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self):
self.rect.x -= game_speed
settings.py
import pygame
pygame.init()
#game options
TITLE = "Ninja Jump"
s_WIDTH = 600
s_HEIGHT = 800
FPS = 60
game_speed = 14
points = 0
font = pygame.font.Font('freesansbold.ttf', 20)
SPRITESHEET = "spritesheet_jumper.png"
#player properties
PLAYER_ACC = 0.5
PLAYER_GRAV = 0.3
#colors
WHITE = (199, 198, 196)
BLACK = (23, 23, 23)
GRAY = (121, 121, 120)
GREEN = (72, 161, 77)
BLACK1 = (0,0,0)
GRAY1 = (162, 162, 162)
Thanks for any help and let me know if the problem needs more clarification.
Spawn the enemies by a time interval. In pygame the system time can be obtained by calling pygame.time.get_ticks(), which returns the number of milliseconds since pygame.init() was called. Define a time interval to spawn enemies. Continuously compare the current time with the time when the next enemy must appear. When the time comes, spawn an enemy and set the time the next enemy must spawn:
class Game(object):
# [...]
def Run(self):
self.next_enemy_time = 0
self.enemy_time_interval = 1000 # 1000 milliseconds == 1 second
# Game Loop
self.playing = True
while self.playing:
current_time = pygame.time.get_ticks()
if current_time > self.next_enemy_time:
self.next_enemy_time += self.enemy_time_interval
new_enemy = Enemy(700, 517, 50, 50)
self.all_sprites.add(new_enemy)
self.ene.add(new_enemy)
self.clock.tick(FPS)
self.Events()
self.Update()
self.Draw()
self.score()
In my game I can place cannons anywhere on the screen. I want my cannons to be able to fire bullets and the bullets should be reset after they travel 100 pixels. Given below is my cannon class, I'm still new to OOP so I require some help however I wasn't able to accomplish this task using lists either. Thank you for your help.
class Cannon():
global cannon_list
global bullet_list
def __init__(self, x, y, track, old_x):
self.x = x
self.y = y
self.track = track
self.old_x = old_x
def spawnBullet(self):
for j in bullet_list:
self.old_x = self.x
self.track = j[2]
screen.blit(bullet, (j[0], j[1]))
def moveBullet(self):
if self.x <= self.track:
self.x += 3
def resetBullet(self):
if self.x >= self.track:
self.x = self.old_x
def spawnCannon(self):
for i in cannon_list:
screen.blit(cannon, i)
Using the cannon class. this is under redrawGamewindow.
for j in bullet_list:
cannonsAndBullets = Cannon(j[0], j[1], j[2], j[0])
cannonsAndBullets.spawnCannon()
cannonsAndBullets.spawnBullet()
cannonsAndBullets.moveBullet()
cannonsAndBullets.resetBullet()
Given below is what I have appended into bullet_list and cannon_list. x an y are the position of my player
cannon_list.append([x,y])
bullet_list.append([x,(y+25),100, x])
Edits in my class
class Cannon():
global cannon_list
global bullet_list
def __init__(self, x, y, track, old_x):
self.x = x
self.y = y
self.track = track
self.old_x = old_x
def spawnBullet(self):
# for j in bullet_list:
# self.x, self.y, self.track, self.old_x = j
screen.blit(bullet, (self.x, self.y))
def moveBullet(self):
# for j in bullet_list:
# self.x, self.y, self.track, self.old_x = j
if self.track <= 100:
print(self.track)
self.track += 3
self.x += 3
def resetBullet(self):
# for j in bullet_list:
# self.x, self.y, self.track, self.old_x = j
if self.track >= 100:
print(self.track)
self.x = self.old_x
def spawnCannon(self):
for i in cannon_list:
screen.blit(cannon, i)
Let's discard everything and start from scratch and make use of pygame features like sprites and vector math.
We begin with a basic skeleton of a pygame game, a simple window:
import pygame
def main():
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
screen.fill(pygame.Color('grey'))
pygame.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()
Now, we want to place some Sprites. Let's create a Sprite class that represents the cannons, and let's place them with the mouse:
import pygame
class Cannon(pygame.sprite.Sprite):
def __init__(self, pos, *grps):
super().__init__(*grps)
self.image = pygame.Surface((32, 32))
self.image.fill(pygame.Color('darkred'))
self.rect = self.image.get_rect(center=pos)
def main():
all_sprites = pygame.sprite.Group()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
if e.type == pygame.MOUSEBUTTONDOWN:
Cannon(e.pos, all_sprites)
all_sprites.update()
screen.fill(pygame.Color('grey'))
all_sprites.draw(screen)
pygame.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()
Now we want the cannons to shoot bullets. To do that, we're making use of some OOP features, like polymorphism. Bullets and cannons are different types, but they provide the same interface: update and draw. And that's it. Note how our mainloop does not need to know what types exactly our sprites are.
We also make sure that all the logic for bullets is in the Bullet class, and all the logic for the cannon is in the Cannon class:
import pygame
class Bullet(pygame.sprite.Sprite):
def __init__(self, pos, *grps):
super().__init__(*grps)
self.image = pygame.Surface((4, 4))
self.image.fill(pygame.Color('black'))
self.rect = self.image.get_rect(center=pos)
self.pos = pygame.Vector2(pos)
self.travelled = pygame.Vector2(0, 0)
direction = pygame.Vector2(pygame.mouse.get_pos()) - self.pos
if direction.length() > 0:
self.direction = direction.normalize()
else:
self.kill()
def update(self, dt):
v = self.direction * dt / 5
self.pos += v
self.travelled += v
self.rect.center = self.pos
if self.travelled.length() > 100:
self.kill()
class Cannon(pygame.sprite.Sprite):
def __init__(self, pos, *grps):
super().__init__(*grps)
self.image = pygame.Surface((32, 32))
self.image.fill(pygame.Color('darkred'))
self.rect = self.image.get_rect(center=pos)
self.timer = 200
def update(self, dt):
self.timer = max(self.timer - dt, 0)
if self.timer == 0:
self.timer = 200
Bullet(self.rect.center, self.groups()[0])
def main():
all_sprites = pygame.sprite.Group()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
dt = 1
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
if e.type == pygame.MOUSEBUTTONDOWN:
Cannon(e.pos, all_sprites)
all_sprites.update(dt)
screen.fill(pygame.Color('grey'))
all_sprites.draw(screen)
pygame.display.flip()
dt = clock.tick(60)
if __name__ == '__main__':
main()
Using a vector and simply adding the distance travelled each frame makes it easy to check for each Bullet if it already travelled 100 pixels. If true, simply calling kill will remove it.
I've tried numerous things to let my bullets collide with my mob, but it doesn't work. The bullet just goes straight through the mob. I also tried spritecollide and groupcollide codes, but they all failed. Maybe i'm putting my code in the wrong line or the wrong place. I also want the bullet and mob to be removed from the list.
import pygame
import random
import math
GRAD = math.pi / 180
black = (0,0,0)
Bulleti = pygame.image.load('bullet.png')
Monster = pygame.image.load('Monster1re.png')
class Config(object):
fullscreen = True
width = 1366
height = 768
fps = 60
class Player(pygame.sprite.Sprite):
maxrotate = 180
down = (pygame.K_DOWN)
up = (pygame.K_UP)
def __init__(self, startpos=(102,579), angle=0):
super().__init__()
self.pos = list(startpos)
self.image = pygame.image.load('BigShagHoofdzzz.gif')
self.orig_image = self.image
self.rect = self.image.get_rect(center=startpos)
self.angle = angle
def update(self, seconds):
pressedkeys = pygame.key.get_pressed()
if pressedkeys[self.down]:
self.angle -= 2
self.rotate_image()
if pressedkeys[self.up]:
self.angle += 2
self.rotate_image()
def rotate_image(self):
self.image = pygame.transform.rotate(self.orig_image, self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
class Mob(pygame.sprite.Sprite):
def __init__(self, image):
super().__init__()
self.image = image
self.rect = self.image.get_rect()
self.rect.x = 1400
self.rect.y = random.randrange(500,600)
self.speedy = random.randrange(-8, -1)
def update(self):
self.rect.x += self.speedy
if self.rect.x < -100 :
self.rect.x = 1400
self.speedy = random.randrange(-8, -1)
class Bullet(pygame.sprite.Sprite):
"""This class represents the bullet."""
def __init__(self, pos, angle, image):
super().__init__()
self.image = image
self.image = pygame.transform.rotate(self.image, angle)
self.rect = self.image.get_rect()
speed = 15
self.velocity_x = math.cos(math.radians(-angle)) * speed
self.velocity_y = math.sin(math.radians(-angle)) * speed
self.pos = list(pos)
def update(self):
""" Move the bullet. """
self.pos[0] += self.velocity_x
self.pos[1] += self.velocity_y
self.rect.center = self.pos
player = Player()
#this is the mob group
mobs = []
for x in range(0,10):
mob = Mob(Monster)
mobs.append(mob)
print(mobs)
#sprite lists
bullet_list = pygame.sprite.Group()
all_sprites_list = pygame.sprite.Group()
allgroup = pygame.sprite.LayeredUpdates()
allgroup.add(player)
for mob in mobs:
all_sprites_list.add(mob)
def main():
#game
pygame.mixer.pre_init(44100, -16, 1, 512)
pygame.mixer.init()
pygame.init()
screen=pygame.display.set_mode((Config.width, Config.height),
pygame.FULLSCREEN)
background = pygame.image.load('BGGameBig.png')
sound = pygame.mixer.Sound("shoot2.wav")
clock = pygame.time.Clock()
FPS = Config.fps
mainloop = True
while mainloop:
millisecond = clock.tick(Config.fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
mainloop = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
mainloop = False
if event.key == pygame.K_SPACE: #Bullet schiet knop op space
# Pass the position and angle of the player.
bullet = Bullet(player.rect.center, player.angle,
Bulleti)
all_sprites_list.add(bullet)
bullet_list.add(bullet)
sound.play()
if event.key == pygame.K_ESCAPE:
mailoop = False
pygame.display.set_caption("hi")
allgroup.update(millisecond)
all_sprites_list.update()
for bullet in bullet_list:
if bullet.rect.x > 1380:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
#this is the code for collission
hits = pygame.sprite.groupcollide(bullet_list, mobs, True, True)
screen.blit(background, (0,0))
allgroup.draw(screen)
all_sprites_list.draw(screen)
pygame.display.flip()
if __name__ == '__main__':
main()
pygame.quit()
if anyone could help me out on this one it would really be appreciated. I spent alot of time working on the solution but I haven't found any yet. Watched alot of youtubers and did the same thing but it just won't work.
I get a different error when I run the program, an AttributeError caused by this line hits = pygame.sprite.groupcollide(bullet_list, mobs, True, True). That happens because the mobs list should be a pygame.sprite.Group.
mobs = pygame.sprite.Group()
for x in range(0,10):
mob = Mob(Monster)
mobs.add(mob)
After I changed this part of the code, it worked correctly.
Here is my code. How can I move my class Player sprite? Would I add an x,y to my def __init__? like def __init__(self, x, y)? Thanks for the answers,
import pygame as pg
WIDTH = 800
HEIGHT = 600
CLOCK = pg.time.Clock()
FPS = 60
GREEN = (0, 255, 0)
LIGHTBLUE = (20, 130, 230)
BGCOLOR = LIGHTBLUE
class Player(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((50, 50))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.center = ((WIDTH / 2, HEIGHT / 2))
self.x = x
self.y = y
player = Player()
pg.init()
screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption('The Moon Smiles Back')
running = True
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_ESCAPE:
running = False
all_sprites = pg.sprite.Group()
all_sprites.add(player)
all_sprites.update()
screen.fill(BGCOLOR)
all_sprites.draw(screen)
pg.display.flip()
CLOCK.tick(FPS)
pg.quit()
Add two attributes to the Player class to store the current velocity of the player. In the update method, add the velocities to the x and y attributes and then set the rect to the new position.
class Player(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((50, 50))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.x = x
self.y = y
self.velocity_x = 0
self.velocity_y = 0
def update(self):
self.x += self.velocity_x
self.y += self.velocity_y
self.rect.center = (self.x, self.y)
To move the player to the right, set the player.velocity_x to the desired speed if the 'd' key is pressed (in this example), and back to 0 if the key is released. Do the same for the other directions.
if event.type == pg.KEYDOWN:
if event.key == pg.K_ESCAPE:
running = False
elif event.key == pg.K_d:
player.velocity_x = 3
elif event.type == pg.KEYUP:
if event.key == pg.K_d:
player.velocity_x = 0
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
i'm having a problem with my code. So, I want to create a game, in Pygame, where the bananas fall from the sky, and the monkey have to grab them. I'm having quite a hard time creating a collision between those two (spent hours trying already).
So, this is my code:
import pygame, sys, random, time, os
from pygame.locals import *
#Variáveis necessárias
banana_speed = 5
monkey_speed = 20
WIDTH = 800
HEIGHT = 800
pontos = 0
vidas = 3
#Nome do jogo
pygame.display.set_caption("Catch the fruit")
#Tamanho do ecrã do jogo
screen = pygame.display.set_mode((WIDTH, HEIGHT))
class Macaco(pygame.sprite.Sprite):
def __init__(self):
self.image = pygame.image.load('monkey.png')
self.rect = self.image
self.x = 300
self.y = 640
def keyboard(self):
key = pygame.key.get_pressed()
if key[pygame.K_RIGHT]:
self.x += monkey_speed
elif key[pygame.K_LEFT]:
self.x -= monkey_speed
def draw (self, screen):
screen.blit(self.rect, (self.x, self.y))
class Background(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
class Banana(pygame.sprite.Sprite):
def __init__(self):
self.image = pygame.image.load('banana.png')
self.rect = self.image
self.x = random.randrange(0,WIDTH)
self.y = -50
def draw(self, screen):
self.y = self.y + banana_speed
screen.blit(self.rect,(self.x, self.y))
#Funções necessárias para o Loop
macaco = Macaco()
banana = Banana()
Background = Background('background.png', [0,0])
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
while vidas > 0:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
screen.blit(Background.image, Background.rect)
pressed_keys = pygame.key.get_pressed()
macaco.keyboard()
macaco.draw(screen)
banana.draw(screen)
pygame.display.update()
edit:
So i'm trying another solution and did this:
import pygame, sys, random, time, os
from pygame.locals import *
#Variáveis necessárias
banana_speed = 5
monkey_speed = 20
WIDTH = 800
HEIGHT = 800
pontos = 0
vidas = 3
green = (0, 0 , 255)
#Nome do jogo
pygame.display.set_caption("Catch the fruit")
#Tamanho do ecrã do jogo
screen = pygame.display.set_mode((WIDTH, HEIGHT))
class Macaco(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.rect = pygame.image.load('monkey.png')
self.image = pygame.Surface([WIDTH, HEIGHT])
self.x = 300
self.y = 640
self.image.fill(green)
def keyboard(self):
key = pygame.key.get_pressed()
if key[pygame.K_RIGHT]:
self.x += monkey_speed
elif key[pygame.K_LEFT]:
self.x -= monkey_speed
def draw (self, screen):
screen.blit(self.rect, (self.x, self.y))
class Background(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
class Banana(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.rect = pygame.image.load('banana.png')
self.image = pygame.Surface([WIDTH, HEIGHT])
self.x = random.randrange(0, WIDTH)
self.y = -50
def draw(self, screen):
self.y = self.y + banana_speed
screen.blit(self.rect,(self.x, self.y))
#Funções necessárias para o Loop
macaco = Macaco()
banana = Banana()
Background = Background('background.png', [0,0])
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
while vidas > 0:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
screen.blit(Background.image, Background.rect)
pressed_keys = pygame.key.get_pressed()
macaco.keyboard()
macaco.draw(screen)
banana.draw(screen)
blocks_hit_list = pygame.sprite.spritecollide(macaco, banana, True)
for blocks in blocks_hit_list:
pontos +=1
pygame.display.update()
Could you give me some help please?
I've created two sprite groups: all_sprites which contains all sprites and is used to update and draw them with just two lines of code, and the bananas group which is used to check for collisions between the macaco and the bananas. Then we need the pygame.sprite.spritecollide function to get the collided sprites. You have to pass a sprite instance and a sprite group and it'll check for you if the sprite has collided with the sprites in the group. It returns the collided bananas as a list over which you can iterate to do something with them or for example to increment a points counter.
You have to call the __init__ method of the parent class in your sprites to be able to use them correctly with sprite groups (do that with the super function super().__init__() (in Python 2 super(Macaco, self).__init__()).
To update the positions of your sprites, set their topleft (or center) attribute to the new x, y coordinates.
To get a rect from an image call self.rect = self.image.get_rect().
import sys
import random
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 800))
class Macaco(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((30, 30))
self.image.fill((190, 140, 20))
self.rect = self.image.get_rect()
self.x = 300
self.y = 640
self.speed = 20
def keyboard(self, keys):
if keys[pygame.K_RIGHT]:
self.x += self.speed
elif keys[pygame.K_LEFT]:
self.x -= self.speed
def update(self):
self.rect.topleft = self.x, self.y
class Banana(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((30, 30))
self.image.fill((230, 230, 40))
self.rect = self.image.get_rect()
self.x = random.randrange(0, 770)
self.y = -50
self.speed = 5
def update(self):
self.y += self.speed
self.rect.topleft = self.x, self.y
macaco = Macaco()
banana = Banana()
all_sprites = pygame.sprite.Group(macaco, banana)
bananas = pygame.sprite.Group(banana)
clock = pygame.time.Clock()
running = True
while running:
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
keys = pygame.key.get_pressed()
macaco.keyboard(keys)
all_sprites.update()
# Collision detection. Check if macaco collided with bananas group,
# return collided bananas as a list. dokill argument is True, so
# that collided bananas will be deleted.
collided_bananas = pygame.sprite.spritecollide(macaco, bananas, True)
for collided_banana in collided_bananas:
print('Collision.')
screen.fill((70, 40, 70))
all_sprites.draw(screen)
pygame.display.update()
clock.tick(30)
pygame.quit()
sys.exit()