0

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
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Blazian444
  • 131
  • 9
  • 1
    To answer your question you call it from the instance, for example `my_box` is an instance of your class: `my_box.change_state("BUMPED")`. But as I see in your code the method `start_bump` is already updating the status in the line `self.state = "BUMPED"` – palvarez Aug 11 '19 at 18:14
  • Yeah, so should I call that method? – Blazian444 Aug 11 '19 at 18:21
  • 2
    Oh sorry didn't see that in you edited the name of the already defined method. Yes, just call it with `coin_box.start_bump()`. – palvarez Aug 11 '19 at 18:30

0 Answers0