Complete enemies' spawning and movement

This commit is contained in:
Nguyễn Gia Phong 2017-10-14 21:49:37 +07:00
parent 62c8b2a81c
commit aa881a5a43
3 changed files with 43 additions and 27 deletions

View File

@ -106,10 +106,11 @@ class Hero:
class Enemy:
"""Object representing an enemy."""
def __init__(self, surface, maze, n, x, y):
def __init__(self, surface, maze, kind, x, y):
self.surface, self.maze = surface, maze
self.angle, self.color = pi / 4, TANGO[TANGO_KEYS[n]]
self.angle, self.color = pi / 4, TANGO[kind]
self.x, self.y = x, y
self.maze[x][y] = ENEMY
self.awake = False
self.offsetx = self.offsety = 0
@ -128,7 +129,10 @@ class Enemy:
def place(self, x=0, y=0):
"""Move the enemy by (x, y)."""
self.x += x
self.x %= len(self.maze)
self.y += y
self.y %= len(self.maze)
self.maze[self.x][self.y] = ENEMY
def move(self):
"""Handle the movement of the enemy.
@ -145,9 +149,9 @@ class Enemy:
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
if (x or y) and self.maze[self.x + x][self.y + y] == EMPTY:
self.offsetx, self.offsety = x * -4, y * -4
self.maze[self.x][self.y] = EMPTY
self.place(x, y)
return True
return False

View File

@ -21,6 +21,8 @@ from pygame.locals import *
from pygame.math import Vector2
SQRT2 = 2 ** 0.5
EMPTY, WALL, HERO, ENEMY = range(4)
ADJACENT_GRIDS = (1, 0), (0, 1), (-1, 0), (0, -1)
FPS = 30
SIZE = 400, 400
@ -37,7 +39,7 @@ TANGO = {'Butter': ((252, 233, 79), (237, 212, 0), (196, 160, 0)),
'Scarlet Red': ((239, 41, 41), (204, 0, 0), (164, 0, 0)),
'Aluminium': ((238, 238, 236), (211, 215, 207), (186, 189, 182),
(136, 138, 133), (85, 87, 83), (46, 52, 54))}
TANGO_KEYS = ('Butter', 'Orange', 'Chocolate', 'Chameleon',
'Sky Blue', 'Plum', 'Scarlet Red', 'Aluminium')
ENEMIES = ('Butter', 'Orange', 'Chocolate', 'Chameleon',
'Sky Blue', 'Plum', 'Scarlet Red')
BG_COLOR = TANGO['Aluminium'][-1]
FG_COLOR = TANGO['Aluminium'][0]

View File

@ -19,7 +19,7 @@
from collections import deque
from math import atan, cos, sin, pi
from random import getrandbits
from random import choice, getrandbits, randint
import pygame
@ -45,9 +45,9 @@ class Maze:
self.rangey = range(MIDDLE - h, MIDDLE + h + 1)
def wall(bit, upper=True):
if bit: return deque([True]*ROAD_WIDTH + [False]*ROAD_WIDTH)
if upper: return deque([True] * (ROAD_WIDTH<<1))
return deque([False] * (ROAD_WIDTH<<1))
if bit: return deque([WALL]*ROAD_WIDTH + [EMPTY]*ROAD_WIDTH)
if upper: return deque([WALL] * (ROAD_WIDTH<<1))
return deque([EMPTY] * (ROAD_WIDTH<<1))
self.map = deque()
for _ in range(MAZE_SIZE):
@ -58,8 +58,16 @@ 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.enemies = []
while len(self.enemies) < 8:
x, y = MIDDLE + randint(-w, w), MIDDLE + randint(-h, h)
if self.map[x][y] != WALL: continue
if all(self.map[x + a][y + b] == WALL for a, b in ADJACENT_GRIDS):
continue
self.enemies.append(
Enemy(self.surface, self.map, choice(ENEMIES), x, y))
self.hero = Hero(self.surface)
self.enemies = [Enemy(self.surface, self.map, 4, 34, 34)]
self.map[MIDDLE][MIDDLE] = HERO
self.right = self.down = self.offsetx = self.offsety = 0
self.draw()
@ -68,7 +76,7 @@ class Maze:
self.surface.fill(BG_COLOR)
for i in self.rangex:
for j in self.rangey:
if not self.map[i][j]: continue
if self.map[i][j] != WALL: continue
x, y = pos(i, j, self.distance, self.middlex, self.middley)
square = regpoly(4, int(self.distance / SQRT2), pi / 4, x, y)
fill_aapolygon(self.surface, square, FG_COLOR)
@ -84,12 +92,23 @@ class Maze:
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
if self.map[i][j] != WALL: 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 rotate(self, x, y):
"""Rotate the maze by (x, y)."""
for enemy in self.enemies: self.map[enemy.x][enemy.y] = EMPTY
if x:
self.offsetx = 0
self.map.rotate(x)
if y:
self.offsety = 0
for d in self.map: d.rotate(y)
for enemy in self.enemies: enemy.place(x, y)
def update(self):
"""Update the maze."""
modified = False
@ -114,19 +133,10 @@ 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(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(y=s)
self.map[MIDDLE][MIDDLE] = None
self.map[MIDDLE][MIDDLE] = EMPTY
self.rotate(sign(self.offsetx) * (abs(self.offsetx)==5),
sign(self.offsety) * (abs(self.offsety)==5))
self.map[MIDDLE][MIDDLE] = HERO
self.middlex = self.x + self.offsetx*self.step
self.middley = self.y + self.offsety*self.step
self.draw()