Update documentations

This commit is contained in:
Nguyễn Gia Phong 2017-11-04 21:43:05 +07:00
parent 13e0ea6f98
commit b1f0c052f9
5 changed files with 116 additions and 58 deletions

View File

@ -12,13 +12,14 @@ job is to help the trigon fight against those evil squares and find a way out
(if there is any). Be aware that the more get killed, the more will show up and
our hero will get weaker when wounded.
As a research game, Brutal Maze has a few primary goals:
Being a research game, Brutal Maze has a few primary goals:
* Highly portable.
* Auto-generated and infinite maze.
* No binary art data.
* Enemies with randomized attributes: stun, poison, etc.
* Resizable in realtime.
* No binary data for drawing.
* Enemies with randomized attributes: stun, poison, camo, etc.
* Somewhat a realistic physic and logic system.
* Resizable game window in-game.
Installation
------------
@ -27,10 +28,10 @@ Brutal Maze is written in Python and is compatible with both version 2 and 3.
The installation procedure should be as simply as follow:
* Install Python and `pip <https://pip.pypa.io/en/latest/>`_. Make sure the
directory for Python executables is your ``PATH``.
* Clone the Github repository or download the Zip achieve and unpack.
* Open Terminal in the directory containing the repo's folder and run
``pip install --user brutalmaze``.
directory for `Python scripts <https://docs.python.org/2/install/index.html#alternate-installation-the-user-scheme>`_
is your ``PATH``.
* Open Terminal or Command Prompt and run ``pip install --user brutalmaze``.
Now you can lauch the game by running the command ``brutalmaze``.
Control
-------
@ -54,7 +55,7 @@ Right, ``d``
Move right.
Left Mouse
Long-ranged attack.
Long-range attack.
Return, Right Mouse
Close-ranged attack.
Close-range attack, also dodge from bullets.

View File

@ -20,18 +20,33 @@
__doc__ = 'brutalmaze module for hero and enemy classes'
from collections import deque
from math import atan2, sin, pi
from math import atan, atan2, sin, pi
from random import choice, shuffle, uniform
import pygame
from .constants import *
from .utils import randsign, regpoly, fill_aapolygon, sign
from .utils import sign, cosin, randsign, regpoly, fill_aapolygon
from .weapons import Bullet
class Hero:
"""Object representing the hero."""
"""Object representing the hero.
Attributes:
surface (pygame.Surface): the display to draw on
x, y (int): coordinates of the center of the hero (in pixels)
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_strike (int): the tick that the hero can do the next attack
slashing (bool): flag indicates if the hero is doing close-range attack
firing (bool): flag indicates if the hero is doing long-range attack
dead (bool): flag indicates if the hero is dead
spin_speed (float): speed of spinning (in frames per slash)
spin_queue (float): frames left to finish spinning
wound (float): amount of wound
"""
def __init__(self, surface, fps):
self.surface = surface
w, h = self.surface.get_width(), self.surface.get_height()
@ -82,15 +97,29 @@ class Hero:
class Enemy:
"""Object representing an enemy."""
"""Object representing an enemy.
Attributes:
maze (Maze): the maze
x, y (int): coordinates of the center of the enemy (in grids)
angle (float): angle of the direction the enemy pointing (in radians)
color (tuple of pygame.Color): colors of the enemy on different HPs
awake (bool): flag indicates if the enemy is active
next_strike (int): the tick that the enemy can do the next attack
move_speed (float): speed of movement (in frames per grid)
offsetx, offsety (integer): steps moved from the center of the grid
spin_speed (float): speed of spinning (in frames per slash)
spin_queue (float): frames left to finish spinning
wound (float): amount of wound
"""
def __init__(self, maze, x, y):
self.maze = maze
self.angle, self.color = pi / 4, TANGO[choice(ENEMIES)]
self.x, self.y = x, y
self.maze.map[x][y] = ENEMY
self.angle, self.color = pi / 4, TANGO[choice(ENEMIES)]
self.awake = False
self.next_move = 0
self.next_strike = 0
self.move_speed = self.maze.fps / ENEMY_SPEED
self.offsetx = self.offsety = 0
self.spin_speed = self.maze.fps / ENEMY_HP
@ -108,15 +137,33 @@ class Enemy:
self.y += y
self.maze.map[self.x][self.y] = ENEMY
def wake(self):
"""Wake the enemy up if it can see the hero."""
if self.awake: return
startx = starty = MIDDLE
stopx, stopy, distance = self.x, self.y, self.maze.distance
if startx > stopx: startx, stopx = stopx, startx
if starty > stopy: starty, stopy = stopy, starty
dx = (self.x-MIDDLE)*distance + self.maze.centerx - self.maze.x
dy = (self.y-MIDDLE)*distance + self.maze.centery - self.maze.y
mind = cosin(abs(atan(dy / dx)) if dx else 0) * distance
def length(x, y): return abs(dy*x - dx*y) / (dy**2 + dx**2)**0.5
for i in range(startx, stopx + 1):
for j in range(starty, stopy + 1):
if self.maze.map[i][j] != WALL: continue
x, y = self.maze.pos(i, j)
if length(x - self.maze.x, y - self.maze.y) <= mind: return
self.awake = True
def fire(self):
"""Return True if the enemy shot the hero, False otherwise."""
x, y = self.pos()
if (self.maze.length(x, y) > FIRANGE*self.maze.distance
or self.next_move > pygame.time.get_ticks()
or self.next_strike > pygame.time.get_ticks()
or (self.x, self.y) in AROUND_HERO or self.offsetx or self.offsety
or uniform(-2, 2) < (INIT_SCORE/self.maze.score) ** 2):
return False
self.next_move = pygame.time.get_ticks() + ATTACK_SPEED
self.next_strike = pygame.time.get_ticks() + ATTACK_SPEED
self.maze.bullets.append(Bullet(
self.maze.surface, x, y,
atan2(self.maze.y - y, self.maze.x - x), self.color[0]))

View File

@ -20,7 +20,7 @@
__doc__ = 'brutalmaze module for the maze class'
from collections import deque
from math import pi, atan, atan2, log
from math import pi, atan2, log
from random import choice, getrandbits
import pygame
@ -28,7 +28,7 @@ from pygame import RESIZABLE
from .characters import Hero, Enemy
from .constants import *
from .utils import round2, sign, cosin, regpoly, fill_aapolygon
from .utils import round2, sign, regpoly, fill_aapolygon
from .weapons import Bullet
@ -53,13 +53,33 @@ def new_column():
class Maze:
"""Object representing the maze, including the characters."""
"""Object representing the maze, including the characters.
Attributes:
w, h: width and height of the display
fps: current frame rate
surface (pygame.Surface): the display to draw on
distance (float): distance between centers of grids (in px)
x, y (int): coordinates of the center of the hero (in px)
centerx, centery (float): center grid's center's coordinates (in px)
rangex, rangey: range of the index of the grids on display
paused (bool): flag indicates if the game is paused
score (float): current score
map (deque of deque): map of grids representing objects on the maze
down, right (int): direction the maze moving
rotatex, rotatey: grids rotated
bullets (list of Bullet): bullets flying
enemies (list of Enemy): alive enemies
hero (Hero): the hero
slashd (float): minimum distance for slashes to be effective
"""
def __init__(self, size, fps):
self.w, self.h = size
self.fps = fps
self.surface = pygame.display.set_mode(size, RESIZABLE)
self.distance = (self.w * self.h / 416) ** 0.5
self.middlex, self.middley = self.x, self.y = self.w >> 1, self.h >> 1
self.x, self.y = self.w // 2, self.h // 2
self.centerx, self.centery = self.w / 2.0, self.h / 2.0
w, h = (int(i/self.distance/2 + 2) for i in size)
self.rangex = range(MIDDLE - w, MIDDLE + w + 1)
self.rangey = range(MIDDLE - h, MIDDLE + h + 1)
@ -90,8 +110,8 @@ class Maze:
def pos(self, x, y):
"""Return coordinate of the center of the grid (x, y)."""
return (self.middlex + (x - MIDDLE)*self.distance,
self.middley + (y - MIDDLE)*self.distance)
return (self.centerx + (x - MIDDLE)*self.distance,
self.centery + (y - MIDDLE)*self.distance)
def draw(self):
"""Draw the maze."""
@ -103,36 +123,19 @@ class Maze:
square = regpoly(4, self.distance / SQRT2, pi / 4, x, y)
fill_aapolygon(self.surface, square, FG_COLOR)
def wake(self, enemy):
"""Wake the enemy up if it can see the hero."""
dx = (enemy.x-MIDDLE)*self.distance + self.middlex - self.x
dy = (enemy.y-MIDDLE)*self.distance + self.middley - self.y
mind = cosin(abs(atan(dy / dx)) if dx else 0) * self.distance
startx = starty = MIDDLE
stopx, stopy = enemy.x, enemy.y
if startx > stopx : startx, stopx = stopx, startx
if starty > stopy : starty, stopy = stopy, starty
for i in range(startx, stopx + 1):
for j in range(starty, stopy + 1):
if self.map[i][j] != WALL: continue
x, y = self.pos(i, j)
d = abs(dy*(x-self.x) - dx*(y-self.y)) / (dy**2 + dx**2)**0.5
if d <= mind: return
enemy.awake = True
def rotate(self):
"""Rotate the maze if needed."""
x = int((self.middlex-self.x) * 2 / self.distance)
y = int((self.middley-self.y) * 2 / self.distance)
x = int((self.centerx-self.x) * 2 / self.distance)
y = int((self.centery-self.y) * 2 / self.distance)
if x == y == 0: return
for enemy in self.enemies: self.map[enemy.x][enemy.y] = EMPTY
self.map[MIDDLE][MIDDLE] = EMPTY
if x:
self.middlex -= x * self.distance
self.centerx -= x * self.distance
self.map.rotate(x)
self.rotatex += x
if y:
self.middley -= y * self.distance
self.centery -= y * self.distance
for d in self.map: d.rotate(y)
self.rotatey += y
self.map[MIDDLE][MIDDLE] = HERO
@ -174,7 +177,7 @@ class Maze:
return ((self.x-x)**2 + (self.y-y)**2)**0.5
def slash(self):
"""Handle close-ranged attacks."""
"""Handle close-range attacks."""
for enemy in self.enemies:
if not enemy.spin_queue: continue
x, y = enemy.pos()
@ -249,14 +252,13 @@ class Maze:
if self.paused: return
self.fps, step = fps, self.distance * HERO_SPEED / fps
dx = step * self.right * self.isvalid(step, dx=self.right)
self.middlex += dx
self.centerx += dx
dy = step * self.down * self.isvalid(step, dy=self.down)
self.middley += dy
self.centery += dy
if dx or dy:
self.rotate()
for enemy in self.enemies:
if not enemy.awake: self.wake(enemy)
for enemy in self.enemies: enemy.wake()
for bullet in self.bullets: bullet.place(dx, dy)
self.draw()
@ -275,12 +277,12 @@ class Maze:
self.surface = pygame.display.set_mode(size, RESIZABLE)
self.hero.resize()
offsetx = (self.middlex-self.x) / self.distance
offsety = (self.middley-self.y) / self.distance
offsetx = (self.centerx-self.x) / self.distance
offsety = (self.centery-self.y) / self.distance
self.distance = (w * h / 416) ** 0.5
self.x, self.y = w >> 1, h >> 1
self.middlex = self.x + offsetx*self.distance
self.middley = self.y + offsety*self.distance
self.x, self.y = w // 2, h // 2
self.centerx = self.x + offsetx*self.distance
self.centery = self.y + offsety*self.distance
w, h = int(w/self.distance/2 + 2), int(h/self.distance/2 + 2)
self.rangex = range(MIDDLE - w, MIDDLE + w + 1)
self.rangey = range(MIDDLE - h, MIDDLE + h + 1)

View File

@ -28,7 +28,15 @@ from .utils import regpoly, fill_aapolygon
class Bullet:
"""Object representing a bullet."""
"""Object representing a bullet.
Attributes:
surface (pygame.Surface): the display to draw on
x, y (int): coordinates of the center of the bullet (in pixels)
angle (float): angle of the direction the bullet pointing (in radians)
color (pygame.Color): color of the bullet
fall_time (int): the tick that the bullet will fall down
"""
def __init__(self, surface, x, y, angle, color):
self.surface = surface
self.x, self.y, self.angle, self.color = x, y, angle, color

View File

@ -7,8 +7,8 @@ with open('README.rst') as f:
setup(
name='brutalmaze',
version='0.0.1',
description='Brutal Maze',
version='0.0.2',
description='A research hash and slash game with fast-paced action and a minimalist art style',
long_description=long_description,
url='https://github.com/McSinyx/brutalmaze',
author='Nguyễn Gia Phong',