Make enemies chase the hero
This commit is contained in:
parent
05bfead6e9
commit
62c8b2a81c
|
@ -19,6 +19,7 @@
|
|||
|
||||
from collections import deque
|
||||
from math import atan2, cos, sin, pi
|
||||
from random import shuffle
|
||||
|
||||
import pygame
|
||||
from pygame.gfxdraw import filled_polygon, aapolygon
|
||||
|
@ -31,7 +32,7 @@ def randsign():
|
|||
return (pygame.time.get_ticks() & 1)*2 - 1
|
||||
|
||||
|
||||
def regpoly(n, R, x, y, r):
|
||||
def regpoly(n, R, r, x, y):
|
||||
"""Return the pointlist of the regular polygon with n sides,
|
||||
circumradius of R, the center point I(x, y) and one point A make the
|
||||
vector IA with angle r (in radians).
|
||||
|
@ -52,6 +53,11 @@ def pos(x, y, distance, middlex, middley):
|
|||
return middlex + (x - MIDDLE)*distance, middley + (y - MIDDLE)*distance
|
||||
|
||||
|
||||
def sign(n):
|
||||
"""Return the sign of number n."""
|
||||
return -1 if n < 0 else 1 if n else 0
|
||||
|
||||
|
||||
class Hero:
|
||||
"""Object representing the hero."""
|
||||
def __init__(self, surface):
|
||||
|
@ -75,7 +81,7 @@ class Hero:
|
|||
|
||||
def draw(self, color=None):
|
||||
"""Draw the hero."""
|
||||
trigon = regpoly(3, self.R, self.x, self.y, self.angle)
|
||||
trigon = regpoly(3, self.R, self.angle, self.x, self.y)
|
||||
fill_aapolygon(self.surface, trigon, color or self.color[self.wound])
|
||||
|
||||
def update(self):
|
||||
|
@ -100,38 +106,58 @@ class Hero:
|
|||
|
||||
class Enemy:
|
||||
"""Object representing an enemy."""
|
||||
def __init__(self, surface, n, x, y):
|
||||
self.surface = surface
|
||||
self.x, self.y = x, y
|
||||
def __init__(self, surface, maze, n, x, y):
|
||||
self.surface, self.maze = surface, maze
|
||||
self.angle, self.color = pi / 4, TANGO[TANGO_KEYS[n]]
|
||||
self.x, self.y = x, y
|
||||
|
||||
self.awake, self.moving = False, False
|
||||
self.wound = 0
|
||||
self.awake = False
|
||||
self.offsetx = self.offsety = 0
|
||||
self.spin_queue = []
|
||||
self.speed = FPS // len(self.color)
|
||||
self.spin_queue, self.slashing = deque(), False
|
||||
self.wound = 0
|
||||
|
||||
def draw(self, distance, middlex, middley, color=None):
|
||||
"""Draw the enemy, given distance between grids and the middle
|
||||
grid.
|
||||
"""
|
||||
"""Draw the enemy, given distance between grids and the middle grid."""
|
||||
x, y = pos(self.x, self.y, distance, middlex, middley)
|
||||
square = regpoly(4, int(distance / SQRT2), x, y, self.angle)
|
||||
step = distance // 5
|
||||
square = regpoly(4, int(distance / SQRT2), self.angle,
|
||||
x + self.offsetx*step, y + self.offsety*step)
|
||||
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) < EPSILON: self.angle = pi / 4
|
||||
self.draw(distance, middlex, middley, color=BG_COLOR)
|
||||
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
|
||||
self.draw(distance, middlex, middley)
|
||||
|
||||
def place(self, x, y):
|
||||
def place(self, x=0, y=0):
|
||||
"""Move the enemy by (x, y)."""
|
||||
self.x += x
|
||||
self.y += y
|
||||
|
||||
def move(self, x, y):
|
||||
"""Command the enemy to move by (x, y)."""
|
||||
def move(self):
|
||||
"""Handle the movement of the enemy.
|
||||
|
||||
Return True if it moved, False otherwise.
|
||||
"""
|
||||
if self.offsetx:
|
||||
self.offsetx -= sign(self.offsetx)
|
||||
return True
|
||||
if self.offsety:
|
||||
self.offsety -= sign(self.offsety)
|
||||
return True
|
||||
|
||||
directions = [(sign(MIDDLE - self.x), 0), (0, sign(MIDDLE - self.y))]
|
||||
shuffle(directions)
|
||||
for x, y in directions:
|
||||
if (x or y) and self.maze[self.x + x][self.y + y] == False:
|
||||
self.offsetx = x * -4
|
||||
self.offsety = y * -4
|
||||
self.place(x, y)
|
||||
return True
|
||||
return False
|
||||
|
||||
def update(self, distance, middlex, middley):
|
||||
"""Update the enemy."""
|
||||
if self.awake:
|
||||
self.draw(distance, middlex, middley, color=BG_COLOR)
|
||||
if not self.spin_queue and not self.move():
|
||||
self.spin_queue.extend([randsign()] * self.speed)
|
||||
if self.spin_queue:
|
||||
self.angle += self.spin_queue.pop() * pi / 2 / self.speed
|
||||
self.draw(distance, middlex, middley)
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
from pygame.locals import *
|
||||
from pygame.math import Vector2
|
||||
|
||||
EPSILON = 8 ** -8
|
||||
SQRT2 = 2 ** 0.5
|
||||
|
||||
FPS = 30
|
||||
|
|
|
@ -23,15 +23,10 @@ from random import getrandbits
|
|||
|
||||
import pygame
|
||||
|
||||
from .characters import pos, regpoly, fill_aapolygon, Hero, Enemy
|
||||
from .characters import pos, sign, regpoly, fill_aapolygon, Hero, Enemy
|
||||
from .constants import *
|
||||
|
||||
|
||||
def sign(n):
|
||||
"""Return the sign of number 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)
|
||||
|
@ -49,10 +44,6 @@ class Maze:
|
|||
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, 34, 34)]
|
||||
self.right = self.down = self.offsetx = self.offsety = 0
|
||||
|
||||
def wall(bit, upper=True):
|
||||
if bit: return deque([True]*ROAD_WIDTH + [False]*ROAD_WIDTH)
|
||||
if upper: return deque([True] * (ROAD_WIDTH<<1))
|
||||
|
@ -67,6 +58,9 @@ class Maze:
|
|||
lower.extend(wall(b, False))
|
||||
for _ in range(ROAD_WIDTH): self.map.append(upper.__copy__())
|
||||
for _ in range(ROAD_WIDTH): self.map.append(lower.__copy__())
|
||||
self.hero = Hero(self.surface)
|
||||
self.enemies = [Enemy(self.surface, self.map, 4, 34, 34)]
|
||||
self.right = self.down = self.offsetx = self.offsety = 0
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
|
@ -76,7 +70,7 @@ class Maze:
|
|||
for j in self.rangey:
|
||||
if not self.map[i][j]: continue
|
||||
x, y = pos(i, j, self.distance, self.middlex, self.middley)
|
||||
square = regpoly(4, int(self.distance / SQRT2), x, y, pi / 4)
|
||||
square = regpoly(4, int(self.distance / SQRT2), pi / 4, x, y)
|
||||
fill_aapolygon(self.surface, square, FG_COLOR)
|
||||
|
||||
def wake(self, enemy):
|
||||
|
@ -120,16 +114,18 @@ class Maze:
|
|||
modified = True
|
||||
|
||||
if modified:
|
||||
self.map[MIDDLE][MIDDLE] = False
|
||||
if abs(self.offsetx) == 5:
|
||||
s = sign(self.offsetx)
|
||||
self.offsetx = 0
|
||||
self.map.rotate(s)
|
||||
for enemy in self.enemies: enemy.place(s, 0)
|
||||
for enemy in self.enemies: enemy.place(x=s)
|
||||
if abs(self.offsety) == 5:
|
||||
s = sign(self.offsety)
|
||||
self.offsety = 0
|
||||
for d in self.map: d.rotate(s)
|
||||
for enemy in self.enemies: enemy.place(0, s)
|
||||
for enemy in self.enemies: enemy.place(y=s)
|
||||
self.map[MIDDLE][MIDDLE] = None
|
||||
|
||||
self.middlex = self.x + self.offsetx*self.step
|
||||
self.middley = self.y + self.offsety*self.step
|
||||
|
|
Loading…
Reference in New Issue