Add Sphix documentation

This commit is contained in:
Matthias Richter 2015-10-09 23:10:15 +02:00
parent 01e8e17b92
commit 0b2167d7b5
12 changed files with 1587 additions and 0 deletions

8
docs/Class.rst Normal file
View File

@ -0,0 +1,8 @@
HC.class
========
::
class = require 'HC.class'
See ``hump.class``.

242
docs/MainModule.rst Normal file
View File

@ -0,0 +1,242 @@
Main Module
===========
::
HC = require 'HC'
The purpose of the main modules is to connect shapes with the spatial hash -- a
data structure to quickly look up neighboring shapes -- and to provide
utilities to tell which shapes intersect (collide) with each other.
Most of the time, HC will be run as a singleton; you can, however, also create
several instances, that each hold their own little worlds.
Initialization
--------------
.. function:: HC.new([cell_size = 100])
:param number cell_size: Resolution of the internal search structure (optional).
:returns: Collider instance.
Creates a new collider instance that holds a separate spatial hash.
Collider instances carry the same methods as the main module.
The only difference is that function calls must use the colon-syntax (see
below).
Useful if you want to maintain several collision layers or several separate
game worlds.
The ``cell_size`` somewhat governs the performance of :func:`HC.neighbors` and
:func:`HC.collisions`. How this parameter affects the performance depends on
how many shapes there are, how big these shapes are and (somewhat) how the
shapes are distributed.
A rule of thumb would be to set ``cell_size`` to be about four times the size
of the average object.
Or just leave it as is and worry about it only if you run into performance
problems that can be traced back to the spatial hash.
**Example**::
collider = HC.new(150) -- create separate world
-- method calls with colon syntax
ball = collider:circle(100,100,20)
rect = collider:rectangle(110,90,20,100)
for shape, delta in pairs(collider:collisions(ball)) do
shape:move(delta.x, delta.y)
end
.. function:: HC.resetHash([cell_size = 100])
:param number cell_size: Resolution of the internal search structure (optional).
Reset the internal search structure, the spatial hash.
This clears *all* shapes that were registered beforehand, meaning that HC will
not be able to find any collisions with those shapes anymore.
**Example**::
function new_stage()
actors = {} -- clear the stage on our side
HC.resetHash() -- as well as on HC's side
end
Bookkeeping
-----------
See also the :doc:`Shapes` sub-module.
.. function:: HC.rectangle(x, y, w, h)
:param numbers x,y: Upper left corner of the rectangle.
:param numbers w,h: Width and height of the rectangle.
:returns: The rectangle :class:`Shape` added to the scene.
Add a rectangle shape to the scene.
.. note::
:class:`Shape` transformations, e.g. :func:`Shape.moveTo` and
:func:`Shape.rotate` will be with respect to the *center, not* the upper left
corner of the rectangle!
**Example**::
rect = HC.rectangle(100, 120, 200, 40)
rect:rotate(23)
.. function:: HC.polygon(x1,y1,...,xn,yn)
:param numbers x1,y1,...,xn,yn: The corners of the polygon. At least three
corners that do not lie on a straight line
are required.
:returns: The polygon :class:`Shape` added to the scene.
Add a polygon to the scene. Any non-self-intersection polygon will work.
The polygon will be closed; the first and the last point do not need to be the
same.
.. note::
If three consecutive points lie on a line, the middle point will be discarded.
This means you cannot construct polygon shapes that are lines.
.. note::
:class:`Shape` transformations, e.g. :func:`Shape.moveTo` and
:func:`Shape.rotate` will be with respect to the center of the polygon.
**Example**::
shape = HC.polygon(10,10, 40,50, 70,10, 40,30)
shape:move(42, 5)
.. function:: HC.circle(cx, cy, radius)
:param numbers cx,cy: Center of the circle.
:param number radius: Radius of the circle.
:returns: The circle :class:`Shape` added to the scene.
Add a circle shape to the scene.
**Example**::
circle = HC.circle(400, 300, 100)
.. function:: HC.point(x, y)
:param numbers x, y: Position of the point.
:returns: The point :class:`Shape` added to the scene.
Add a point shape to the scene.
Point shapes are most useful for bullets and such, because detecting collisions
between a point and any other shape is a little faster than detecting collision
between two non-point shapes. In case of a collision, the separating vector
will not be valid.
**Example**::
bullets[#bulltes+1] = HC.point(player.pos.x, player.pos.y)
.. function:: HC.register(shape)
:param Shape shape: The :class:`Shape` to add to the spatial hash.
Add a shape to the bookkeeping system.
:func:`HC.neighbors` and :func:`Hc.collisions` works only with registered
shapes.
You don't need to (and should not) register any shapes created with the above
functions.
Overwrites :func:`Shape.move`, :func:`Shape.rotate`, and :func:`Shape.scale`
with versions that update the :doc:`SpatialHash`.
This function is mostly only useful if you provide a custom shape.
See :ref:`custom-shapes`.
.. function:: HC.remove(shape)
:param Shape shape: The :class:`Shape` to remove from the spatial hash.
Remove a shape to the bookkeeping system.
.. warning::
This will also invalidate the functions :func:`Shape.move`,
:func:`Shape.rotate`, and :func:`Shape.scale`.
Make sure you delete the shape from your own actor list(s).
**Example**::
for i = #bullets,1,-1 do
if bullets[i]:collidesWith(player)
player:takeDamage()
HC.remove(bullets[i]) -- remove bullet from HC
table.remove(bullets, i) -- remove bullet from own actor list
end
end
Collision Detection
-------------------
.. function:: HC.collisions(shape)
:param Shape shape: Query shape.
:returns: Table of colliding shapes and separating vectors.
Get shapes that are colliding with ``shape`` and the vector to separate the shapes.
The separating vector points away from ``shape``.
The table is a *set*, meaning that the shapes are stored in *keys* of the table.
The *values* are the separating vector.
You can iterate over the shapes using ``pairs`` (see example).
**Example**::
local collisions = HC.collisions(shape)
for other, separating_vector in pairs(collisions)
shape:move(-separating_vector.x/2, -separating_vector.y/2)
other:move( separating_vector.x/2, separating_vector.y/2)
end
.. function:: HC.neighbors(shape)
:param Shape shape: Query shape.
:returns: Table of neighboring shapes, where the keys of the table are the shape.
Get other shapes in that are close to ``shape``.
The table is a *set*, meaning that the shapes are stored in *keys* of the table.
You can iterate over the shapes using ``pairs`` (see example).
.. note::
The result depends on the size and position of ``shape`` as well as the
grid size of the spatial hash: :func:`HC.neighbors` returns the shapes that
are in the same cell(s) as ``shape``.
**Example**::
local candidates = HC.neighbors(shape)
for other in pairs(candidates)
local collides, dx, dy = shape:collidesWith(other)
if collides then
other:move(dx, dy)
end
end
.. attribute:: HC.hash
Reference to the :class:`SpatialHash` instance.

192
docs/Makefile Normal file
View File

@ -0,0 +1,192 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/HC.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/HC.qhc"
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/HC"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/HC"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

213
docs/Polygon.rst Normal file
View File

@ -0,0 +1,213 @@
HC.polygon
==============
::
polygon = require 'HC.polygon'
Polygon class with some handy algorithms. Does not provide collision detection
- this functionality is provided by :func:`newPolygonShape` instead.
.. class:: Polygon(x1,y1, ..., xn,yn)
:param numbers x1,y1, ..., xn,yn: The corners of the polygon. At least three corners are needed.
:returns: The polygon object.
Construct a polygon.
At least three points that are not collinear (i.e. not lying on a straight
line) are needed to construct the polygon. If there are collinear points, these
points will be removed. The shape of the polygon is not changed.
.. note::
The syntax depends on used class system. The shown syntax works when using
the bundled `hump.class <http://vrld.github.com/hump/#hump.class>`_ or
`slither <https://bitbucket.org/bartbes/slither>`_.
**Example**::
Polygon = require 'HC.polygon'
poly = Polygon(10,10, 40,50, 70,10, 40,30)
.. function:: Polygon:unpack()
:returns: ``x1,y1, ..., xn,yn`` - The vertices of the polygon.
Get the polygon's vertices. Useful for drawing with ``love.graphics.polygon()``.
**Example**::
love.graphics.draw('line', poly:unpack())
.. function:: Polygon:clone()
:returns: A copy of the polygon.
Get a copy of the polygon.
.. note::
Since Lua uses references when simply assigning an existing polygon to a
variable, unexpected things can happen when operating on the variable. Consider
this code::
p1 = Polygon(10,10, 40,50, 70,10, 40,30)
p2 = p1 -- p2 is a reference
p3 = p1:clone() -- p3 is a clone
p2:rotate(math.pi) -- p1 will be rotated, too!
p3:rotate(-math.pi) -- only p3 will be rotated
**Example**::
copy = poly:clone()
copy:move(10,20)
.. function:: Polygon:bbox()
:returns: ``x1, y1, x2, y2`` - Corners of the counding box.
Get axis aligned bounding box.
``x1, y1`` defines the upper left corner, while ``x2, y2`` define the lower
right corner.
**Example**::
x1,y1,x2,y2 = poly:bbox()
-- draw bounding box
love.graphics.rectangle('line', x1,y2, x2-x1, y2-y1)
.. function:: Polygon:isConvex()
:returns: ``true`` if the polygon is convex, ``false`` otherwise.
Test if a polygon is convex, i.e. a line line between any two points inside the
polygon will lie in the interior of the polygon.
**Example**::
-- split into convex sub polygons
if not poly:isConvex() then
list = poly:splitConvex()
else
list = {poly:clone()}
end
.. function:: Polygon:move(x,y)
:param numbers x, y: Coordinates of the direction to move.
Move a polygon in a direction..
**Example**::
poly:move(10,-5) -- move 10 units right and 5 units up
.. function:: Polygon:rotate(angle[, cx, cy])
:param number angle: The angle to rotate in radians.
:param numbers cx, cy: The rotation center (optional).
Rotate the polygon. You can define a rotation center. If it is omitted, the
polygon will be rotated around it's centroid.
**Example**::
p1:rotate(math.pi/2) -- rotate p1 by 90° around it's center
p2:rotate(math.pi/4, 100,100) -- rotate p2 by 45° around the point 100,100
.. function:: Polygon:triangulate()
:returns: ``table`` of Polygons: Triangles that the polygon is composed of.
Split the polygon into triangles.
**Example**::
triangles = poly:triangulate()
for i,triangle in ipairs(triangles) do
triangles.move(math.random(5,10), math.random(5,10))
end
.. function:: Polygon:splitConvex()
:returns: ``table`` of Polygons: Convex polygons that form the original polygon.
Split the polygon into convex sub polygons.
**Example**::
convex = concave_polygon:splitConvex()
function love.draw()
for i,poly in ipairs(convex) do
love.graphics.polygon('fill', poly:unpack())
end
end
.. function:: Polygon:mergedWith(other)
:param Polygon other: The polygon to merge with.
:returns: The merged polygon, or nil if the two polygons don't share an edge.
Create a merged polygon of two polygons **if, and only if** the two polygons
share one complete edge. If the polygons share more than one edge, the result
may be erroneous.
This function does not change either polygon, but rather creates a new one.
**Example**::
merged = p1:mergedWith(p2)
.. function:: Polygon:contains(x, y)
:param numbers x, y: Point to test.
:returns: ``true`` if ``x,y`` lies in the interior of the polygon.
Test if the polygon contains a given point.
**Example**::
if button:contains(love.mouse.getPosition()) then
button:setHovered(true)
end
.. function:: Polygon:intersectionsWithRay(x, y, dx, dy)
:param numbers x, y: Starting point of the ray.
:param numbers dx, dy: Direction of the ray.
:returns: Table of ray parameters.
Test if the polygon intersects the given ray.
The ray parameters of the intersections are returned as a table.
The position of the intersections can be computed as
``(x,y) + ray_parameter * (dx, dy)``.
.. function:: Polygon:intersectsRay(x, y, dx, dy)
:param numbers x, y: Starting point of the ray.
:param numbers dx, dy: Direction of the ray.
:returns: ``intersects, ray_parameter`` - intersection indicator and ray paremter.
Test if the polygon intersects a ray.
If the shape intersects the ray, the point of intersection can be computed by
``(x,y) + ray_parameter * (dx, dy)``.
**Example**::
if poly:intersectsRay(400,300, dx,dy) then
love.graphics.setLine(2) -- highlight polygon
end

303
docs/Shapes.rst Normal file
View File

@ -0,0 +1,303 @@
HC.shapes
=========
::
shapes = require 'HC.shapes'
Shape classes with collision detection methods.
This module defines methods to move, rotate and draw shapes created with the
main module.
As each shape is at it's core a Lua table, you can attach values and add
functions to it. Be careful not to use keys that name a function or start with
an underscore, e.g. `move` or `_rotation`, since these are used internally.
Everything else is fine.
If you don't want to use the full blown module, you can still use these classes
to test for colliding shapes.
This may be useful for scenes where the shapes don't move very much and only
few collisions are of interest - for example graphical user interfaces.
.. _shape-baseclass:
Base Class
----------
.. class:: Shape(type)
:param any type: Arbitrary type identifier of the shape's type.
Base class for all shapes. All shapes must conform to the interface defined below.
.. function:: Shape:move(dx, dy)
:param numbers dx,dy: Coordinates to move the shape by.
Move the shape *by* some distance.
**Example**::
circle:move(10, 15) -- move the circle 10 units right and 15 units down.
.. function:: Shape:moveTo(x, y)
:param numbers x,y: Coordinates to move the shape to.
Move the shape *to* some point. Most shapes will be *centered* on the point
``(x,y)``.
.. note::
Equivalent to::
local cx,cy = shape:center()
shape:move(x-cx, y-cy)
**Example**::
local x,y = love.mouse.getPosition()
circle:moveTo(x, y) -- move the circle with the mouse
.. function:: Shape:center()
:returns: ``x, y`` - The center of the shape.
Get the shape's center.
**Example**::
local cx, cy = circle:center()
print("Circle at:", cx, cy)
.. function:: Shape:rotate(angle[, cx, cy])
:param number angle: Amount of rotation in radians.
:param numbers cx, cy: Rotation center; defaults to the shape's center if omitted (optional).
Rotate the shape *by* some angle. A rotation center can be specified. If no
center is given, rotate around the center of the shape.
**Example**::
rectangle:rotate(math.pi/4)
.. function:: Shape:setRotation(angle[, cx, cy])
:param number angle: Amount of rotation in radians.
:param numbers cx, cy: Rotation center; defaults to the shape's center if omitted (optional).
Set the rotation of a shape. A rotation center can be specified. If no center
is given, rotate around the center of the shape.
.. note::
Equivalent to::
shape:rotate(angle - shape.rotation(), cx,cy)
**Example**::
rectangle:setRotation(math.pi, 100,100)
.. function:: Shape:rotation()
:returns: The shape's rotation in radians.
Get the rotation of the shape in radians.
.. function:: Shape:scale(s)
:param number s: Scale factor; must be > 0.
Scale the shape relative to it's center.
.. note::
There is no way to query the scale of a shape.
**Example**::
circle:scale(2) -- double the size
.. function:: Shape:outcircle()
:returns: ``x, y, r`` - Parameters of the outcircle.
Get parameters of a circle that fully encloses the shape.
**Example**::
if player:hasShield() then
love.graphics.circle('line', player:outcircle())
end
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
.. function:: Shape:bbox()
:returns: ``x1, y1, x2, y2`` - Corners of the counding box.
Get axis aligned bounding box.
``x1, y1`` defines the upper left corner, while ``x2, y2`` define the lower
right corner.
**Example**::
-- draw bounding box
local x1,y1, x2,y2 = shape:bbox()
love.graphics.rectangle('line', x1,y1, x2-x1,y2-y1)
.. function:: Shape:draw(mode)
:param DrawMode mode: How to draw the shape. Either 'line' or 'fill'.
Draw the shape either filled or as outline. Mostly for debug-purposes.
**Example**::
circle:draw('fill')
.. function:: Shape:support(dx,dy)
:param numbers dx, dy: Search direction.
:returns: The furthest vertex in direction `dx, dy`.
Get furthest vertex of the shape with respect to the direction ``dx, dy``.
Used in the collision detection algorithm, but may be useful for other things -
e.g. lighting - too.
**Example**::
-- get vertices that produce a shadow volume
local x1,y1 = circle:support(lx, ly)
local x2,y2 = circle:support(-lx, -ly)
.. function:: Shape:collidesWith(other)
:param Shape other: Test for collision with this shape.
:returns: ``collide, dx, dy`` - Collision indicator and separating vector.
Test if two shapes collide.
The separating vector ``dx, dy`` will only be defined if ``collide`` is ``true``.
If defined, the separating vector will point in the direction of ``other``,
i.e. ``dx, dy`` is the direction and magnitude to move ``other`` so that the
shapes do not collide anymore.
**Example**::
if circle:collidesWith(rectangle) then
print("collision detected!")
end
.. function:: Shape:contains(x, y)
:param numbers x, y: Point to test.
:returns: ``true`` if ``x,y`` lies in the interior of the shape.
Test if the shape contains a given point.
**Example**::
if unit.shape:contains(love.mouse.getPosition) then
unit:setHovered(true)
end
.. function:: Shape:intersectionsWithRay(x, y, dx, dy)
:param numbers x, y: Starting point of the ray.
:param numbers dx, dy: Direction of the ray.
:returns: Table of ray parameters.
Test if the shape intersects the given ray.
The ray parameters of the intersections are returned as a table.
The position of the intersections can be computed as
``(x,y) + ray_parameter * (dx, dy)``.
**Example**::
local ts = player:intersectionsWithRay(x,y, dx,dy)
for _, t in ipairs(t) do
-- find point of intersection
local vx,vy = vector.add(x, y, vector.mul(t, dx, dy))
player:addMark(vx,vy)
end
.. function:: Shape:intersectsRay(x, y, dx, dy)
:param numbers x, y: Starting point of the ray.
:param numbers dx, dy: Direction of the ray.
:returns: ``intersects, ray_parameter`` - intersection indicator and ray paremter.
Test if the shape intersects the given ray.
If the shape intersects the ray, the point of intersection can be computed by
``(x,y) + ray_parameter * (dx, dy)``.
**Example**::
local intersecting, t = player:intersectsRay(x,y, dx,dy)
if intersecting then
-- find point of intersection
local vx,vy = vector.add(x, y, vector.mul(t, dx, dy))
player:addMark(vx,vy)
end
.. _custom-shapes:
Custom Shapes
-------------
Custom shapes must implement at least the following methods (as defined above)
- :func:`Shape:move`
- :func:`Shape:rotate`
- :func:`Shape:scale`
- :func:`Shape:bbox`
- :func:`Shape:collidesWith`
.. _builtin-shapes:
Built-in Shapes
---------------
.. class:: ConcavePolygonShape
.. class:: ConvexPolygonShape
.. class:: CircleShape
.. class:: PointShape
.. function:: newPolygonShape(...)
:param numbers ...: Vertices of the :class:`Polygon`.
:returns: :class:`ConcavePolygonShape` or :class:`ConvexPolygonShape`.
.. function:: newCircleShape(cx, cy, radius)
:param numbers cx,cy: Center of the circle.
:param number radius: Radius of the circle.
:returns: :class:`CircleShape`.
.. function:: newPointShape
:param numbers x, y: Position of the point.
:returns: :class:`PointShape`.

164
docs/SpatialHash.rst Normal file
View File

@ -0,0 +1,164 @@
HC.spatialhash
==============
::
spatialhash = require 'HC.spatialhash'
A spatial hash implementation that supports scenes of arbitrary size. The hash
is sparse, which means that cells will only be created when needed.
.. class:: Spatialhash([cellsize = 100])
:param number cellsize: Width and height of a cell (optional).
Create a new spatial hash with a given cell size.
Choosing a good cell size depends on your application. To get a decent speedup,
the average cell should not contain too many objects, nor should a single
object occupy too many cells. A good rule of thumb is to choose the cell size
so that the average object will occupy only one cell.
.. note::
The syntax depends on used class system. The shown syntax works when using
the bundled `hump.class <http://vrld.github.com/hump/#hump.class>`_ or
`slither <https://bitbucket.org/bartbes/slither>`_.
**Example**::
Spatialhash = require 'hardoncollider.spatialhash'
hash = Spatialhash(150)
.. function:: Spatialhash:cellCoords(x,y)
:param numbers x, y: The position to query.
:returns: Coordinates of the cell which would contain ``x,y``.
Get coordinates of a given value, i.e. the cell index in which a given point
would be placed.
**Example**::
local mx,my = love.mouse.getPosition()
cx, cy = hash:cellCoords(mx, my)
.. function:: Spatialhash:cell(i,k)
:param numbers i, k: The cell index.
:returns: Set of objects contained in the cell.
Get the cell with given coordinates.
A cell is a table which's keys and value are the objects stored in the cell,
i.e.::
cell = {
[obj1] = obj1,
[obj2] = obj2,
...
}
You can iterate over the objects in a cell using ``pairs()``::
for object in pairs(cell) do stuff(object) end
**Example**::
local mx,my = love.mouse.getPosition()
cx, cy = hash:cellCoords(mx, my)
cell = hash:cell(cx, cy)
.. function:: Spatialhash:cellAt(x,y)
:param numbers x, y: The position to query.
:returns: Set of objects contained in the cell.
Get the cell that contains point x,y.
Same as ``hash:cell(hash:cellCoords(x,y))``
**Example**::
local mx,my = love.mouse.getPosition()
cell = hash:cellAt(mx, my)
.. function:: Spatialhash:shapes()
:returns: Set of all shapes in the hash.
Get *all* shapes that are recorded in the hash.
.. function:: Spatialhash:inSameCells(x1,y1, x2,y2)
:param numbers x1,y1: Upper left corner of the query bounding box.
:param numbers x2,y2: Lower right corner of the query bounding box.
:returns: Set of all shapes in the same cell as the bbox.
Get the shapes that are in the same cell as the defined bounding box.
.. function:: Spatialhash:register(obj, x1,y1, x2,y2)
:param mixed obj: Object to place in the hash. It can be of any type except `nil`.
:param numbers x1,y1: Upper left corner of the bounding box.
:param numbers x2,y2: Lower right corner of the bounding box.
Insert an object into the hash using a given bounding box.
**Example**::
hash:register(shape, shape:bbox())
.. function:: Spatialhash:remove(obj[, x1,y1[, x2,y2]])
:param mixed obj: The object to delete
:param numbers x1,y1: Upper left corner of the bounding box (optional).
:param numbers x2,y2: Lower right corner of the bounding box (optional).
Remove an object from the hash using a bounding box.
If no bounding box is given, search the whole hash to delete the object.
**Example**::
hash:remove(shape, shape:bbox())
hash:remove(object_with_unknown_position)
.. function:: Spatialhash:update(obj, x1,y1, x2,y2, x3,y3, x4,y4)
:param mixed obj: The object to be updated.
:param numbers x1,y1: Upper left corner of the bounding box before the object was moved.
:param numbers x2,y2: Lower right corner of the bounding box before the object was moved.
:param numbers x3,y3: Upper left corner of the bounding box after the object was moved.
:param numbers x4,y4: Lower right corner of the bounding box after the object was moved.
Update an objects position given the old bounding box and the new bounding box.
**Example**::
hash:update(shape, -100,-30, 0,60, -100,-70, 0,20)
.. function:: Spatialhash:draw(draw_mode[, show_empty = true[, print_key = false]])
:param string draw_mode: Either 'fill' or 'line'. See the LÖVE wiki.
:param boolean show_empty: Wether to draw empty cells (optional).
:param boolean print_key: Wether to print cell coordinates (optional).
Draw hash cells on the screen, mostly for debug purposes
**Example**::
love.graphics.setColor(160,140,100,100)
hash:draw('line', true, true)
hash:draw('fill', false)

8
docs/Vector.rst Normal file
View File

@ -0,0 +1,8 @@
HC.vector
=========
::
vector = require 'HC.vector'
See ``hump.vector_light``.

296
docs/conf.py Normal file
View File

@ -0,0 +1,296 @@
# -*- coding: utf-8 -*-
#
# HC documentation build configuration file, created by
# sphinx-quickstart on Thu Oct 8 20:31:43 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
import shlex
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.mathjax',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'HC'
copyright = u'2015, Matthias Richter'
author = u'Matthias Richter'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.1'
# The full version, including alpha/beta/rc tags.
release = '0.1-1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'HCdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'HC.tex', u'HC Documentation',
u'Matthias Richter', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'hc', u'HC Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'HC', u'HC Documentation',
author, 'HC', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
primary_domain = "js"
highlight_language = "lua"
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
#import sphinx_bootstrap_theme
#html_theme = 'bootstrap'
#html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()

115
docs/index.rst Normal file
View File

@ -0,0 +1,115 @@
.. HC documentation master file, created by
sphinx-quickstart on Thu Oct 8 20:31:43 2015.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
HC - General purpose collision detection with LÖVE_
===================================================
HC is a Lua module to simplify one important aspect in computer games:
Collision detection.
It can detect collisions between arbitrary positioned and rotated shapes.
Built-in shapes are points, circles and polygons.
Any non-intersecting polygons are supported, even concave ones.
You can add other types of shapes if you need them.
The main interface is simple:
- Define collision callbacks,
- Add shapes to the scene and
- Update HC every frame.
First steps
-----------
This is an example on how to use HC. One shape will stick to the mouse
position, while the other will stay in the same place::
HC = require 'HC'
-- array to hold collision messages
local text = {}
function love.load()
-- add a rectangle to the scene
rect = HC.rectangle(200,400,400,20)
-- add a circle to the scene
mouse = HC.circle(400,300,20)
mouse:moveTo(love.mouse.getPosition())
end
function love.update(dt)
-- move circle to mouse position
mouse:moveTo(love.mouse.getPosition())
-- rotate rectangle
rect:rotate(dt)
-- check for collisions
for shape, delta in pairs(HC.collisions(mouse)) do
text[#text+1] = string.format("Colliding. Separating vector = (%s,%s)",
delta.x, delta.y)
end
while #text > 40 do
table.remove(text, 1)
end
end
function love.draw()
-- print messages
for i = 1,#text do
love.graphics.setColor(255,255,255, 255 - (i-1) * 6)
love.graphics.print(text[#text - (i-1)], 10, i * 15)
end
-- shapes can be drawn to the screen
love.graphics.setColor(255,255,255)
rect:draw('fill')
mouse:draw('fill')
end
Get HC
------
You can download the latest packaged version as `zip <https://github.com/vrld/HC/zipball/master>`_- or `tar <https://github.com/vrld/HC/tarball/master>`_-archive directly
from github_.
You can also have a look at the sourcecode online `here <http://github.com/vrld/HC>`_.
If you use the Git command line client, you can clone the repository by
running::
git clone git://github.com/vrld/HC.git
Once done, you can check for updates by running::
git pull
from inside the directory.
Read on
-------
.. toctree::
:maxdepth: 2
reference
tutorial
license
Indices and tables
^^^^^^^^^^^^^^^^^^
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. _LÖVE: http://love2d.org
.. _github: https://github.com

26
docs/license.rst Normal file
View File

@ -0,0 +1,26 @@
License
=======
Copyright (c) 2011-2015 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

16
docs/reference.rst Normal file
View File

@ -0,0 +1,16 @@
Reference
=========
HC is composed of several parts. Most of the time, you will only have to deal
with the main module and the `Shapes` sub-module, but the other modules are
at your disposal if you need them.
.. toctree::
:maxdepth: 2
HC <MainModule>
HC.shapes <Shapes>
HC.polygon <Polygon>
HC.spatialhash <SpatialHash>
HC.vector <Vector>
HC.class <Class>

4
docs/tutorial.rst Normal file
View File

@ -0,0 +1,4 @@
Tutorial
========
To be rewritten.