I am making platformer game with coin boxes and coins. I want there to be a coin jump out when the player hits the coin box. Whenever the player hits the box, I want the box state to be "BUMPED". I was planning on doing this by calling a method (def start_bump) from the class to start a bump. But I don't know how to do that. Can anyone help?
class CoinBox(pygame.sprite.Sprite):
"""Coin box sprite"""
def __init__(self, x, y, contents='coin', group=None):
pygame.sprite.Sprite.__init__(self)
self.sprite_sheet = SpriteSheet('tiles_spritesheet.png')
self.frames = []
self.setup_frames()
self.frame_index = 0
self.image = self.frames[self.frame_index]
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.first_half = True
self.state = RESTING
self.rest_height = y
self.gravity = 1.2
self.y_vel = 0
def setup_frames(self):
"""Create frame list"""
self.frames.append(self.get_image(0, 720, 70, 70))
self.frames.append(self.get_image(0, 576, 70, 70))
self.frames.append(self.get_image(0, 648, 70, 70))
def update(self):
"""Update coin box behavior"""
self.handle_states()
def handle_states(self):
"""Determine action based on RESTING, BUMPED or OPENED
state"""
if self.state == RESTING:
self.resting()
elif self.state == BUMPED:
self.bumped()
elif self.state == OPENED:
self.opened()
def bumped(self):
"""Action after Mario has bumped the box from below"""
self.rect.y += self.y_vel
self.y_vel += self.gravity
if self.rect.y > self.rest_height + 5:
self.rect.y = self.rest_height
self.state = OPENED
self.frame_index = 2
self.image = self.frames[self.frame_index]
def start_bump(self):
"""Transitions box into BUMPED state"""
self.y_vel = -6
self.state = BUMPED
if self.contents == 'coin':
self.group.add(Coin(self.rect.centerx, self.rect.y))
def opened(self):
"""Placeholder for OPENED state"""
pass
class Coin(pygame.sprite.Sprite):
"""Coins found in boxes and bricks"""
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.sprite_sheet = SpriteSheet('items1_spritesheet.png')
self.frames = []
self.frame_index = 0
self.animation_timer = 0
self.state = SPIN
self.setup_frames()
self.image = self.frames[self.frame_index]
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.bottom = y - 5
self.gravity = 1
self.y_vel = -15
self.initial_height = self.rect.bottom - 5
def get_image(self, x, y, width, height):
"""Get the image frames from the sprite sheet"""
image = pygame.Surface([width, height]).convert()
rect = image.get_rect()
image.blit(self.sprite_sheet, (0, 0), (x, y, width, height))
image.set_colorkey(BLACK)
image = pygame.transform.scale(image, (int(rect.width * 0.9), int(rect.height * 0.9)))
return image
def setup_frames(self):
"""create the frame list"""
self.frames.append(self.get_image(288, 432, 70, 70))
def update(self):
"""Update the coin's behavior"""
if self.state == SPIN:
self.spinning()
def jump(self):
"""Action when the coin is in the SPIN state"""
self.image = self.frames[self.frame_index]
self.rect.y += self.y_vel
self.y_vel += self.gravity
if self.rect.bottom > self.initial_height:
self.kill()
class Level(object):
""" This is a generic super-class used to define a level and can a child class for each level with level-specific
info """
# Methods
def __init__(self, player):
""" Level constructor """
# Lists of sprites used in all levels
self.coin_box_list = None
self.coin_list = None
# Creates sprite groups
self.coin_box_list = pygame.sprite.Group()
self.coin_list = pygame.sprite.Group()
self.player = player
# Background image
self.background = None
# How far this world has been scrolled left/right
self.world_shift = 0
def update(self):
""" Update everything in the level."""
# Updates the sprites
self.coin_box_list.update()
self.coin_list.update()
def draw(self, screen):
""" Draw everything on this level. """
# Draws the background
width = self.background.get_width()
screen.blit(self.background, (self.world_shift // 3, 0))
screen.blit(self.background, ((self.world_shift // 3 + width), 0))
# "self.world_shift // 3 + width". The background shifts slower than the sprites to show depth.
# Draws the sprites
self.coin_box_list.draw(screen)
self.coin_list.draw(screen)
def shift_world(self, shift_x):
""" Shifts the world when the player moves """
# Shifts all the coin blocks in the list
for coin_box in self.coin_box_list:
coin_box.rect.x += shift_x
for coin in self.coin_list:
coin.rect.x += shift_x
class Level01(Level):
""" Creates Level 1. """
# Methods
def __init__(self, player):
# Calls the parent constructor
Level.__init__(self, player)
level_coin_boxes = CoinBox(500, 250, COIN, self.coin_list)
self.coin_box_list.add(level_coin_boxes)
class Player(pygame.sprite.Sprite):
""" This class represents the bar at the bottom that the player
controls. """
# -- Methods
def __init__(self):
""" Constructor function """
# Call the parent's constructor
super().__init__()
# -- Attributes
# List of sprites we can bump against
self.level = None
def update(self):
""" Moves the player """
# Move left/right
self.rect.x += self.change_x
# Checks if the player hits a coin block on the x-axis
coin_box_hit_list = pygame.sprite.spritecollide(self, self.level.coin_box_list, False)
for coin_box in coin_box_hit_list:
if self.change_x > 0:
# If we are moving right, set our right side to the left side of the coin block we hit
self.rect.right = coin_box.rect.left
elif self.change_x < 0:
# Otherwise if we are moving left, do the opposite.
self.rect.left = coin_box.rect.right
# Move up/down
self.rect.y += self.change_y
# Checks if the player hits a coin block on the y-axis
coin_box_hit_list = pygame.sprite.spritecollide(self, self.level.coin_box_list, False)
for coin_box in coin_box_hit_list:
if self.change_y > 0:
# If we are moving down, set our bottom side to the top side of the platform we hit
self.rect.bottom = coin_box.rect.top
elif self.change_y < 0:
# Otherwise if we are moving up, do the opposite
self.rect.top = coin_box.rect.bottom
# Stop our vertical movement
self.change_y = 0