From fc05e0ccee392985d67872507bc5476a5775142c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Gia=20Phong?= Date: Mon, 25 Jun 2018 21:40:19 +0700 Subject: [PATCH] Prevent gang-bang and re-balance gameplay --- brutalmaze/characters.py | 21 ++++++++++++++------- brutalmaze/constants.py | 3 ++- brutalmaze/game.py | 2 +- brutalmaze/maze.py | 37 ++++++++++++++++++++----------------- setup.py | 2 +- 5 files changed, 38 insertions(+), 27 deletions(-) diff --git a/brutalmaze/characters.py b/brutalmaze/characters.py index 7aead58..b6ab9af 100644 --- a/brutalmaze/characters.py +++ b/brutalmaze/characters.py @@ -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): diff --git a/brutalmaze/constants.py b/brutalmaze/constants.py index e742858..82e76c9 100644 --- a/brutalmaze/constants.py +++ b/brutalmaze/constants.py @@ -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) diff --git a/brutalmaze/game.py b/brutalmaze/game.py index 6295ae1..95b7c09 100644 --- a/brutalmaze/game.py +++ b/brutalmaze/game.py @@ -17,7 +17,7 @@ # You should have received a copy of the GNU Affero General Public License # along with Brutal Maze. If not, see . -__version__ = '0.7.5' +__version__ = '0.7.7' import re from argparse import ArgumentParser, FileType, RawTextHelpFormatter diff --git a/brutalmaze/maze.py b/brutalmaze/maze.py index c6f2585..ef1c2fb 100644 --- a/brutalmaze/maze.py +++ b/brutalmaze/maze.py @@ -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]) diff --git a/setup.py b/setup.py index 7461f9c..6151256 100755 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ with open('README.rst') as f: setup( name='brutalmaze', - version='0.7.5', + version='0.7.7', description='A minimalist TPS game with fast-paced action', long_description=long_description, url='https://github.com/McSinyx/brutalmaze',