diff options
-rw-r--r-- | README.rst | 7 | ||||
-rw-r--r-- | brutalmaze/characters.py | 70 | ||||
-rw-r--r-- | brutalmaze/constants.py | 4 | ||||
-rw-r--r-- | brutalmaze/main.py | 8 | ||||
-rw-r--r-- | brutalmaze/maze.py | 26 | ||||
-rw-r--r-- | brutalmaze/weapons.py | 4 |
6 files changed, 64 insertions, 55 deletions
diff --git a/README.rst b/README.rst index eab00b8..557069f 100644 --- a/README.rst +++ b/README.rst @@ -47,5 +47,8 @@ Left, ``a`` Right, ``d`` Move right. -Return, Left Mouse - Close-range attack. +Left Mouse + Long-ranged attack. + +Return, Right Mouse + Close-ranged attack. diff --git a/brutalmaze/characters.py b/brutalmaze/characters.py index 029b78d..dd69d69 100644 --- a/brutalmaze/characters.py +++ b/brutalmaze/characters.py @@ -26,7 +26,7 @@ from random import shuffle import pygame from .constants import * -from .utils import round2, randsign, regpoly, fill_aapolygon, pos, sign +from .utils import randsign, regpoly, fill_aapolygon, pos, sign class Hero: @@ -38,42 +38,32 @@ class Hero: self.angle, self.color = pi / 4, TANGO['Aluminium'] self.R = int((w * h / sin(pi*2/3) / 624) ** 0.5) - self.spin_speed = round2(fps / len(self.color)) - self.spin_queue, self.slashing = deque(), False - self.wound = 0.0 - - def get_color(self): - """Return the color of the hero based on the amount of wounds.""" - return self.color[int(self.wound)] - - def slash(self, hold=False): - """Spin the hero. If the button is hold, delay before continue - each spin. - """ - if self.slashing and not self.spin_queue: - if hold: self.spin_queue.extend([0] * (self.spin_speed >> 1)) - self.spin_queue.extend([randsign()] * self.spin_speed) - - def draw(self): - """Draw the hero.""" - trigon = regpoly(3, self.R, self.angle, self.x, self.y) - fill_aapolygon(self.surface, trigon, self.get_color()) + self.next_strike = 0 + self.slashing = self.firing = False + self.spin_speed = fps / len(self.color) + self.spin_queue = self.wound = 0.0 def update(self, fps): """Update the hero.""" - self.spin_speed = round2(fps / (len(self.color)-self.wound)) + old_speed, time = self.spin_speed, pygame.time.get_ticks() + self.spin_speed = fps / (len(self.color)-self.wound**0.5) + self.spin_queue *= self.spin_speed / old_speed self.wound -= HEAL_SPEED / len(self.color) / self.spin_speed if self.wound < 0: self.wound = 0.0 - self.slash(hold=True) - direction = self.spin_queue.popleft() if self.spin_queue else 0 - if direction: - self.angle += direction * pi * 2 / 3 / self.spin_speed + if self.slashing and time >= self.next_strike: + self.next_strike = time + ATTACK_SPEED + self.spin_queue = randsign() * self.spin_speed + if abs(self.spin_queue) > 0.5: + self.angle += sign(self.spin_queue) * pi / 2 / self.spin_speed + self.spin_queue -= sign(self.spin_queue) else: # Follow the mouse cursor x, y = pygame.mouse.get_pos() self.angle = atan2(y - self.y, x - self.x) - self.draw() + self.spin_queue = 0.0 + trigon = regpoly(3, self.R, self.angle, self.x, self.y) + fill_aapolygon(self.surface, trigon, self.color[int(self.wound)]) def resize(self): """Resize the hero.""" @@ -91,25 +81,28 @@ class Enemy: self.maze[x][y] = ENEMY self.awake = False + self.next_move = 0 self.move_speed = fps / MOVE_SPEED self.offsetx = self.offsety = 0 self.spin_speed = fps / len(self.color) self.spin_queue = self.wound = 0.0 + def firable(self): + """Return True if the enemies should shoot the hero, + False otherwise. + """ + if not self.awake or self.spin_queue or self.offsetx or self.offsety: + return False + else: + self.next_move = pygame.time.get_ticks() + ATTACK_SPEED + return True + def pos(self, distance, middlex, middley): """Return coordinate of the center of the enemy.""" x, y = pos(self.x, self.y, distance, middlex, middley) step = distance / self.move_speed return x + self.offsetx*step, y + self.offsety*step - def draw(self, distance, middlex, middley): - """Draw the enemy, given distance between grids and the middle grid.""" - radious = distance/SQRT2 - self.awake*2 - square = regpoly(4, radious, self.angle, - *self.pos(distance, middlex, middley)) - color = self.color[int(self.wound)] if self.awake else FG_COLOR - fill_aapolygon(self.surface, square, color) - def place(self, x=0, y=0): """Move the enemy by (x, y) (in grids).""" self.x += x @@ -121,6 +114,7 @@ class Enemy: Return True if it moved, False otherwise. """ + if self.next_move > pygame.time.get_ticks(): return False if self.offsetx: self.offsetx -= sign(self.offsetx) return True @@ -152,7 +146,11 @@ class Enemy: self.spin_queue -= sign(self.spin_queue) else: self.angle, self.spin_queue = pi / 4, 0.0 - self.draw(distance, middlex, middley) + radious = distance/SQRT2 - self.awake*2 + square = regpoly(4, radious, self.angle, + *self.pos(distance, middlex, middley)) + color = self.color[int(self.wound)] if self.awake else FG_COLOR + fill_aapolygon(self.surface, square, color) def die(self): """Kill the enemy.""" diff --git a/brutalmaze/constants.py b/brutalmaze/constants.py index 4d750ee..e85c1cb 100644 --- a/brutalmaze/constants.py +++ b/brutalmaze/constants.py @@ -37,8 +37,10 @@ MIDDLE = (MAZE_SIZE + MAZE_SIZE%2 - 1)*ROAD_WIDTH + ROAD_WIDTH//2 LAST_ROW = (MAZE_SIZE-1) * ROAD_WIDTH * 2 INIT_SCORE = 208.2016 MOVE_SPEED = 5 # grid/s +BULLET_SPEED = 10 # grid/s HEAL_SPEED = 1.0 # HP/s -BULLET_LIFETIME = 1000 # milliseconds +ATTACK_SPEED = 333 # ms/strike +BULLET_LIFETIME = 1000 # ms EMPTY, WALL, HERO, ENEMY = range(4) ADJACENT_GRIDS = (1, 0), (0, 1), (-1, 0), (0, -1) diff --git a/brutalmaze/main.py b/brutalmaze/main.py index 1874ed6..eb17954 100644 --- a/brutalmaze/main.py +++ b/brutalmaze/main.py @@ -48,7 +48,6 @@ def main(): maze.move(-1, 0) elif event.key == K_RETURN: maze.hero.slashing = True - maze.hero.slash() elif event.type == KEYUP: if event.key in (K_UP, K_w): maze.move(0, -1) @@ -62,12 +61,13 @@ def main(): maze.hero.slashing = False elif event.type == MOUSEBUTTONDOWN: if event.button == 1: + maze.hero.firing = True + elif event.button == 3: maze.hero.slashing = True - maze.hero.slash() - if event.button == 3: - maze.fire() elif event.type == MOUSEBUTTONUP: if event.button == 1: + maze.hero.firing = False + elif event.button == 3: maze.hero.slashing = False elif event.type == VIDEORESIZE: maze.resize(event.w, event.h) diff --git a/brutalmaze/maze.py b/brutalmaze/maze.py index f78c1c5..f9877a4 100644 --- a/brutalmaze/maze.py +++ b/brutalmaze/maze.py @@ -18,8 +18,8 @@ # Copyright (C) 2017 Nguyễn Gia Phong from collections import deque -from math import pi, atan, log -from random import choice, getrandbits +from math import pi, atan, atan2, log +from random import choice, getrandbits, uniform import pygame @@ -168,7 +168,7 @@ class Maze: if d >= 0: self.hero.wound += d / self.hero.R / enemy.spin_speed - if not self.hero.slashing: return + if not self.hero.spin_queue: return unit, killist = self.distance/SQRT2 * self.hero.spin_speed, [] for i, enemy in enumerate(self.enemies): x, y = enemy.pos(self.distance, self.middlex, self.middley) @@ -185,6 +185,17 @@ class Maze: def track_bullets(self): """Handle the bullets.""" fallen, time = [], pygame.time.get_ticks() + for enemy in self.enemies: + if uniform(-2, 2) > (INIT_SCORE/self.score)**2 and enemy.firable(): + x, y = enemy.pos(self.distance, self.middlex, self.middley) + self.bullets.append( + Bullet(self.surface, x, y, atan2(self.y - y, self.x - x), + enemy.color[0])) + if (self.hero.firing and not self.hero.slashing + and time >= self.hero.next_strike): + self.hero.next_strike = time + ATTACK_SPEED + self.bullets.append(Bullet(self.surface, self.x, self.y, + self.hero.angle, FG_COLOR)) for i, bullet in enumerate(self.bullets): wound = float(bullet.fall_time-time) / BULLET_LIFETIME bullet.update(self.fps, self.distance) @@ -207,7 +218,7 @@ class Maze: fallen.append(i) break elif length(bullet.x, bullet.y, self.x, self.y) < self.distance: - self.hero.wound += wound + if not self.hero.spin_queue: self.hero.wound += wound fallen.append(i) for i in reversed(fallen): self.bullets.pop(i) @@ -277,7 +288,6 @@ class Maze: self.rangex = range(MIDDLE - w, MIDDLE + w + 1) self.rangey = range(MIDDLE - h, MIDDLE + h + 1) self.slashd = self.hero.R + self.distance/SQRT2 - self.draw() def move(self, x, y): """Command the maze to move x step/frame faster to the left and @@ -288,11 +298,7 @@ class Maze: self.down += y self.right, self.down = sign(self.right), sign(self.down) - def fire(self): - """Create a bullet shot from the hero.""" - self.bullets.append( - Bullet(self.surface, self.x, self.y, self.hero.angle, FG_COLOR)) - def lose(self): """Handle loses.""" + print('Your score is: {}'.format(int(self.score - INIT_SCORE))) quit() diff --git a/brutalmaze/weapons.py b/brutalmaze/weapons.py index 108b042..0d2fb8c 100644 --- a/brutalmaze/weapons.py +++ b/brutalmaze/weapons.py @@ -36,10 +36,10 @@ class Bullet: def update(self, fps, distance): """Update the bullet.""" - s = distance * 8 / fps + s = distance * BULLET_SPEED / fps self.x += s * cos(self.angle) self.y += s * sin(self.angle) - hexagon = regpoly(6, distance // 4, self.angle, self.x, self.y) + hexagon = regpoly(5, distance // 4, self.angle, self.x, self.y) fill_aapolygon(self.surface, hexagon, self.color) def place(self, x, y, step): |