Give enemies eyes
This commit is contained in:
parent
613732b7c6
commit
05bfead6e9
|
@ -4,6 +4,7 @@ Brutal Maze
|
|||
**Brutal Maze** is a research hash and slash game with *polyart* graphic and
|
||||
Tango color palette. Its primary goals are:
|
||||
|
||||
* Highly portable.
|
||||
* Auto-generated and infinite maze.
|
||||
* No binary data.
|
||||
* Enemies with randomized attributes: stun, poison, etc.
|
||||
|
|
|
@ -47,6 +47,11 @@ def fill_aapolygon(surface, points, color):
|
|||
filled_polygon(surface, points, color)
|
||||
|
||||
|
||||
def pos(x, y, distance, middlex, middley):
|
||||
"""Return coordinate of the center of the grid (x, y)."""
|
||||
return middlex + (x - MIDDLE)*distance, middley + (y - MIDDLE)*distance
|
||||
|
||||
|
||||
class Hero:
|
||||
"""Object representing the hero."""
|
||||
def __init__(self, surface):
|
||||
|
@ -60,12 +65,6 @@ class Hero:
|
|||
self.speed = FPS // len(self.color)
|
||||
self.spin_queue, self.slashing = deque(), False
|
||||
|
||||
def resize(self):
|
||||
"""Resize the hero."""
|
||||
w, h = self.surface.get_width(), self.surface.get_height()
|
||||
self.x, self.y = w >> 1, h >> 1
|
||||
self.R = int((w * h / sin(pi*2/3) / 624) ** 0.5)
|
||||
|
||||
def slash(self, hold=False):
|
||||
"""Spin the hero. If the button is hold, delay before continue
|
||||
each spin.
|
||||
|
@ -92,6 +91,12 @@ class Hero:
|
|||
self.angle = atan2(y - self.y, x - self.x)
|
||||
self.draw()
|
||||
|
||||
def resize(self):
|
||||
"""Resize the hero."""
|
||||
w, h = self.surface.get_width(), self.surface.get_height()
|
||||
self.x, self.y = w >> 1, h >> 1
|
||||
self.R = int((w * h / sin(pi*2/3) / 624) ** 0.5)
|
||||
|
||||
|
||||
class Enemy:
|
||||
"""Object representing an enemy."""
|
||||
|
@ -100,25 +105,24 @@ class Enemy:
|
|||
self.x, self.y = x, y
|
||||
self.angle, self.color = pi / 4, TANGO[TANGO_KEYS[n]]
|
||||
|
||||
self.moving = False
|
||||
self.awake, self.moving = False, False
|
||||
self.wound = 0
|
||||
self.speed = FPS // len(self.color)
|
||||
self.spin_queue, self.slashing = deque(), False
|
||||
|
||||
def draw(self, distance, middlex, middley, color=None):
|
||||
"""Draw the enemy, given distance between blocks and the middle
|
||||
block.
|
||||
"""Draw the enemy, given distance between grids and the middle
|
||||
grid.
|
||||
"""
|
||||
x = middlex + (self.x - MIDDLE)*distance
|
||||
y = middley + (self.y - MIDDLE)*distance
|
||||
x, y = pos(self.x, self.y, distance, middlex, middley)
|
||||
square = regpoly(4, int(distance / SQRT2), x, y, self.angle)
|
||||
fill_aapolygon(self.surface, square, color or self.color[self.wound])
|
||||
|
||||
def update(self, distance, middlex, middley):
|
||||
"""Update the enemy."""
|
||||
if (self.angle - pi/4) < FLOATING_ZERO: self.angle = pi / 4
|
||||
if (self.angle - pi/4) < EPSILON: self.angle = pi / 4
|
||||
self.draw(distance, middlex, middley, color=BG_COLOR)
|
||||
if not self.spin_queue:
|
||||
if self.awake and not self.spin_queue:
|
||||
self.spin_queue.extend([randsign()] * self.speed)
|
||||
if self.spin_queue and not self.moving:
|
||||
self.angle += self.spin_queue.popleft() * pi / 2 / self.speed
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
from pygame.locals import *
|
||||
from pygame.math import Vector2
|
||||
|
||||
FLOATING_ZERO = 8 ** -8
|
||||
EPSILON = 8 ** -8
|
||||
SQRT2 = 2 ** 0.5
|
||||
|
||||
FPS = 30
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# maze.py - module containing the maze object
|
||||
# This file is part of brutalmaze
|
||||
|
@ -19,12 +18,12 @@
|
|||
# Copyright (C) 2017 Nguyễn Gia Phong
|
||||
|
||||
from collections import deque
|
||||
from math import pi
|
||||
from math import atan, cos, sin, pi
|
||||
from random import getrandbits
|
||||
|
||||
import pygame
|
||||
|
||||
from .characters import regpoly, fill_aapolygon, Hero, Enemy
|
||||
from .characters import pos, regpoly, fill_aapolygon, Hero, Enemy
|
||||
from .constants import *
|
||||
|
||||
|
||||
|
@ -33,6 +32,11 @@ def sign(n):
|
|||
return -1 if n < 0 else 1 if n else 0
|
||||
|
||||
|
||||
def cosin(x):
|
||||
"""Return the sum of cosine and sine of x (measured in radians)."""
|
||||
return cos(x) + sin(x)
|
||||
|
||||
|
||||
class Maze:
|
||||
"""Object representing the maze, including the characters."""
|
||||
def __init__(self, size):
|
||||
|
@ -40,13 +44,13 @@ class Maze:
|
|||
self.surface = pygame.display.set_mode(size, RESIZABLE)
|
||||
self.distance = int((self.w * self.h / 416) ** 0.5)
|
||||
self.step = self.distance // 5
|
||||
self.x, self.y = self.w >> 1, self.h >> 1
|
||||
self.middlex, self.middley = self.x, self.y = self.w >> 1, self.h >> 1
|
||||
w, h = self.w//self.distance+2 >> 1, self.h//self.distance+2 >> 1
|
||||
self.rangex = range(MIDDLE - w, MIDDLE + w + 1)
|
||||
self.rangey = range(MIDDLE - h, MIDDLE + h + 1)
|
||||
|
||||
self.hero = Hero(self.surface)
|
||||
self.enemies = [Enemy(self.surface, 4, 35, 35)]
|
||||
self.enemies = [Enemy(self.surface, 4, 34, 34)]
|
||||
self.right = self.down = self.offsetx = self.offsety = 0
|
||||
|
||||
def wall(bit, upper=True):
|
||||
|
@ -68,38 +72,29 @@ class Maze:
|
|||
def draw(self):
|
||||
"""Draw the maze."""
|
||||
self.surface.fill(BG_COLOR)
|
||||
middlex = self.x + self.offsetx*self.step
|
||||
middley = self.y + self.offsety*self.step
|
||||
for i in self.rangex:
|
||||
for j in self.rangey:
|
||||
if not self.map[i][j]: continue
|
||||
x = middlex + (i - MIDDLE)*self.distance
|
||||
y = middley + (j - MIDDLE)*self.distance
|
||||
x, y = pos(i, j, self.distance, self.middlex, self.middley)
|
||||
square = regpoly(4, int(self.distance / SQRT2), x, y, pi / 4)
|
||||
fill_aapolygon(self.surface, square, FG_COLOR)
|
||||
|
||||
def resize(self, w, h):
|
||||
"""Resize the maze."""
|
||||
size = self.w, self.h = w, h
|
||||
self.surface = pygame.display.set_mode(size, RESIZABLE)
|
||||
self.hero.resize()
|
||||
|
||||
self.distance = int((w * h / 416) ** 0.5)
|
||||
self.step = self.distance // 5
|
||||
self.x, self.y = w >> 1, h >> 1
|
||||
w, h = self.w//self.distance+2 >> 1, self.h//self.distance+2 >> 1
|
||||
self.rangex = range(MIDDLE - w, MIDDLE + w + 1)
|
||||
self.rangey = range(MIDDLE - h, MIDDLE + h + 1)
|
||||
self.draw()
|
||||
|
||||
def move(self, x, y):
|
||||
"""Command the maze to move x step/frame faster to the left and
|
||||
y step/frame faster upward so the hero will move in the reverse
|
||||
direction.
|
||||
"""
|
||||
self.right += x
|
||||
self.down += y
|
||||
self.right, self.down = sign(self.right), sign(self.down)
|
||||
def wake(self, enemy):
|
||||
"""Wake the enemy up if it can see the hero."""
|
||||
dx = (enemy.x - MIDDLE)*self.distance + self.offsetx*self.step
|
||||
dy = (enemy.y - MIDDLE)*self.distance + self.offsety*self.step
|
||||
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 not self.map[i][j] or (i, j) == (enemy.x, enemy.y): continue
|
||||
x, y = pos(i, j, self.distance, self.middlex, self.middley)
|
||||
d = abs(dy*(x-self.x) - dx*(y-self.y)) / (dy**2 + dx**2)**0.5
|
||||
if d <= mind: return
|
||||
enemy.awake = True
|
||||
|
||||
def update(self):
|
||||
"""Update the maze."""
|
||||
|
@ -136,11 +131,38 @@ class Maze:
|
|||
for d in self.map: d.rotate(s)
|
||||
for enemy in self.enemies: enemy.place(0, s)
|
||||
|
||||
self.middlex = self.x + self.offsetx*self.step
|
||||
self.middley = self.y + self.offsety*self.step
|
||||
self.draw()
|
||||
for enemy in self.enemies:
|
||||
if not enemy.awake: self.wake(enemy)
|
||||
|
||||
middlex = self.x + self.offsetx*self.step
|
||||
middley = self.y + self.offsety*self.step
|
||||
for enemy in self.enemies:
|
||||
enemy.update(self.distance, middlex, middley)
|
||||
enemy.update(self.distance, self.middlex, self.middley)
|
||||
self.hero.update()
|
||||
pygame.display.flip()
|
||||
|
||||
def resize(self, w, h):
|
||||
"""Resize the maze."""
|
||||
size = self.w, self.h = w, h
|
||||
self.surface = pygame.display.set_mode(size, RESIZABLE)
|
||||
self.hero.resize()
|
||||
|
||||
self.distance = int((w * h / 416) ** 0.5)
|
||||
self.step = self.distance // 5
|
||||
self.middlex = self.x + self.offsetx*self.step
|
||||
self.middley = self.y + self.offsety*self.step
|
||||
self.x, self.y = w >> 1, h >> 1
|
||||
w, h = self.w//self.distance+2 >> 1, self.h//self.distance+2 >> 1
|
||||
self.rangex = range(MIDDLE - w, MIDDLE + w + 1)
|
||||
self.rangey = range(MIDDLE - h, MIDDLE + h + 1)
|
||||
self.draw()
|
||||
|
||||
def move(self, x, y):
|
||||
"""Command the maze to move x step/frame faster to the left and
|
||||
y step/frame faster upward so the hero will move in the reverse
|
||||
direction.
|
||||
"""
|
||||
self.right += x
|
||||
self.down += y
|
||||
self.right, self.down = sign(self.right), sign(self.down)
|
||||
|
|
Loading…
Reference in New Issue