Revise geometry and physics

Shards are now rotated to look better.  Pico get recoiled while firing.
Size of these objects are tweaked.  Vector normalize function is fixed.
Graphics get less edgy.
This commit is contained in:
Nguyễn Gia Phong 2019-08-24 16:05:47 +07:00
parent a8babebfdf
commit c32bc50f58
6 changed files with 19 additions and 32 deletions

View File

@ -13,5 +13,5 @@ The game is still under development. For testing, first install GLFW version 3.3
$ git clone https://github.com/McSinyx/axuy.git
$ pip3 install --user --editable axuy
$ axuy --port=42069 &
$ axuy --seeder=localhost:42069
$ axuy --seeder=:42069
```

View File

@ -70,7 +70,7 @@ def normalized(*vector):
"""Return normalized vector as a NumPy array of float32."""
v = numpy.float32(vector)
if not any(v): return v
return v / sum(v**2)
return v / numpy.sqrt(numpy.sum(v**2))
def sign(x) -> int:

View File

@ -16,7 +16,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with Axuy. If not, see <https://www.gnu.org/licenses/>.
__version__ = '0.0.3'
__version__ = '0.0.4'
__doc__ = 'Axuy main loop'
from argparse import ArgumentParser, RawTextHelpFormatter

View File

@ -30,9 +30,8 @@ INVX = np.float32([[-1, 0, 0], [0, 1, 0], [0, 0, 1]])
INVY = np.float32([[1, 0, 0], [0, -1, 0], [0, 0, 1]])
INVZ = np.float32([[1, 0, 0], [0, 1, 0], [0, 0, -1]])
# Magic numbers. Do not try to figure out what they mean.
PICO_SPEED = (1+sqrt(5)) / 2 # in unit/s
SHARD_SPEED = PICO_SPEED * 243**0.25 # in unit/s
PICO_SPEED = 1 + sqrt(5) # in unit/s
SHARD_SPEED = PICO_SPEED * 2 # in unit/s
SHARD_LIFE = 3 # bounces
@ -211,5 +210,6 @@ class Picobot:
if self.placeable(z=z): self.z = z % 9
def shoot(self):
self.move(forward=-1)
self.shards[max(self.shards, default=0) + 1] = Shard(
self.addr, self.space, self.pos, self.rot)

View File

@ -20,7 +20,7 @@ __doc__ = 'Axuy module for map class'
from collections import deque
from configparser import ConfigParser
from itertools import product
from itertools import combinations, product
from os.path import join as pathjoin, pathsep
from math import degrees, log2, radians, sqrt
from random import randint
@ -49,7 +49,6 @@ GLFW_VER_WARN = 'Your GLFW version appear to be lower than 3.3, '\
ZMIN, ZMAX = -1.0, 1.0
CONWAY = 1.303577269034
EDGE_BRIGHTNESS = 1/6
QUAD = np.float32([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]).tobytes()
OXY = np.float32([[0, 0, 0], [1, 0, 0], [1, 1, 0],
@ -60,13 +59,13 @@ 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]]) / 12
[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([[-1, 0, 0], [0, -1, 0], [0, 0, -1],
[0, 1, 0], [0, 0, 1], [1, 0, 0]]) / 12
OCTOINDECIES = np.int32([0, 1, 2, 0, 1, 4, 3, 0, 2, 3, 0, 4,
2, 1, 5, 4, 1, 5, 2, 5, 3, 4, 5, 3])
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])
with open(abspath('shaders/map.vert')) as f: MAP_VERTEX = f.read()
with open(abspath('shaders/pico.vert')) as f: PICO_VERTEX = f.read()
@ -239,12 +238,12 @@ class View:
Processed executable code in GLSL for map rendering.
mapva : moderngl.VertexArray
Vertex data of the map.
prog2, prog3 : moderngl.Program
prog3 : moderngl.Program
Processed executable code in GLSL
for rendering picobots and their shards.
pva2, pva3 : moderngl.VertexArray
pva3 : moderngl.VertexArray
Vertex data of picobots.
sva2, sva3 : moderngl.VertexArray
sva3 : moderngl.VertexArray
Vertex data of shards.
pfilter : moderngl.VertexArray
Vertex data for filtering highly saturated colors.
@ -338,11 +337,6 @@ class View:
svb = [(context.buffer(OCTOVERTICES.tobytes()), '3f', 'in_vert')]
sib = context.buffer(OCTOINDECIES.tobytes())
self.prog2 = context.program(vertex_shader=PICO_VERTEX,
geometry_shader=LINE_GEOMETRY,
fragment_shader=WORLD_FRAGMENT)
self.pva2 = context.vertex_array(self.prog2, pvb, pib)
self.sva2 = context.vertex_array(self.prog2, svb, sib)
self.prog3 = context.program(vertex_shader=PICO_VERTEX,
geometry_shader=TRIANGLE_GEOMETRY,
fragment_shader=WORLD_FRAGMENT)
@ -494,26 +488,22 @@ class View:
"""Return whether given keys are pressed."""
return any(glfw.get_key(self.window, k) == glfw.PRESS for k in keys)
def prender(self, obj, va2, va3, col, bright=1.0):
def prender(self, obj, va3, col, bright=1.0):
"""Render the obj and its images in bounded 3D space."""
rotation = Matrix44.from_matrix33(obj.rot).astype(np.float32).tobytes()
position = obj.pos.astype(np.float32).tobytes()
self.prog2['rot'].write(rotation)
self.prog3['rot'].write(rotation)
self.prog2['pos'].write(position)
self.prog3['pos'].write(position)
self.prog2['color'].write(color(col, bright*EDGE_BRIGHTNESS).tobytes())
self.prog3['color'].write(color(col, bright).tobytes())
va2.render(moderngl.LINES)
va3.render(moderngl.TRIANGLES)
def render_pico(self, pico):
"""Render pico and its images in bounded 3D space."""
self.prender(pico, self.pva2, self.pva3, self.colors[pico.addr])
self.prender(pico, self.pva3, self.colors[pico.addr])
def render_shard(self, shard):
"""Render shard and its images in bounded 3D space."""
self.prender(shard, self.sva2, self.sva3,
self.prender(shard, self.sva3,
self.colors[shard.addr], shard.power/SHARD_LIFE)
def add_pico(self, address, position, rotation):
@ -536,11 +526,8 @@ class View:
self.mapva.render(moderngl.TRIANGLES)
# Render picos and shards
self.prog2['visibility'].value = visibility
self.prog3['visibility'].value = visibility
self.prog2['camera'].write(self.pos.tobytes())
self.prog3['camera'].write(self.pos.tobytes())
self.prog2['vp'].write(vp)
self.prog3['vp'].write(vp)
with self.lock:

View File

@ -6,7 +6,7 @@ with open('README.md') as f:
setup(
name='axuy',
version='0.0.3',
version='0.0.4',
description='Minimalist first-person shooter',
long_description=long_description,
long_description_content_type='text/markdown',