You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
5.2 KiB
216 lines
5.2 KiB
9 months ago
|
|
||
|
|
||
|
|
||
|
import pygame as pg
|
||
|
from .. import setup
|
||
|
from .. import constants as c
|
||
|
|
||
|
|
||
|
class Enemy(pg.sprite.Sprite):
|
||
|
"""Base class for all enemies (Goombas, Koopas, etc.)"""
|
||
|
def __init__(self):
|
||
|
pg.sprite.Sprite.__init__(self)
|
||
|
|
||
|
|
||
|
def setup_enemy(self, x, y, direction, name, setup_frames):
|
||
|
"""Sets up various values for enemy"""
|
||
|
self.sprite_sheet = setup.GFX['smb_enemies_sheet']
|
||
|
self.frames = []
|
||
|
self.frame_index = 0
|
||
|
self.animate_timer = 0
|
||
|
self.death_timer = 0
|
||
|
self.gravity = 1.5
|
||
|
self.state = c.WALK
|
||
|
|
||
|
self.name = name
|
||
|
self.direction = direction
|
||
|
setup_frames()
|
||
|
|
||
|
self.image = self.frames[self.frame_index]
|
||
|
self.rect = self.image.get_rect()
|
||
|
self.rect.x = x
|
||
|
self.rect.bottom = y
|
||
|
self.set_velocity()
|
||
|
|
||
|
|
||
|
def set_velocity(self):
|
||
|
"""Sets velocity vector based on direction"""
|
||
|
if self.direction == c.LEFT:
|
||
|
self.x_vel = -2
|
||
|
else:
|
||
|
self.x_vel = 2
|
||
|
|
||
|
self.y_vel = 0
|
||
|
|
||
|
|
||
|
def get_image(self, x, y, width, height):
|
||
|
"""Get the image frames from the sprite sheet"""
|
||
|
image = pg.Surface([width, height]).convert()
|
||
|
rect = image.get_rect()
|
||
|
|
||
|
image.blit(self.sprite_sheet, (0, 0), (x, y, width, height))
|
||
|
image.set_colorkey(c.BLACK)
|
||
|
|
||
|
|
||
|
image = pg.transform.scale(image,
|
||
|
(int(rect.width*c.SIZE_MULTIPLIER),
|
||
|
int(rect.height*c.SIZE_MULTIPLIER)))
|
||
|
return image
|
||
|
|
||
|
|
||
|
def handle_state(self):
|
||
|
"""Enemy behavior based on state"""
|
||
|
if self.state == c.WALK:
|
||
|
self.walking()
|
||
|
elif self.state == c.FALL:
|
||
|
self.falling()
|
||
|
elif self.state == c.JUMPED_ON:
|
||
|
self.jumped_on()
|
||
|
elif self.state == c.SHELL_SLIDE:
|
||
|
self.shell_sliding()
|
||
|
elif self.state == c.DEATH_JUMP:
|
||
|
self.death_jumping()
|
||
|
|
||
|
|
||
|
def walking(self):
|
||
|
"""Default state of moving sideways"""
|
||
|
if (self.current_time - self.animate_timer) > 125:
|
||
|
if self.frame_index == 0:
|
||
|
self.frame_index += 1
|
||
|
elif self.frame_index == 1:
|
||
|
self.frame_index = 0
|
||
|
|
||
|
self.animate_timer = self.current_time
|
||
|
|
||
|
|
||
|
def falling(self):
|
||
|
"""For when it falls off a ledge"""
|
||
|
if self.y_vel < 10:
|
||
|
self.y_vel += self.gravity
|
||
|
|
||
|
|
||
|
def jumped_on(self):
|
||
|
"""Placeholder for when the enemy is stomped on"""
|
||
|
pass
|
||
|
|
||
|
|
||
|
def death_jumping(self):
|
||
|
"""Death animation"""
|
||
|
self.rect.y += self.y_vel
|
||
|
self.rect.x += self.x_vel
|
||
|
self.y_vel += self.gravity
|
||
|
|
||
|
if self.rect.y > 600:
|
||
|
self.kill()
|
||
|
|
||
|
|
||
|
def start_death_jump(self, direction):
|
||
|
"""Transitions enemy into a DEATH JUMP state"""
|
||
|
self.y_vel = -8
|
||
|
if direction == c.RIGHT:
|
||
|
self.x_vel = 2
|
||
|
else:
|
||
|
self.x_vel = -2
|
||
|
self.gravity = .5
|
||
|
self.frame_index = 3
|
||
|
self.image = self.frames[self.frame_index]
|
||
|
self.state = c.DEATH_JUMP
|
||
|
|
||
|
|
||
|
def animation(self):
|
||
|
"""Basic animation, switching between two frames"""
|
||
|
self.image = self.frames[self.frame_index]
|
||
|
|
||
|
|
||
|
def update(self, game_info, *args):
|
||
|
"""Updates enemy behavior"""
|
||
|
self.current_time = game_info[c.CURRENT_TIME]
|
||
|
self.handle_state()
|
||
|
self.animation()
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
class Goomba(Enemy):
|
||
|
|
||
|
def __init__(self, y=c.GROUND_HEIGHT, x=0, direction=c.LEFT, name='goomba'):
|
||
|
Enemy.__init__(self)
|
||
|
self.setup_enemy(x, y, direction, name, self.setup_frames)
|
||
|
|
||
|
|
||
|
def setup_frames(self):
|
||
|
"""Put the image frames in a list to be animated"""
|
||
|
|
||
|
self.frames.append(
|
||
|
self.get_image(0, 4, 16, 16))
|
||
|
self.frames.append(
|
||
|
self.get_image(30, 4, 16, 16))
|
||
|
self.frames.append(
|
||
|
self.get_image(61, 0, 16, 16))
|
||
|
self.frames.append(pg.transform.flip(self.frames[1], False, True))
|
||
|
|
||
|
|
||
|
def jumped_on(self):
|
||
|
"""When Mario squishes him"""
|
||
|
self.frame_index = 2
|
||
|
|
||
|
if (self.current_time - self.death_timer) > 500:
|
||
|
self.kill()
|
||
|
|
||
|
|
||
|
|
||
|
class Koopa(Enemy):
|
||
|
|
||
|
def __init__(self, y=c.GROUND_HEIGHT, x=0, direction=c.LEFT, name='koopa'):
|
||
|
Enemy.__init__(self)
|
||
|
self.setup_enemy(x, y, direction, name, self.setup_frames)
|
||
|
|
||
|
|
||
|
def setup_frames(self):
|
||
|
"""Sets frame list"""
|
||
|
self.frames.append(
|
||
|
self.get_image(150, 0, 16, 24))
|
||
|
self.frames.append(
|
||
|
self.get_image(180, 0, 16, 24))
|
||
|
self.frames.append(
|
||
|
self.get_image(360, 5, 16, 15))
|
||
|
self.frames.append(pg.transform.flip(self.frames[2], False, True))
|
||
|
|
||
|
|
||
|
def jumped_on(self):
|
||
|
"""When Mario jumps on the Koopa and puts him in his shell"""
|
||
|
self.x_vel = 0
|
||
|
self.frame_index = 2
|
||
|
shell_y = self.rect.bottom
|
||
|
shell_x = self.rect.x
|
||
|
self.rect = self.frames[self.frame_index].get_rect()
|
||
|
self.rect.x = shell_x
|
||
|
self.rect.bottom = shell_y
|
||
|
|
||
|
|
||
|
def shell_sliding(self):
|
||
|
"""When the koopa is sliding along the ground in his shell"""
|
||
|
if self.direction == c.RIGHT:
|
||
|
self.x_vel = 10
|
||
|
elif self.direction == c.LEFT:
|
||
|
self.x_vel = -10
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|