class Enemy: """Main enemy control class.""" def __init__(self, player: int, location: tuple, floor_height: float): """ctor""" self.sprite = Sprite("assets/Sprites", (70, 80), 2.5, player != 1, Player.SPRITE_SHEET_STATES) if player == 1: self.controls = Player.PLAYER_ONE_CONTROLS else: self.controls = Player.PLAYER_TWO_CONTROLS self.location = Vector(location) self.sprite_state = "IDLE" self.speed = 0 self.ResetSpeed() self.frame_counter = 0 self.floor_height = floor_height self.velocity = Vector((0, 0)) self.acceleration = Vector((0, GRAVITY)) self.sprite_state_counter = 0 self.damage_time = 0 self.health = 100 self.imports_done = False def Draw(self, canvas: simplegui.Canvas) -> None: """Public draw handler.""" self.frame_counter += 1 self.velocity.Add(self.acceleration) movement = self.velocity.Copy() movement.x *= self.speed if self.damage_time: self.damage_time -= 1 if not self.damage_time: self.location.Add( Vector((75 * (1 if self.sprite.flip else -1), -50))) self.acceleration = Vector((0, GRAVITY)) else: self.location.Add(movement) self.location.x = max(0, min(canvas._width, self.location.x)) if self.location.y > self.floor_height // 1: self.acceleration.y = 0 self.velocity.y = 0 self.location.y = self.floor_height self.sprite_state = "IDLE" self.sprite_state_counter = 0 if not self.frame_counter % Player.FRAME_RATES[self.sprite_state]: self.Evolve() self.sprite.Draw(canvas, self.location.GetP()) self.KeyDown(0) self.KeyUp(0) def ResetSpeed(self) -> None: """Resets speed after a locking operation.""" self.speed = 7 def Evolve(self) -> None: """Updates the state of the sprites.""" self.sprite_state_counter += 1 mod_by = len(Player.SPRITE_SHEET_STATES[self.sprite_state]) if self.sprite_state == "PUNCH" and self.sprite_state_counter == mod_by: self.sprite_state = "IDLE" self.sprite_state_counter = 0 self.ResetSpeed() self.sprite_state_counter %= mod_by self.sprite.SetSpriteState(self.sprite_state, self.sprite_state_counter) def Damage(self, amount: int) -> None: """Damages the enemy by the specified amount and checks for death.""" self.health -= amount self.damage_time = 5 def KeyDown(self, keyargs: int) -> None: """Handles key press.""" from StreetFighter import GAME #pylint: disable=no-member opponent = GAME.player if self.sprite.flip else GAME.enemy punch_point = opponent.sprite.sprite_dims[ 0] * opponent.sprite.sprite_scale / 1.75 punch_point //= 1 if abs(self.location.x - opponent.location.x) < abs(punch_point): if self.sprite.flip and self.location.x > opponent.location.x: keyargs = self.controls["ATTACK"] elif not self.sprite.flip and self.location.x < opponent.location.x: keyargs = self.controls["ATTACK"] else: keyargs = self.controls["RIGHT" if self.location.x < opponent. location.x else "LEFT"] else: if opponent.sprite_state == "PUNCH": keyargs = self.controls["UP"] else: keyargs = self.controls["RIGHT" if self.location.x < opponent. location.x else "LEFT"] if (keyargs == self.controls["UP"] and self.acceleration.y < GRAVITY and not self.sprite_state == "PUNCH"): self.sprite_state = "JUMP" self.sprite_state_counter = -1 self.Evolve() self.acceleration = Vector((0, GRAVITY)) self.velocity.y = -30 self.location.y -= 1 if keyargs == self.controls["RIGHT"] and self.velocity.x < 1: self.velocity.x = min(1, self.velocity.x + 1) if keyargs == self.controls["LEFT"] and self.velocity.x > -1: self.velocity.x = max(-1, self.velocity.x - 1) if keyargs == self.controls["DOWN"] and self.acceleration.y < GRAVITY: self.sprite_state = "CROUCH" self.sprite_state_counter = -1 self.Evolve() self.speed = 0 if (keyargs == self.controls["ATTACK"] and self.acceleration.y < GRAVITY and self.sprite_state != "CROUCH" and self.sprite_state != "PUNCH"): self.sprite_state = "PUNCH" self.sprite_state_counter = -1 self.Evolve() self.speed = 0 #pylint: disable=unused-argument def KeyUp(self, keyargs: int) -> None: """Handles key release.""" from StreetFighter import GAME #pylint: disable=no-member opponent = GAME.player if self.sprite.flip else GAME.enemy if abs(self.location.x - opponent.location.x) < (2.5 / 1.75): if self.sprite.flip and self.location.x > opponent.location.x: self.velocity.x = 0 elif not self.sprite.flip and self.location.x < opponent.location.x: self.velocity.x = 0 else: if self.sprite.flip and self.location.x < opponent.location.x and self.velocity.x < 0: self.velocity.x = 0 elif not self.sprite.flip and self.location.x > opponent.location.x and self.velocity.x > 0: self.velocity.x = 0
class Player: """Object representing a human-controlled player. Control Scheme: W/Up Arrow - Jump A/Left Arrow - Go left S/Down Arrow - Duck D/Right Arrow - Go right Space/Shift - Attack""" PLAYER_ONE_CONTROLS = { "UP": 87, "LEFT": 65, "DOWN": 83, "RIGHT": 68, "ATTACK": 32 } PLAYER_TWO_CONTROLS = { "UP": 38, "LEFT": 37, "DOWN": 40, "RIGHT": 39, "ATTACK": 17 } SPRITE_SHEET_STATES = { "IDLE": [(x, 1) for x in range(4)], "PUNCH": [(x, 2) for x in range(3)], "JUMP": [(x, 8) for x in range(7)], "CROUCH": [(0, 9)] } FRAME_RATES = {"IDLE": 5, "JUMP": 7, "PUNCH": 10, "CROUCH": 1000} def __init__(self, player: int, location: tuple, floor_height: float): """ctor""" self.sprite = Sprite("assets/Sprites", (70, 80), 2.5, player != 1, Player.SPRITE_SHEET_STATES) if player == 1: self.controls = Player.PLAYER_ONE_CONTROLS else: self.controls = Player.PLAYER_TWO_CONTROLS self.location = Vector(location) self.sprite_state = "IDLE" self.speed = 0 self.ResetSpeed() self.frame_counter = 0 self.floor_height = floor_height self.velocity = Vector((0, 0)) self.acceleration = Vector((0, GRAVITY)) self.sprite_state_counter = 0 self.damage_time = 0 self.health = 100 def KeyDown(self, keyargs: int) -> None: """Handles key press.""" if (keyargs == self.controls["UP"] and self.acceleration.y < GRAVITY and not self.sprite_state == "PUNCH"): self.sprite_state = "JUMP" self.sprite_state_counter = -1 self.Evolve() self.acceleration = Vector((0, GRAVITY)) self.velocity.y = -30 self.location.y -= 1 if keyargs == self.controls["RIGHT"] and self.velocity.x < 1: self.velocity.x = min(1, self.velocity.x + 1) if keyargs == self.controls["LEFT"] and self.velocity.x > -1: self.velocity.x = max(-1, self.velocity.x - 1) if keyargs == self.controls["DOWN"] and self.acceleration.y < GRAVITY: self.sprite_state = "CROUCH" self.sprite_state_counter = -1 self.Evolve() self.speed = 0 if (keyargs == self.controls["ATTACK"] and self.acceleration.y < GRAVITY and self.sprite_state != "CROUCH"): self.sprite_state = "PUNCH" self.sprite_state_counter = -1 self.Evolve() self.speed = 0 def KeyUp(self, keyargs: int) -> None: """Handles key release.""" if keyargs == self.controls["RIGHT"]: self.velocity.x = min(0, self.velocity.x - 1) if keyargs == self.controls["LEFT"]: self.velocity.x = max(0, self.velocity.x + 1) if keyargs == self.controls["DOWN"]: self.sprite_state = "IDLE" self.Evolve() self.ResetSpeed() def Draw(self, canvas: simplegui.Canvas) -> None: """Public draw handler.""" self.frame_counter += 1 self.velocity.Add(self.acceleration) movement = self.velocity.Copy() movement.x *= self.speed if self.damage_time: self.damage_time -= 1 if not self.damage_time: self.location.Add( Vector((75 * (1 if self.sprite.flip else -1), -50))) self.acceleration = Vector((0, GRAVITY)) else: self.location.Add(movement) self.location.x = max(0, min(canvas._width, self.location.x)) if self.location.y > self.floor_height // 1: self.acceleration.y = 0 self.velocity.y = 0 self.location.y = self.floor_height self.sprite_state = "IDLE" self.sprite_state_counter = 0 if not self.frame_counter % Player.FRAME_RATES[self.sprite_state]: self.Evolve() self.sprite.Draw(canvas, self.location.GetP()) def ResetSpeed(self) -> None: """Resets speed after a locking operation.""" self.speed = 7 def Evolve(self) -> None: """Updates the state of the sprites.""" self.sprite_state_counter += 1 mod_by = len(Player.SPRITE_SHEET_STATES[self.sprite_state]) if self.sprite_state == "PUNCH" and self.sprite_state_counter == mod_by: self.sprite_state = "IDLE" self.sprite_state_counter = 0 self.ResetSpeed() self.sprite_state_counter %= mod_by self.sprite.SetSpriteState(self.sprite_state, self.sprite_state_counter) def Damage(self, amount: int) -> None: """Damages the player by the specified amount and checks for death.""" self.health -= amount self.damage_time = 5