Make recoil independant from FPS and limit shooting speed
This commit is contained in:
parent
c32bc50f58
commit
1ec17fa772
|
@ -66,11 +66,16 @@ def neighbors(x, y, z):
|
|||
for i, j, k in NEIGHBORS: yield x + i*12, y + j*12, z + k*9
|
||||
|
||||
|
||||
def norm(vector):
|
||||
"""Return the norm of the given vector."""
|
||||
return numpy.sqrt(numpy.sum(vector**2))
|
||||
|
||||
|
||||
def normalized(*vector):
|
||||
"""Return normalized vector as a NumPy array of float32."""
|
||||
v = numpy.float32(vector)
|
||||
if not any(v): return v
|
||||
return v / numpy.sqrt(numpy.sum(v**2))
|
||||
if not v.any(): return v
|
||||
return v / norm(v)
|
||||
|
||||
|
||||
def sign(x) -> int:
|
||||
|
|
41
axuy/pico.py
41
axuy/pico.py
|
@ -18,13 +18,21 @@
|
|||
|
||||
__doc__ = 'Axuy module for character class'
|
||||
|
||||
from itertools import combinations
|
||||
from math import pi, sqrt
|
||||
from random import random
|
||||
|
||||
import numpy as np
|
||||
from pyrr import matrix33
|
||||
|
||||
from .misc import normalized, placeable
|
||||
from .misc import norm, normalized, placeable
|
||||
|
||||
TETRAVERTICES = np.float32([[0, sqrt(8), -1], [sqrt(6), -sqrt(2), -1],
|
||||
[0, 0, 3], [-sqrt(6), -sqrt(2), -1]]) / 18
|
||||
OCTOVERTICES = np.float32([(a + b) / 2.0
|
||||
for a, b in combinations(TETRAVERTICES, 2)])
|
||||
RPICO = norm(TETRAVERTICES[0])
|
||||
RSHARD = norm(OCTOVERTICES[0])
|
||||
|
||||
INVX = np.float32([[-1, 0, 0], [0, 1, 0], [0, 0, 1]])
|
||||
INVY = np.float32([[1, 0, 0], [0, -1, 0], [0, 0, 1]])
|
||||
|
@ -33,11 +41,12 @@ INVZ = np.float32([[1, 0, 0], [0, 1, 0], [0, 0, -1]])
|
|||
PICO_SPEED = 1 + sqrt(5) # in unit/s
|
||||
SHARD_SPEED = PICO_SPEED * 2 # in unit/s
|
||||
SHARD_LIFE = 3 # bounces
|
||||
RPS = 6 # rounds per second
|
||||
|
||||
|
||||
class Shard:
|
||||
"""Fragment broken or shot out of a Picobot, which is a regular
|
||||
octahedron whose circumscribed sphere's radius is 1/12 unit.
|
||||
octahedron whose circumscribed sphere's radius is RSHARD.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
@ -94,7 +103,7 @@ class Shard:
|
|||
if x is None: x = self.x
|
||||
if y is None: y = self.y
|
||||
if z is None: z = self.z
|
||||
return not placeable(self.space, x, y, z, r=1/12)
|
||||
return not placeable(self.space, x, y, z, r=RSHARD)
|
||||
|
||||
def update(self, fps):
|
||||
"""Update states."""
|
||||
|
@ -119,7 +128,7 @@ class Shard:
|
|||
|
||||
class Picobot:
|
||||
"""Game character, which is represented as a regular tetrahedron
|
||||
whose circumscribed sphere's radius is 1/4 unit.
|
||||
whose circumscribed sphere's radius is RPICO.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
@ -144,6 +153,10 @@ class Picobot:
|
|||
Rotational matrix.
|
||||
shards : dict of Shard
|
||||
Active shards.
|
||||
recoil_u : np.ndarray of length 3 of np.float32
|
||||
Recoil direction (unit vector).
|
||||
recoil_t : float
|
||||
Recoil time left in seconds.
|
||||
fps : float
|
||||
Currently rendered frames per second.
|
||||
"""
|
||||
|
@ -166,6 +179,7 @@ class Picobot:
|
|||
self.rot = rotation
|
||||
|
||||
self.shards = {}
|
||||
self.recoil_u, self.recoil_t = np.float32([0, 0, 0]), 0.0
|
||||
self.fps = 60.0
|
||||
|
||||
@property
|
||||
|
@ -192,7 +206,7 @@ class Picobot:
|
|||
if x is None: x = self.x
|
||||
if y is None: y = self.y
|
||||
if z is None: z = self.z
|
||||
return placeable(self.space, x, y, z, 1/4)
|
||||
return placeable(self.space, x, y, z, RPICO)
|
||||
|
||||
def rotate(self, yaw, pitch):
|
||||
"""Rotate yaw radians around y-axis
|
||||
|
@ -202,14 +216,25 @@ class Picobot:
|
|||
@ matrix33.create_from_y_rotation(yaw) @ self.rot)
|
||||
|
||||
def move(self, right=0, upward=0, forward=0):
|
||||
"""Try to move in the given direction."""
|
||||
"""Try to move in the given direction.
|
||||
|
||||
This is the equivalence of Shard.update
|
||||
and should be called every loop.
|
||||
"""
|
||||
dt = 1.0 / self.fps
|
||||
direction = normalized(right, upward, forward) @ self.rot
|
||||
x, y, z = self.pos + direction/self.fps*PICO_SPEED
|
||||
if self.recoil_t:
|
||||
direction += self.recoil_u * self.recoil_t * RPS
|
||||
self.recoil_t = max(self.recoil_t - dt, 0.0)
|
||||
x, y, z = self.pos + direction*dt*PICO_SPEED
|
||||
if self.placeable(x=x): self.x = x % 12
|
||||
if self.placeable(y=y): self.y = y % 12
|
||||
if self.placeable(z=z): self.z = z % 9
|
||||
|
||||
def shoot(self):
|
||||
self.move(forward=-1)
|
||||
"""Shoot in the forward direction."""
|
||||
if self.recoil_t: return
|
||||
self.recoil_t = 1.0 / RPS
|
||||
self.recoil_u = [0, 0, -1] @ self.rot
|
||||
self.shards[max(self.shards, default=0) + 1] = Shard(
|
||||
self.addr, self.space, self.pos, self.rot)
|
||||
|
|
11
axuy/view.py
11
axuy/view.py
|
@ -20,9 +20,9 @@ __doc__ = 'Axuy module for map class'
|
|||
|
||||
from collections import deque
|
||||
from configparser import ConfigParser
|
||||
from itertools import combinations, product
|
||||
from itertools import product
|
||||
from os.path import join as pathjoin, pathsep
|
||||
from math import degrees, log2, radians, sqrt
|
||||
from math import degrees, log2, radians
|
||||
from random import randint
|
||||
from re import IGNORECASE, match
|
||||
from statistics import mean
|
||||
|
@ -36,7 +36,7 @@ from appdirs import AppDirs
|
|||
from PIL import Image
|
||||
from pyrr import Matrix44
|
||||
|
||||
from .pico import SHARD_LIFE, Picobot
|
||||
from .pico import TETRAVERTICES, OCTOVERTICES, SHARD_LIFE, Picobot
|
||||
from .misc import abspath, color, neighbors
|
||||
|
||||
CONTROL_ALIASES = (('Move left', 'left'), ('Move right', 'right'),
|
||||
|
@ -58,12 +58,7 @@ OYZ = np.float32([[0, 0, 0], [0, 1, 0], [0, 1, 1],
|
|||
OZX = np.float32([[0, 0, 0], [1, 0, 0], [1, 0, 1],
|
||||
[1, 0, 1], [0, 0, 1], [0, 0, 0]])
|
||||
|
||||
TETRAVERTICES = np.float32([[0, sqrt(8), -1], [sqrt(6), -sqrt(2), -1],
|
||||
[0, 0, 3], [-sqrt(6), -sqrt(2), -1]]) / 18
|
||||
TETRAINDECIES = np.int32([0, 1, 2, 3, 1, 2, 0, 3, 2, 0, 3, 1])
|
||||
|
||||
OCTOVERTICES = np.float32([(a + b) / 2
|
||||
for a, b in combinations(TETRAVERTICES, 2)])
|
||||
OCTOINDECIES = np.int32([0, 1, 2, 0, 1, 3, 4, 0, 2, 4, 0, 3,
|
||||
2, 1, 5, 3, 1, 5, 2, 5, 4, 3, 5, 4])
|
||||
|
||||
|
|
Loading…
Reference in New Issue