Prevent gang-bang and re-balance gameplay
This commit is contained in:
parent
3507a52ac7
commit
fc05e0ccee
|
@ -19,6 +19,7 @@
|
|||
|
||||
__doc__ = 'Brutal Maze module for hero and enemy classes'
|
||||
|
||||
from collections import deque
|
||||
from math import atan, atan2, sin, pi
|
||||
from random import choice, randrange, shuffle
|
||||
from sys import modules
|
||||
|
@ -40,7 +41,7 @@ class Hero:
|
|||
angle (float): angle of the direction the hero pointing (in radians)
|
||||
color (tuple of pygame.Color): colors of the hero on different HPs
|
||||
R (int): circumradius of the regular triangle representing the hero
|
||||
next_heal (float): ms until the hero gains back healing ability
|
||||
next_heal (float): minimum wound in ATTACK_SPEED allowing healing again
|
||||
next_beat (float): time until next heart beat (in ms)
|
||||
next_strike (float): time until the hero can do the next attack (in ms)
|
||||
slashing (bool): flag indicates if the hero is doing close-range attack
|
||||
|
@ -49,6 +50,7 @@ class Hero:
|
|||
spin_speed (float): speed of spinning (in frames per slash)
|
||||
spin_queue (float): frames left to finish spinning
|
||||
wound (float): amount of wound
|
||||
wounds (deque of float): wounds in time of an attack (ATTACK_SPEED)
|
||||
sfx_heart (pygame.mixer.Sound): heart beat sound effect
|
||||
"""
|
||||
def __init__(self, surface, fps, maze_size):
|
||||
|
@ -58,10 +60,12 @@ class Hero:
|
|||
self.angle, self.color = -pi * 3 / 4, TANGO['Aluminium']
|
||||
self.R = (w * h / sin(pi*2/3) / 624) ** 0.5
|
||||
|
||||
self.next_heal = self.next_beat = self.next_strike = 0.0
|
||||
self.next_heal = -1.0
|
||||
self.next_beat = self.next_strike = 0.0
|
||||
self.slashing = self.firing = self.dead = False
|
||||
self.spin_speed = fps / HERO_HP
|
||||
self.spin_queue = self.wound = 0.0
|
||||
self.wounds = deque([0.0])
|
||||
|
||||
self.sfx_heart = SFX_HEART
|
||||
|
||||
|
@ -73,11 +77,14 @@ class Hero:
|
|||
old_speed = self.spin_speed
|
||||
self.spin_speed = fps / (HERO_HP-self.wound**0.5)
|
||||
self.spin_queue *= self.spin_speed / old_speed
|
||||
if self.next_heal <= 0:
|
||||
|
||||
if len(self.wounds) > fps * ATTACK_SPEED / 1000: self.wounds.popleft()
|
||||
if sum(self.wounds) < self.next_heal: self.next_heal = -1.0
|
||||
self.wound += self.wounds[-1]
|
||||
if self.next_heal < 0:
|
||||
self.wound -= HEAL_SPEED / self.spin_speed / HERO_HP
|
||||
if self.wound < 0: self.wound = 0.0
|
||||
else:
|
||||
self.next_heal -= 1000.0 / fps
|
||||
self.wounds.append(0.0)
|
||||
if self.next_beat <= 0:
|
||||
play(self.sfx_heart)
|
||||
self.next_beat = MIN_BEAT*(2 - self.wound/HERO_HP)
|
||||
|
@ -100,7 +107,7 @@ class Hero:
|
|||
"""Return the number of sides the hero has. While the hero is
|
||||
generally a trigon, Agent Orange may turn him into a square.
|
||||
"""
|
||||
return 3 if self.next_heal <= 0 else 4
|
||||
return 3 if self.next_heal < 0 else 4
|
||||
|
||||
def update_angle(self, angle):
|
||||
"""Turn to the given angle if the hero is not busy slashing."""
|
||||
|
@ -252,7 +259,7 @@ class Enemy:
|
|||
def slash(self):
|
||||
"""Return the enemy's close-range damage per frame."""
|
||||
wound = self.get_slash() / self.spin_speed
|
||||
if self.spin_queue: self.maze.hit_hero(wound, self.color)
|
||||
if self.spin_queue and wound: self.maze.hit_hero(wound, self.color)
|
||||
return wound
|
||||
|
||||
def get_angle(self, reversed=False):
|
||||
|
|
|
@ -43,7 +43,7 @@ SFX_LOSE = Sound(pkg_file('brutalmaze', 'soundfx/lose.ogg'))
|
|||
if mixer is None: pygame.mixer.quit()
|
||||
|
||||
SQRT2 = 2 ** 0.5
|
||||
INIT_SCORE = 5**0.5/2 + 0.5 # golden mean
|
||||
INIT_SCORE = 2
|
||||
ROAD_WIDTH = 3 # grids
|
||||
WALL_WIDTH = 4 # grids
|
||||
CELL_WIDTH = WALL_WIDTH + ROAD_WIDTH*2 # grids
|
||||
|
@ -55,6 +55,7 @@ HERO_SPEED = 5 # grid/s
|
|||
ENEMY_SPEED = 6 # grid/s
|
||||
BULLET_SPEED = 15 # grid/s
|
||||
ATTACK_SPEED = 333.333 # ms/strike
|
||||
MAX_WOUND = 1 # per attack turn
|
||||
FIRANGE = 6 # grids
|
||||
BULLET_LIFETIME = 1000.0 * FIRANGE / (BULLET_SPEED-HERO_SPEED) # ms
|
||||
EMPTY, WALL, HERO, ENEMY = range(4)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with Brutal Maze. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__version__ = '0.7.5'
|
||||
__version__ = '0.7.7'
|
||||
|
||||
import re
|
||||
from argparse import ArgumentParser, FileType, RawTextHelpFormatter
|
||||
|
|
|
@ -30,7 +30,7 @@ from .constants import (
|
|||
EMPTY, WALL, HERO, ENEMY, ROAD_WIDTH, WALL_WIDTH, CELL_WIDTH, CELL_NODES,
|
||||
MAZE_SIZE, MIDDLE, INIT_SCORE, ENEMIES, MINW, MAXW, SQRT2, SFX_SPAWN,
|
||||
SFX_SLASH_ENEMY, SFX_LOSE, ADJACENTS, TANGO_VALUES, BG_COLOR, FG_COLOR,
|
||||
HERO_HP, ENEMY_HP, ATTACK_SPEED, HERO_SPEED, BULLET_LIFETIME)
|
||||
HERO_HP, ENEMY_HP, ATTACK_SPEED, MAX_WOUND, HERO_SPEED, BULLET_LIFETIME)
|
||||
from .misc import round2, sign, around, regpoly, fill_aapolygon, play
|
||||
from .weapons import Bullet
|
||||
|
||||
|
@ -229,19 +229,20 @@ class Maze:
|
|||
|
||||
def hit_hero(self, wound, color):
|
||||
"""Handle the hero when he loses HP."""
|
||||
fx = (uniform(0, sum(self.enemy_weights.values()))
|
||||
< self.enemy_weights[color])
|
||||
if (color == 'Butter' or color == 'ScarletRed') and fx:
|
||||
self.hero.wound += wound * 2.5
|
||||
elif color == 'Orange' and fx:
|
||||
self.hero.next_heal = max(self.hero.next_heal, 0) + wound*1000
|
||||
elif color == 'SkyBlue' and fx:
|
||||
self.next_move = max(self.next_move, 0) + wound*1000
|
||||
else:
|
||||
self.hero.wound += wound
|
||||
if self.enemy_weights[color] + wound < MAXW:
|
||||
self.enemy_weights[color] += wound
|
||||
if self.hero.wound > HERO_HP and not self.hero.dead: self.lose()
|
||||
if color == 'Orange':
|
||||
self.hero.next_heal = abs(self.hero.next_heal * (1 - wound))
|
||||
elif (uniform(0, sum(self.enemy_weights.values()))
|
||||
< self.enemy_weights[color]):
|
||||
self.hero.next_heal = -1.0 # what doesn't kill you heals you
|
||||
if color == 'Butter' or color == 'ScarletRed':
|
||||
wound *= ENEMY_HP
|
||||
elif color == 'SkyBlue':
|
||||
self.next_move = max(self.next_move, 0) + wound*1000
|
||||
wound = 0
|
||||
if wound and sum(self.hero.wounds) < MAX_WOUND:
|
||||
self.hero.wounds[-1] += wound
|
||||
|
||||
def slash(self):
|
||||
"""Handle close-range attacks."""
|
||||
|
@ -272,14 +273,14 @@ class Maze:
|
|||
self.hero.angle, 'Aluminium'))
|
||||
|
||||
fallen = []
|
||||
block = (self.hero.spin_queue and self.hero.next_heal <= 0
|
||||
block = (self.hero.spin_queue and self.hero.next_heal < 0
|
||||
and self.hero.next_strike > self.hero.spin_queue / self.fps)
|
||||
|
||||
for i, bullet in enumerate(self.bullets):
|
||||
wound = bullet.fall_time / BULLET_LIFETIME
|
||||
bullet.update(self.fps, self.distance)
|
||||
gridx, gridy = self.get_grid(bullet.x, bullet.y)
|
||||
if wound < 0 or not self.is_displayed(gridx, gridy):
|
||||
if wound <= 0 or not self.is_displayed(gridx, gridy):
|
||||
fallen.append(i)
|
||||
elif bullet.color == 'Aluminium':
|
||||
if self.map[gridx][gridy] == WALL and self.next_move <= 0:
|
||||
|
@ -353,10 +354,11 @@ class Maze:
|
|||
for bullet in self.bullets: bullet.place(self.vx, self.vy)
|
||||
|
||||
for enemy in self.enemies: enemy.update()
|
||||
self.track_bullets()
|
||||
if not self.hero.dead:
|
||||
self.hero.update(fps)
|
||||
self.slash()
|
||||
self.track_bullets()
|
||||
if self.hero.wound > HERO_HP: self.lose()
|
||||
|
||||
def resize(self, size):
|
||||
"""Resize the maze."""
|
||||
|
@ -443,7 +445,8 @@ class Maze:
|
|||
self.enemy_weights = {color: MINW for color in ENEMIES}
|
||||
self.add_enemy()
|
||||
|
||||
self.next_move = self.next_slashfx = 0.0
|
||||
self.hero.next_heal = self.hero.next_strike = 0
|
||||
self.next_move = self.next_slashfx = self.hero.next_strike = 0.0
|
||||
self.hero.next_heal = -1.0
|
||||
self.hero.slashing = self.hero.firing = self.hero.dead = False
|
||||
self.hero.spin_queue = self.hero.wound = 0.0
|
||||
self.hero.wounds = deque([0.0])
|
||||
|
|
Loading…
Reference in New Issue