From 3399422099b97749bb2573b5cb21b77b5b738e50 Mon Sep 17 00:00:00 2001 From: Tim Martin Date: Thu, 21 May 2015 15:58:28 -0400 Subject: [PATCH 01/15] A very simple logging function --- src/crafty.js | 1 + src/debug/logging.js | 23 +++++++++++++++++++++++ tests/debug.js | 25 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 src/debug/logging.js diff --git a/src/crafty.js b/src/crafty.js index dc5d45fc..e1e6ae81 100644 --- a/src/crafty.js +++ b/src/crafty.js @@ -45,6 +45,7 @@ require('./controls/keycodes'); require('./sound/sound'); require('./debug/debug-layer'); +require('./debug/logging'); if(window) window.Crafty = Crafty; diff --git a/src/debug/logging.js b/src/debug/logging.js new file mode 100644 index 00000000..849348ee --- /dev/null +++ b/src/debug/logging.js @@ -0,0 +1,23 @@ +var Crafty = require('../core/core.js'); + + +/**@ + * #Crafty.log + * @category Debug + * + * @sign Crafty.log( arguments ) + * @param arguments - arguments which are passed to `console.log` + * + * This is a simple wrapper for `console.log`. You can disable logging messages by setting `Crafty.loggingEnabled` to false. + */ + +Crafty.extend({ + // Allow logging to be disabled + loggingEnabled: true, + // In some cases console.log doesn't exist, so provide a wrapper for it + log: function() { + if (Crafty.loggingEnabled && console && console.log) { + console.log.apply(this, arguments); + } + } +}); \ No newline at end of file diff --git a/tests/debug.js b/tests/debug.js index 28e7674a..e15469c9 100644 --- a/tests/debug.js +++ b/tests/debug.js @@ -1,6 +1,31 @@ (function() { var module = QUnit.module; + module("Crafty.log"); + + test("Logging works when console.log is enabled", function(){ + var original_log = console.log; + var logged_message = ""; + console.log = function(msg) { logged_message = msg; }; + var test_message = "test message"; + + Crafty.log(test_message); + equal(logged_message, test_message, "Crafty.log correctly passes through to console.log"); + + Crafty.loggingEnabled = false; + logged_message = ""; + Crafty.log(test_message); + equal(logged_message, "", "Crafty.log does nothing when logging is disabled."); + Crafty.loggingEnabled = true; + + console.log = undefined; + Crafty.log(test_message); + equal(logged_message, "", "Crafty.log does not crash when console.log is undefined."); + + + console.log = original_log; + }); + module("DebugLayer"); test("DebugCanvas", function() { From c42b9e89fb5e0fc5fa3e63ee5cb872412a7a8cd0 Mon Sep 17 00:00:00 2001 From: Tim Martin Date: Thu, 21 May 2015 15:58:47 -0400 Subject: [PATCH 02/15] Warn when using old syntax in Crafty.load Since we changed the method signature of Crafty.load, we should warn when people try to use the old syntax. --- src/core/loader.js | 4 ++++ tests/loader.js | 24 +++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/core/loader.js b/src/core/loader.js index 67e1c888..4a2a3e11 100644 --- a/src/core/loader.js +++ b/src/core/loader.js @@ -225,6 +225,10 @@ module.exports = { */ load: function (data, oncomplete, onprogress, onerror) { + if (Array.isArray(data)) { + Crafty.log("Calling Crafty.load with an array of assets no longer works; see the docs for more details."); + } + data = (typeof data === "string" ? JSON.parse(data) : data); var j = 0, diff --git a/tests/loader.js b/tests/loader.js index 4ad9b0ae..f4afc1ea 100644 --- a/tests/loader.js +++ b/tests/loader.js @@ -3,6 +3,16 @@ module('Loader'); + test("Warning on old syntax", function(){ + var original_log = Crafty.log; + var logged_message = ""; + Crafty.log = function(msg) { logged_message = msg; }; + Crafty.load(["falsey.png"], function(){ logged_message = "nope"; }); + ok(logged_message.indexOf("no longer works") >=0, "Correctly logged warning."); + Crafty.log = original_log; + }); + + asyncTest('assets loading', function() { expect(1); @@ -39,13 +49,13 @@ Crafty.load(assets_to_load, function() { Crafty.removeAssets(assets_to_load); - ok(checkItems() == 2 && wereItemsRemoved(), - 'all assets have been successfully loaded, and then successfully removed'); + ok(checkItems() == 2 && wereItemsRemoved(), 'all assets have been successfully loaded, and then successfully removed'); start(); - }, function(data) { - items.push(data); - }, function(error) { - console.log(error); - }); + }, function(data) { + items.push(data); + }, function(error) { + console.log(error); + } + ); }); })(); \ No newline at end of file From be6035110f9dcec09e702f39f2cdd1d57718fbd2 Mon Sep 17 00:00:00 2001 From: Tim Martin Date: Thu, 21 May 2015 19:15:16 -0400 Subject: [PATCH 03/15] Add a server for viewing the documentation This adds a new grunt task `grunt api-server` that will serve the api documentation directly from `api.json`. Use `grunt view-api` to build the docs and then view them in your default browser. This copies over some scripts from the craftyjs.com repo, but perhaps there's a better way to share them. --- Gruntfile.js | 20 ++ build/api-gen/clean-name.js | 5 + build/api-gen/doc-components.jsx | 395 +++++++++++++++++++++++++++++++ build/api-gen/dynamic-server.js | 57 +++++ build/api-gen/index-docs.js | 44 ++++ build/api-gen/server-side.jsx | 46 ++++ package.json | 13 +- 7 files changed, 577 insertions(+), 3 deletions(-) create mode 100644 build/api-gen/clean-name.js create mode 100644 build/api-gen/doc-components.jsx create mode 100644 build/api-gen/dynamic-server.js create mode 100644 build/api-gen/index-docs.js create mode 100644 build/api-gen/server-side.jsx diff --git a/Gruntfile.js b/Gruntfile.js index e497507e..63522796 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,5 +1,6 @@ require("coffee-script"); var fs = require('fs'); +var open = require("open"); module.exports = function (grunt) { var pkg = grunt.file.readJSON('package.json'); @@ -25,6 +26,16 @@ module.exports = function (grunt) { grunt.log.writeln("Wrote api data to " + outputFile); }; + var apiServer = require("./build/api-gen/dynamic-server.js"); + function runApiServer() { + var done = this.async(); + apiServer(grunt, "./build/api.json"); + setTimeout(function(){ + open("http://localhost:8080"); + }, 100); + } + + // Project configuration. grunt.initConfig({ @@ -104,6 +115,12 @@ module.exports = function (grunt) { keepalive: true } } + }, + + open: { + api : { + path: 'http://localhost:8080/', + }, } }); @@ -145,4 +162,7 @@ module.exports = function (grunt) { // Run only tests grunt.registerTask('validate', ['qunit']); + grunt.registerTask('api-server', "View dynamically generated docs", runApiServer); + grunt.registerTask('view-api', ['api', 'api-server'] ); + }; diff --git a/build/api-gen/clean-name.js b/build/api-gen/clean-name.js new file mode 100644 index 00000000..212b45b4 --- /dev/null +++ b/build/api-gen/clean-name.js @@ -0,0 +1,5 @@ +var re = /[\.-]/g + +module.exports = function cleanName(raw) { + return raw.replace(re, "-"); +} diff --git a/build/api-gen/doc-components.jsx b/build/api-gen/doc-components.jsx new file mode 100644 index 00000000..0e075c4c --- /dev/null +++ b/build/api-gen/doc-components.jsx @@ -0,0 +1,395 @@ +var marked = require("marked"); +var hljs = require("highlight.js"); +var cleanName = require("./clean-name"); +var githubRoot = "https://github.com/craftyjs/Crafty/blob/"; + + +// Assumes the marked.js renderer has been imported into a global variable `marked` +var MarkdownBlock = React.createClass({ + markedConfig: { + renderer: (function() { + var r = new marked.Renderer(); + r.code = function(code, language){ + return '
' + 
+                hljs.highlight("javascript", code).value +
+              '
'; + }; + return r; + })() + }, + + convert: function(raw) { + var raw = marked(raw, this.markedConfig) + return raw; + }, + + render: function() { + var raw = this.props.value; + var rawHtml = this.convert(raw); + var key = this.props.key; + return + } +}) + + +var ToC = React.createClass({ + render: function() { + var blocks = this.props.data; + var toc = this.props.index; + var primary = this.props.primary; + + // Generate categories + catArray = []; + for (var cat in toc.categories) { + if (cat != primary) { + catArray.push(toc.categories[cat]); + } + } + catArray.sort(nameSort); + var catElements = catArray.map( function(cat, index){return }); + return ( + + ) + } + +}) + +var DocLink = React.createClass({ + render: function() { + var target = this.props.target; + var linkText, href; + var parent = (this.props.parentPage) ? this.props.parentPage.main.name : undefined; + // If the link target starts with the name of the page, assume it is an internal link + // (This is about resolving links such as Crafty.viewport.centerOn) + // If the ref begins with # or ., also assume it is an internal link + if (parent && target.indexOf(parent + ".") === 0 ) { + linkText = target.replace(parent, ""); + href = "#" + cleanName(target); + } else if (target[0] === "#") { + linkText = target.substr(1); + href = cleanName(target); + } else if (target[0] === ".") { + linkText = target; + href = "#" + cleanName(target); + } else { + linkText = target; + href = cleanName(target) + ".html"; + } + return {linkText} + } +}) + +var Category = React.createClass({ + render: function() { + this.props.pages.sort(stringSort); + var pages = this.props.pages.map(function(page, index){return
  • }); + return ( +
  • + {this.props.catName} +
      + {pages} +
    +
  • + ) + } +}); + +var Node = React.createClass({ + render: function() { + var node = this.props.node; + var page = this.props.page; + switch(node.type) { + case "method": + return + case "param": + return + case "triggers": + return + case "raw": + return + case "return": + return + case "xref": + return + case "example": + return + default: + return

    Unsupported node type: {node.type}

    + } + } +}) + +function mapNodes(contents, page){ + return contents.map( function(node, index){ + return + }); +} + + +var SubSectionHeader = React.createClass({ + render: function() { + return

    {this.props.children || ""}

    + } +}) + +// SeeAlso +var SeeAlso = React.createClass({ + render: function() { + var page = this.props.page; + xrefs = this.props.xrefs.map(function(xref, index){ + // if () + return
  • + }); + return
    + See Also +
      + {xrefs} +
    + +
    + } +}) + +// Example + +var Example = React.createClass({ + render: function() { + var contents = this.props.contents; + var pieces = mapNodes(contents, this.props.page); + return (
    + Example + {pieces} +
    ) + + } +}) + +// Event & Trigger + +var Events = React.createClass({ + render: function() { + if (!this.props.triggers) + return
    + triggers = this.props.triggers.map(function(trigger, index){ + return + }) + if (this.props.noHeading) + var heading = ""; + else + var heading = Events; + return ( +
    + {heading} +
    + {triggers} +
    +
    + ); + } +}) + +var Trigger = React.createClass({ + render: function() { + var trigger = this.props.trigger; + var triggerData; + if (trigger.objName!=="Data" || trigger.objProp) + triggerData = [ {trigger.objName} {trigger.objProp ? "{ " + trigger.objProp + " }": ""}] + else + triggerData = ""; + return ( +
    +
    {trigger.event} {triggerData}
    +
    {trigger.description}
    +
    + ) + + } +}) + + +// Objects for displaying methods: Method is the container, Signature is required, Parameter and Returns are optional + +var Method = React.createClass({ + render: function() { + var contents = this.props.data.contents; + var pieces = mapNodes(contents, this.props.page); + return ( +
    + + {pieces} +
    + ) + } +}); + +var Parameter = React.createClass({ + render: function() { + return ( +
    +
    {this.props.paramName}
    +
    +
    + ) + } +}) + +var Signature = React.createClass({ + render: function() { + return ( + {this.props.sign} + ) + } +}) + +var Returns = React.createClass({ + render: function() { + return ( +
    +
    [Returns]
    +
    +
    + ) + } +}) + + +// Base doclet component + +var Doclet = React.createClass({ + render: function() { + var contents = this.props.data.contents; + var pieces = mapNodes(contents, this.props.page); + if (!this.props.top) { + var link = Back to top + var header =

    {this.props.data.name}

    + } else { + var link = ""; + var header = ""; + } + return ( +
    + {link} + {header} +
    + {pieces} +
    + ) + } +}); + +var SourceLink = React.createClass({ + render: function() { + var file = this.props.data.file; + var start = this.props.data.startLine; + var end = this.props.data.endLine; + var commit = this.props.data.commit; + var fileLocation = file +"#L" + start + "-" + end; + var target = githubRoot + commit + "/" + fileLocation; + return {fileLocation} + } + +}) + + + +function nameSort(a, b) { + return stringSort(a.name, b.name); +} + +function stringSort(a, b) { + if (typeof a === "string" && typeof b==="string") + return a.toUpperCase().localeCompare(b.toUpperCase()); + else + if (typeof b === "string") + return 1; + else + return -1; +} + + +// page, dict, +var DocPage = React.createClass({ + render: function() { + var page = this.props.page; + if (!page) { + return
    + } + var parts = page.parts; + parts.sort(nameSort); + var partlets = parts.map(function(part, index){return }); + var page_toc = parts.map( function(part, index){ return
  • }); + if (!page.main){ + return
    + } + if (parts.length > 0) { + var bottomParts = +
    + Methods and Properties +
      + {page_toc} +
    + {partlets} +
    + } else { + var bottomParts = ""; + } + return ( +
    +

    {page.main.name}

    + + {bottomParts} +
    + ) + } +}) + +var EventPage = React.createClass({ + render: function() { + var parts = this.props.data; + var events = []; + var index=0; + for (var p in parts) { + var part = parts[p]; + var contents = part.contents; + for (var b in contents){ + var block = contents[b]; + if (block.type == "triggers") { + events.push( +
    + {part.name} + +
    + + ); + } + } + } + var retval =
    + {events} +
    + return retval; + } +}) + + +var InternalLink = React.createClass({ + render: function() { + var cleanTarget = cleanName(this.props.target); + var linkText = this.props.target.replace(this.props.parent, ""); + return {linkText} + } +}); + + + +if (module) { + module.exports = { + "DocPage":DocPage, + "ToC": ToC, + "EventPage": EventPage + } +} diff --git a/build/api-gen/dynamic-server.js b/build/api-gen/dynamic-server.js new file mode 100644 index 00000000..ee956323 --- /dev/null +++ b/build/api-gen/dynamic-server.js @@ -0,0 +1,57 @@ +var http = require('http'), + director = require('director'); + + +var React = require('react'); +require('node-jsx').install({extension: '.jsx'}); +var StaticPage = require('./server-side'); // React component + +var createIndex = require("./index-docs"); +var cleanName = require("./clean-name"); + +function startServer(grunt, input){ + var api = grunt.file.readJSON(input), + index = createIndex(api), + pages = index.pages, + props = {data: api, index: index}; + + function createPage(selector, filename) { + filename = filename || cleanName(selector) + ".html"; + props.selector = selector; + var page = React.createElement(StaticPage, props); + var raw = React.renderToStaticMarkup(page); + if (pages[selector]) { + var title = pages[selector].main.name; + } else { + var title = selector || filename; + } + raw = "" + title + "" + + "
    " + raw + "
    "; + + return raw; + } + + var router = new director.http.Router(); + + var server = http.createServer(function (req, res) { + router.dispatch(req, res, function (err) { + if (err) { + // Return index when page is missing + this.res.writeHead(200, { 'Content-Type': 'text/html' }) + this.res.end( createPage("index") ); + } + }); + }); + + router.path(/(.+)\.html/, function () { + this.get(function (id) { + this.res.writeHead(200, { 'Content-Type': 'text/html' }) + this.res.end( createPage(id) ); + }); + }); + + console.log("Starting api server") + server.listen(8080); +}; + +module.exports = startServer; \ No newline at end of file diff --git a/build/api-gen/index-docs.js b/build/api-gen/index-docs.js new file mode 100644 index 00000000..6ac1f4b9 --- /dev/null +++ b/build/api-gen/index-docs.js @@ -0,0 +1,44 @@ +var cleanName = require("./clean-name"); + +function createIndex(blocks) { + var cats = {}; + var pages = {}; + var dictionary = {}; + function comp(c) { + var clean = cleanName(c); + return pages[clean] || (pages[clean] = {name:c, cleanName: clean, main: null, parts:[]}) + } + function cat(c) { + return cats[c] || (cats[c] = {name:c, pages:[]}) + } + for (var i = 0; i < blocks.length; i++) { + var block = blocks[i]; + // Add to any categories + if (block.categories) { + for (var j = 0; j < block.categories.length; j++) { + if (block.name) { + cat(block.categories[j]).pages.push(block.name) + } + comp(block.name).main = block; + } + } + // Add to any comps + if (block.comp && block.name) { + comp(block.comp).parts.push(block); + } + + if (block.name) { + dictionary[block.name] = block; + } + } + + // console.log("Cats", cats) + return { + pages: pages, + categories: cats, + dictionary: dictionary + } + +} + +module.exports = createIndex; \ No newline at end of file diff --git a/build/api-gen/server-side.jsx b/build/api-gen/server-side.jsx new file mode 100644 index 00000000..ff2e6e0b --- /dev/null +++ b/build/api-gen/server-side.jsx @@ -0,0 +1,46 @@ +React = require("react"); + +docComp = require("./doc-components"); +var ToC = docComp.ToC; +var DocPage = docComp.DocPage; +var EventPage = docComp.EventPage; + + +// We create a StaticPage component for generating the page +// Unlike in thre dynamic case, we assume we can just pass the necessary state directly +var StaticPage = React.createClass({ + render: function() { + var pages = this.props.index.pages; + var selector = this.props.selector; + var dict = this.props.index.dictionary; + + if (selector == "events") { + var content = + } else { + var page = pages[selector]; + if (page) { + var content = + } else { + var content =
    + } + } + + return
    +
    + +
    +
    + {content} +
    +
    + } + + +}) + +var StaticFactory = React.createFactory(StaticPage); + +module.exports = StaticPage; + + + diff --git a/package.json b/package.json index 0e82955b..791666f7 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ }, "devDependencies": { "coffee-script": "1.7.1", + "director": "^1.2.8", "git-rev-sync": "^1.0.0", "grunt": "^0.4.5", "grunt-banner": "^0.2.3", @@ -38,9 +39,15 @@ "grunt-contrib-uglify": "^0.5.1", "grunt-contrib-watch": "^0.6.1", "grunt-jsvalidate": "^0.2.2", - "marked": "^0.3.2" + "highlight.js": "^8.6.0", + "marked": "^0.3.3", + "node-jsx": "^0.13.3", + "open": "0.0.5", + "react": "^0.13.3" }, - "browserify": { - "transform": [ "brfs" ] + "browserify": { + "transform": [ + "brfs" + ] } } From 19b616638fe0d1bd842be5b60863f5813f3dd35b Mon Sep 17 00:00:00 2001 From: Airza Date: Wed, 29 Apr 2015 02:36:43 -0500 Subject: [PATCH 04/15] Better support for a grid that things can be placed on; three dimensional placement of tiles with intelligent Z calculation is now in place. Also methods for choosing tile based on pixel and pixels based on tile work better. --- src/isometric/diamond-iso.js | 173 ++++++++++++++++++++++------------- 1 file changed, 108 insertions(+), 65 deletions(-) diff --git a/src/isometric/diamond-iso.js b/src/isometric/diamond-iso.js index 114a77df..94bfd0e4 100644 --- a/src/isometric/diamond-iso.js +++ b/src/isometric/diamond-iso.js @@ -5,35 +5,40 @@ Crafty.extend({ /**@ * #Crafty.diamondIso * @category 2D - * Place entities in a 45deg diamond isometric fashion. It is similar to Crafty.isometric but has another grid locations + * Place entities in a 45deg diamond isometric fashion. It is similar to isometric but has another grid locations * In this mode, the x axis and y axis are aligned to the edges of tiles with x increasing being down and to the * right and y being down and to the left. */ diamondIso: { _tile: { width: 0, - height: 0, - r: 0 + height: 0 + }, + getTileDimensions: function(){ + return {w:this._tile.width,h:this._tile.height}; }, _map: { width: 0, - height: 0, - x: 0, - y: 0 + height: 0 }, - _origin: { x: 0, y: 0 }, + _tiles: [], + getTile: function(x,y,z){ + return this._tiles[x][y][z]; + }, /**@ * #Crafty.diamondIso.init * @comp Crafty.diamondIso * @sign public this Crafty.diamondIso.init(Number tileWidth,Number tileHeight,Number mapWidth,Number mapHeight) - * @param tileWidth - The size of base tile width in Pixel - * @param tileHeight - The size of base tile height in Pixel + * @param tileWidth - The size of base tile width's grid space in Pixel + * @param tileHeight - The size of base tile height grid space in Pixel * @param mapWidth - The width of whole map in Tiles * @param mapHeight - The height of whole map in Tiles + * @param x - the x coordinate of the TOP corner of the 0,0 tile + * @param y - the y coordinate of the TOP corner of the 0,0, tile * * Method used to initialize the size of the isometric placement. * Recommended to use a size alues in the power of `2` (128, 64 or 32). @@ -46,15 +51,22 @@ Crafty.extend({ * * @see Crafty.diamondIso.place */ - init: function (tw, th, mw, mh) { + init: function (tw, th, mw, mh, x, y) { this._tile.width = parseInt(tw, 10); this._tile.height = parseInt(th, 10) || parseInt(tw, 10) / 2; this._tile.r = this._tile.width / this._tile.height; this._map.width = parseInt(mw, 10); this._map.height = parseInt(mh, 10) || parseInt(mw, 10); - - this._origin.x = this._map.height * this._tile.width / 2; + for (var i=0; i0 && x0 && y Date: Thu, 28 May 2015 12:37:08 -0400 Subject: [PATCH 05/15] Fix some formatting issues in our doc blocks We had inconsistent conventions regarding @param and @returns tags - In some places, the description of the param/return value was continued across multiple lines - In many other places, the description of the method as a whole was place directly after such tags While the latter outnumbered the former, I think its useful to be able to have longer param/return descriptions split across multiple lines. So to allow this while not breaking the docs, this fixes all incidences of the second style. (This is probably also more readable when looking directly at the source.) --- src/controls/controls.js | 1 + src/core/core.js | 11 +++++++++++ src/core/loader.js | 4 ++++ src/core/scenes.js | 2 ++ src/debug/debug-layer.js | 2 ++ src/graphics/sprite.js | 1 + src/spatial/2d.js | 15 +++++++++++++++ src/spatial/collision.js | 3 +++ src/spatial/spatial-grid.js | 1 + 9 files changed, 40 insertions(+) diff --git a/src/controls/controls.js b/src/controls/controls.js index 6d52d77f..3072eb4e 100644 --- a/src/controls/controls.js +++ b/src/controls/controls.js @@ -68,6 +68,7 @@ Crafty.c("Draggable", { * * @sign public this .dragDirection(degree) * @param degree - A number, the degree (clockwise) of the move direction with respect to the x axis. + * * Specify the dragging direction. * * @example diff --git a/src/core/core.js b/src/core/core.js index 2ea0f87a..20a3af6f 100644 --- a/src/core/core.js +++ b/src/core/core.js @@ -201,6 +201,7 @@ Crafty.fn = Crafty.prototype = { * @param componentList - A string of components to add separated by a comma `,` * @sign public this .addComponent(String Component1[, .., String ComponentN]) * @param Component# - Component ID to add. + * * Adds a component to the selected entities or entity. * * Components are used to extend the functionality of entities. @@ -271,6 +272,7 @@ Crafty.fn = Crafty.prototype = { * @param ComponentList - A string of components to add or remove separated by a comma `,` * @sign public this .toggleComponent(String Component1[, .., String componentN]) * @param Component# - Component ID to add or remove. + * * Add or Remove Components from an entity. * * @example @@ -432,12 +434,14 @@ Crafty.fn = Crafty.prototype = { * @param value - Value to set the property to * @param silent - If you would like to supress events * @param recursive - If you would like merge recursively + * * Use this method to set any property of the entity. * * @sign public this .attr(Object map[, Boolean silent[, Boolean recursive]]) * @param map - Object where each key is the property to modify and the value as the property value * @param silent - If you would like to supress events * @param recursive - If you would like merge recursively + * * Use this method to set multiple properties of the entity. * * Setter options: @@ -447,6 +451,7 @@ Crafty.fn = Crafty.prototype = { * @sign public Any .attr(String property) * @param property - Property of the entity to modify * @returns Value - the value of the property + * * Use this method to get any property of the entity. You can also retrieve the property using `this.property`. * * @@ -625,6 +630,7 @@ Crafty.fn = Crafty.prototype = { * @sign public this .bind(String eventName, Function callback) * @param eventName - Name of the event to bind to * @param callback - Method to execute when the event is triggered + * * Attach the current entity (or entities) to listen for an event. * * Callback will be invoked when an event with the event name passed @@ -715,6 +721,7 @@ Crafty.fn = Crafty.prototype = { * @sign public this .unbind(String eventName[, Function callback]) * @param eventName - Name of the event to unbind * @param callback - Function to unbind + * * Removes binding with an event from current entity. * * Passing an event name will remove all events bound to @@ -740,6 +747,7 @@ Crafty.fn = Crafty.prototype = { * @sign public this .trigger(String eventName[, Object data]) * @param eventName - Event to trigger * @param data - Arbitrary data that will be passed into every callback as an argument + * * Trigger an event with arbitrary data. Will invoke all callbacks with * the context (value of `this`) of the current entity object. * @@ -771,6 +779,7 @@ Crafty.fn = Crafty.prototype = { * @comp Crafty Core * @sign public this .each(Function method) * @param method - Method to call on each iteration + * * Iterates over found entities, calling a function for every entity. * * The function will be called for every entity and will pass the index @@ -879,6 +888,7 @@ Crafty.fn = Crafty.prototype = { * @sign public this .setter(String property, Function callback) * @param property - Property to watch for modification * @param callback - Method to execute if the property is modified + * * Will watch a property waiting for modification and will then invoke the * given callback when attempting to modify. * @@ -1509,6 +1519,7 @@ Crafty.extend({ * @sign public void Crafty.c(String name, Object component) * @param name - Name of the component * @param component - Object with the component's properties and methods + * * Creates a component where the first argument is the ID and the second * is the object that will be inherited by entities. * diff --git a/src/core/loader.js b/src/core/loader.js index 4a2a3e11..c9f8ac07 100644 --- a/src/core/loader.js +++ b/src/core/loader.js @@ -68,10 +68,13 @@ module.exports = { * @sign public void Crafty.asset(String key, Object asset) * @param key - asset url. * @param asset - `Audio` or `Image` object. + * * Add new asset to assets object. * * @sign public void Crafty.asset(String key) * @param key - asset url. + * + * * Get asset from assets object. * * @example @@ -355,6 +358,7 @@ module.exports = { * * @sign public void Crafty.removeAssets(Object assets) * @param data - Object JSON formatted (or JSON string), with assets to remove (accepts sounds, images and sprites) + * * Removes assets (audio, images, sprites - and related sprite components) in order to allow the browser * to free memory. * diff --git a/src/core/scenes.js b/src/core/scenes.js index 20f4211e..944935ca 100644 --- a/src/core/scenes.js +++ b/src/core/scenes.js @@ -15,11 +15,13 @@ module.exports = { * @param sceneName - Name of the scene to add * @param init - Function to execute when scene is played * @param uninit - Function to execute before next scene is played, after entities with `2D` are destroyed + * * This is equivalent to calling `Crafty.defineScene`. * * @sign public void Crafty.scene(String sceneName[, Data]) * @param sceneName - Name of scene to play * @param Data - The init function of the scene will be called with this data as its parameter. Can be of any type other than a function. + * * This is equivalent to calling `Crafty.enterScene`. * * Method to create scenes on the stage. Pass an ID and function to register a scene. diff --git a/src/debug/debug-layer.js b/src/debug/debug-layer.js index bf1611ab..a079af9c 100644 --- a/src/debug/debug-layer.js +++ b/src/debug/debug-layer.js @@ -137,6 +137,7 @@ Crafty.c("DebugRectangle", { * @comp DebugRectangle * @sign public .debugRectangle(Object rect) * @param rect - an object with _x, _y, _w, and _h to draw + * * Sets the rectangle that this component draws to the debug canvas. * */ @@ -221,6 +222,7 @@ Crafty.c("DebugPolygon", { * @comp DebugPolygon * @sign public .debugPolygon(Polygon poly) * @param poly - a polygon to render + * * Sets the polygon that this component renders to the debug canvas. * */ diff --git a/src/graphics/sprite.js b/src/graphics/sprite.js index bf19fca4..9783da8d 100644 --- a/src/graphics/sprite.js +++ b/src/graphics/sprite.js @@ -25,6 +25,7 @@ Crafty.extend({ * @param paddingX - Horizontal space in between tiles. Defaults to 0. * @param paddingY - Vertical space in between tiles. Defaults to paddingX. * @param paddingAroundBorder - If padding should be applied around the border of the sprite sheet. If enabled the first tile starts at (paddingX,paddingY) instead of (0,0). Defaults to false. + * * Generates components based on positions in a sprite image to be applied to entities. * * Accepts a tile size, URL and map for the name of the sprite and its position. diff --git a/src/spatial/2d.js b/src/spatial/2d.js index e3fa4465..67ca0a20 100644 --- a/src/spatial/2d.js +++ b/src/spatial/2d.js @@ -464,6 +464,7 @@ Crafty.c("2D", { * @param h - Height of the rect * @sign public Boolean .intersect(Object rect) * @param rect - An object that must have the `_x, _y, _w, _h` values as properties + * * Determines if this entity intersects a rectangle. If the entity is rotated, its MBR is used for the test. */ intersect: function (x, y, w, h) { @@ -493,6 +494,7 @@ Crafty.c("2D", { * @param h - Height of the rect * @sign public Boolean .within(Object rect) * @param rect - An object that must have the `_x, _y, _w, _h` values as properties + * * Determines if this current entity is within another rectangle. */ within: function (x, y, w, h) { @@ -522,6 +524,7 @@ Crafty.c("2D", { * @param h - Height of the rect * @sign public Boolean .contains(Object rect) * @param rect - An object that must have the `_x, _y, _w, _h` values as properties. + * * Determines if the rectangle is within the current entity. If the entity is rotated, its MBR is used for the test. */ contains: function (x, y, w, h) { @@ -547,6 +550,7 @@ Crafty.c("2D", { * @sign public Object .pos(void) * * @param {{}=obj} pos + * * Returns the x, y, w, h properties as a new rect object if * no object is included. If object is inclued adds x, y, w, h * to included object. @@ -590,6 +594,7 @@ Crafty.c("2D", { * @sign public Boolean .isAt(Number x, Number y) * @param x - X position of the point * @param y - Y position of the point + * * Determines whether a point is contained by the entity. Unlike other methods, * an object can't be passed. The arguments require the x and y value. * @@ -612,6 +617,7 @@ Crafty.c("2D", { * @sign public this .move(String dir, Number by) * @param dir - Direction to move (n,s,e,w,ne,nw,se,sw) * @param by - Amount to move in the specified direction + * * Quick method to move the entity in a direction (n, s, e, w, ne, nw, se, sw) by an amount of pixels. */ move: function (dir, by) { @@ -631,6 +637,7 @@ Crafty.c("2D", { * @param y - Amount to move Y * @param w - Amount to widen * @param h - Amount to increase height + * * Shift or move the entity by an amount. Use negative values * for an opposite direction. */ @@ -648,6 +655,7 @@ Crafty.c("2D", { * @comp 2D * @sign public void ._cascade(e) * @param e - An object describing the motion + * * Move or rotate the entity's children according to a certain motion. * This method is part of a function bound to "Move": It is used * internally for ensuring that when a parent moves, the child also @@ -684,6 +692,7 @@ Crafty.c("2D", { * @comp 2D * @sign public this .attach(Entity obj[, .., Entity objN]) * @param obj - Child entity(s) to attach + * * Sets one or more entities to be children, with the current entity (`this`) * as the parent. When the parent moves or rotates, its children move or * rotate by the same amount. (But not vice-versa: If you move a child, it @@ -718,6 +727,7 @@ Crafty.c("2D", { * @comp 2D * @sign public this .detach([Entity obj]) * @param obj - The entity to detach. Left blank will remove all attached entities + * * Stop an entity from following the current entity. Passing no arguments will stop * every entity attached. */ @@ -746,11 +756,14 @@ Crafty.c("2D", { /**@ * #.origin * @comp 2D + * * @sign public this .origin(Number x, Number y) * @param x - Pixel value of origin offset on the X axis * @param y - Pixel value of origin offset on the Y axis + * * @sign public this .origin(String offset) * @param offset - Combination of center, top, bottom, middle, left and right + * * Set the origin point of an entity for it to rotate around. * * @example @@ -1573,6 +1586,7 @@ Crafty.c("Motion", { * * @sign public Vector2D .velocity() * @return The velocity Vector2D with the properties {x, y} that reflect the velocities in the direction of the entity. + * * Returns the current velocity. You can access/modify the properties in order to retrieve/change the velocity. * @example @@ -1599,6 +1613,7 @@ Crafty.c("Motion", { * * @sign public Vector2D .acceleration() * @return The acceleration Vector2D with the properties {x, y} that reflects the acceleration in the direction of the entity. + * * Returns the current acceleration. You can access/modify the properties in order to retrieve/change the acceleration. * * @example diff --git a/src/spatial/collision.js b/src/spatial/collision.js index 4b2a185b..7193201c 100644 --- a/src/spatial/collision.js +++ b/src/spatial/collision.js @@ -444,10 +444,13 @@ Crafty.c("Collision", { /**@ * #.ignoreHits * @comp Collision + * * @sign public this .ignoreHits() + * * @sign public this .ignoreHits(String componentList) * @param componentList - A comma seperated list of components to stop checking * for collisions with. + * * @sign public this .ignoreHits(String component1[, .., String componentN]) * @param component# - A component to stop checking for collisions with. * diff --git a/src/spatial/spatial-grid.js b/src/spatial/spatial-grid.js index 2cbc28e4..f02e032c 100644 --- a/src/spatial/spatial-grid.js +++ b/src/spatial/spatial-grid.js @@ -317,6 +317,7 @@ var Crafty = require('../core/core.js'); * @comp Crafty.HashMap * @sign public Object Crafty.HashMap.key(Object obj) * @param obj - an Object that has .mbr() or _x, _y, _w and _h. + * * Get the rectangular region (in terms of the grid, with grid size `cellsize`), where the object may fall in. This region is determined by the object's bounding box. * The `cellsize` is 64 by default. * From eef5620206eed841766d29e95d50d9d18a3e6904 Mon Sep 17 00:00:00 2001 From: Airza Date: Thu, 28 May 2015 16:23:19 -0500 Subject: [PATCH 06/15] A lot of changes to diamond-iso so the API is better and there's pathfinding --- src/core/tween.js | 2 +- src/isometric/diamond-iso.js | 287 ++++++++++++++++++++++++----------- 2 files changed, 201 insertions(+), 88 deletions(-) diff --git a/src/core/tween.js b/src/core/tween.js index 177c62b0..8f8c68e3 100644 --- a/src/core/tween.js +++ b/src/core/tween.js @@ -11,7 +11,7 @@ module.exports = { this.tweenGroup = {}; this.tweenStart = {}; this.tweens = []; - this.bind("EnterFrame", this._tweenTick); + this.uniqueBind("EnterFrame", this._tweenTick); }, diff --git a/src/isometric/diamond-iso.js b/src/isometric/diamond-iso.js index 94bfd0e4..badf5b69 100644 --- a/src/isometric/diamond-iso.js +++ b/src/isometric/diamond-iso.js @@ -14,9 +14,6 @@ Crafty.extend({ width: 0, height: 0 }, - getTileDimensions: function(){ - return {w:this._tile.width,h:this._tile.height}; - }, _map: { width: 0, height: 0 @@ -25,28 +22,30 @@ Crafty.extend({ x: 0, y: 0 }, - _tiles: [], - getTile: function(x,y,z){ - return this._tiles[x][y][z]; - }, + _grid: [], + //false if there is no collision in this square + _collisionMap: [], + _tileLocations: {}, + _tileZSpacing: 6, /**@ * #Crafty.diamondIso.init * @comp Crafty.diamondIso - * @sign public this Crafty.diamondIso.init(Number tileWidth,Number tileHeight,Number mapWidth,Number mapHeight) + * @sign public this Crafty.diamondIso.init(Number tileWidth,Number tileHeight,Number mapWidth,Number mapHeight, Number x, Number Y) * @param tileWidth - The size of base tile width's grid space in Pixel * @param tileHeight - The size of base tile height grid space in Pixel * @param mapWidth - The width of whole map in Tiles * @param mapHeight - The height of whole map in Tiles * @param x - the x coordinate of the TOP corner of the 0,0 tile - * @param y - the y coordinate of the TOP corner of the 0,0, tile + * @param y - the y coordinate of the TOP corner of the 0,0,tile * * Method used to initialize the size of the isometric placement. * Recommended to use a size alues in the power of `2` (128, 64 or 32). * This makes it easy to calculate positions and implement zooming. + * If TH isn't equal to TW*2, this won't work. * * @example * ~~~ - * var iso = Crafty.diamondIso.init(64,128,20,20); + * var iso = Crafty.diamondIso.init(64,128,20,20,0,0); * ~~~ * * @see Crafty.diamondIso.place @@ -59,93 +58,169 @@ Crafty.extend({ this._map.width = parseInt(mw, 10); this._map.height = parseInt(mh, 10) || parseInt(mw, 10); for (var i=0; i 0; + var hasTopLevelTile = this._grid[x][y][1].length >0; + if (hasTopLevelTile){ + topTileIsObstacle = this._grid[x][y][1][0].has("Obstacle"); + } else { + topTileIsObstacle = false; + } + var impassable = !hasGroundLevelTile || topTileIsObstacle; + this._collisionMap[x][y] = impassable; + }, + /**@ + * #Crafty.diamondIso.detachTile + * @comp Crafty.diamondIso + * @sign private this Crafty.diamondIso.detachTile(Entity obj) + * @param obj - the object to remove + * When passed an entity, removes that entity from the grid and returns its previous location. + * Does not delete the tile. + */ detachTile: function(obj){ - for (var _x=0; _x Date: Thu, 28 May 2015 12:20:26 -0400 Subject: [PATCH 07/15] Update doc generation scripts and viewer - better support for internal linking - @warning and @note tags - In the intial parse, assume that a block of text doesn't end until *two* linebreaks, rather than one, even if its the value of a tag. --- build/api-gen/doc-components.jsx | 106 +++++++++++++++++++++++++++++-- build/parseNodes.coffee | 8 +++ build/parseSourceDocs.coffee | 51 ++++++++++++--- 3 files changed, 150 insertions(+), 15 deletions(-) diff --git a/build/api-gen/doc-components.jsx b/build/api-gen/doc-components.jsx index 0e075c4c..5190a016 100644 --- a/build/api-gen/doc-components.jsx +++ b/build/api-gen/doc-components.jsx @@ -75,6 +75,21 @@ var DocLink = React.createClass({ } else if (target[0] === ".") { linkText = target; href = "#" + cleanName(target); + } else if (target.indexOf("#") > 0){ + var i = target.indexOf("#"); + var page = target.substring(0, i); + var anchor = target.substring(i+1); + + // Handle link text based on context + if (anchor.indexOf(page) >= 0) { + linkText = anchor; + } else if (anchor[0] === ".") { + linkText = page + anchor; + } else { + linkText = page + "\u2794" + anchor; + } + + href = cleanName(page) + ".html#" + cleanName(anchor); } else { linkText = target; href = cleanName(target) + ".html"; @@ -117,6 +132,10 @@ var Node = React.createClass({ return case "example": return + case "warning": + return + case "note": + return default: return

    Unsupported node type: {node.type}

    } @@ -168,6 +187,27 @@ var Example = React.createClass({ } }) +// Warning + +var Warning = React.createClass({ + render: function() { + return
    +
    Warning
    + +
    + } +}); + +// Note + +var Note = React.createClass({ + render: function() { + return
    + +
    + } +}); + // Event & Trigger var Events = React.createClass({ @@ -196,10 +236,24 @@ var Trigger = React.createClass({ render: function() { var trigger = this.props.trigger; var triggerData; - if (trigger.objName!=="Data" || trigger.objProp) - triggerData = [ {trigger.objName} {trigger.objProp ? "{ " + trigger.objProp + " }": ""}] - else + if (trigger.objName !== "Data" || trigger.objProp) { + if (trigger.objProp) { + var props = trigger.objProp; + if (props[0] !== "{") + props = "{" + props + "}"; + props = " = " + props; + } else { + var props = ""; + } + triggerData = + [ + {trigger.objName} + {props} + ] + + } else { triggerData = ""; + } return (
    {trigger.event} {triggerData}
    @@ -237,11 +291,51 @@ var Parameter = React.createClass({ } }) +// Seperator reg ex +var sepRe = /([()[\],]+)/ ; var Signature = React.createClass({ render: function() { + + var parts = this.props.sign.split(sepRe); + var contents = parts.map(function(content, index) { + if (sepRe.test(content)) { + return + } else if (content.length === 0) { + return ""; + } else { + return + } + }) return ( - {this.props.sign} - ) + + {contents} + + ); + } +}); + +var SignaturePhrase = React.createClass({ + render: function() { + var phrase = this.props.value.split(" "); + var last = phrase.length - 1; + var words = phrase.map( function(word, index) { + if (index === last) { + return {word} + } else { + return {word} + } + }); + return ( + + {words} + + ); + } +}) + +var SignatureSeperator = React.createClass({ + render: function() { + return {this.props.value} } }) @@ -271,7 +365,7 @@ var Doclet = React.createClass({ var header = ""; } return ( -
    +
    {link} {header}
    diff --git a/build/parseNodes.coffee b/build/parseNodes.coffee index 0c16505f..adf54b22 100644 --- a/build/parseNodes.coffee +++ b/build/parseNodes.coffee @@ -51,6 +51,14 @@ addNode = parent.contents.push(iterator.current()) iterator.next() + note: (parent, iterator)-> + parent.contents.push(iterator.current()) + iterator.next() + + warning: (parent, iterator)-> + parent.contents.push(iterator.current()) + iterator.next() + xref: (parent, iterator)-> base = iterator.current() while (iterator.next()?.type is "xref") diff --git a/build/parseSourceDocs.coffee b/build/parseSourceDocs.coffee index f4dc16c7..535cc68b 100644 --- a/build/parseSourceDocs.coffee +++ b/build/parseSourceDocs.coffee @@ -44,6 +44,7 @@ nextBlock = (buffer) -> # Process block, stopping when the doclet finishes, and returning an array of the results nodes = while buffer.isOpen() and buffer.current().indexOf('*/') == -1 n = nextNode( buffer ) + continue if not n? parseNode(n.tag, n.value) @@ -62,37 +63,69 @@ tagRe = /\@([^\s]*)\s?(.*)/ nameRe = /^\s*\#[^\#]/ emptyRe = /^\s*$/ +# Check whether a tag should be greedy or lazy when consuming subsequent lines +lazyTag = (tag) -> + switch tag + when "name", "comp", "category", "example", "sign" + true + else + false + # Assign each line to a node, throwing away empty lines that aren't directly after untagged lines # Guaranteed to leave the buffer in a state where buffer.current() hasn't yet been processed nextNode = (buffer)-> - clean = cleanLine( buffer.current() ) - + + # Find next non-empty line + while (buffer.isOpen() and buffer.current().indexOf('*/') == -1) and (clean = cleanLine( buffer.current() )).length == 0 + buffer.next() + return null if buffer.current().indexOf('*/') >= 0 or not buffer.isOpen() buffer.next() + + return null if clean.length == 0 + + # Determine what type of tag we're looking at tagged = clean?.match(tagRe) if tagged? - return { + node = { tag: tagged[1], value: tagged[2]?.trim() } else if nameRe.test(clean) - return { + node = { tag: "name", value: clean[clean.indexOf('#')+1..].trim() } else value = clean - while (buffer.current().indexOf('*/') == -1) and ((clean = cleanLine(buffer.current())) or true) and (not tagRe.test(clean) and not nameRe.test(clean)) - value = value + "\n" + clean - buffer.next() - break if not buffer.isOpen() - return {tag: "raw", value: value} + node = {tag: "raw", value: value} + return node if lazyTag(node.tag) + + # Now consume non-tagged lines until we hit an empty line or a tag + while ( + (buffer.isOpen() and buffer.current().indexOf('*/') == -1) and + ( (clean = cleanLine(buffer.current()) ).length > 0 or node.tag is "raw") and + (not tagRe.test(clean) and not nameRe.test(clean)) + ) + + if (node.tag is "raw") + node.value += "\n" + clean + else + node.value += " " + clean + + buffer.next() + break if not buffer.isOpen() + return node cleanLine = (line)-> # Trim the line, then remove the comment markers clean = line.trim().replace(/\/\*\*\@|\*\/|\*/, '') # Remove just the first space of the new line (additional spaces will be intentional formatting) clean = clean.substr(1) if clean[0] is ' ' + # Check if the remaining string contains any non-space characters, emptying if not + # Replace it with the empty string if not + if ( !(/\S/.test(clean)) ) + clean = ""; # Triple backtick is a bit more standard for markdown parsers clean = clean.replace("~~~", "```") return clean or "" From f51438f1bc262ac4d97948c9463136917c3a2b3c Mon Sep 17 00:00:00 2001 From: Tim Martin Date: Mon, 1 Jun 2015 12:55:27 -0400 Subject: [PATCH 08/15] Fix numerous small issues in our documentation I went through and fixed a large number of small issues in our documentation. This includes typos, formatting problems, and some places where docs were obviously wrong or missing. --- src/controls/device.js | 20 ++++++----- src/controls/inputs.js | 55 ++++++++++++++++-------------- src/core/core.js | 62 ++++++++++++++++++++++------------ src/core/extensions.js | 10 ++++-- src/core/loader.js | 4 +-- src/core/storage.js | 28 ++++++++++------ src/core/systems.js | 16 +++++---- src/core/time.js | 4 +++ src/graphics/canvas-layer.js | 2 +- src/graphics/dom-layer.js | 2 +- src/graphics/dom.js | 3 +- src/graphics/drawing.js | 9 +++-- src/graphics/html.js | 5 ++- src/graphics/image.js | 9 ++--- src/graphics/particles.js | 65 +++++++++++++++++++----------------- src/graphics/sprite.js | 8 ++++- src/graphics/text.js | 11 +++--- src/graphics/viewport.js | 2 +- src/graphics/webgl.js | 6 ++-- src/isometric/isometric.js | 39 ++++++++++++---------- src/spatial/2d.js | 22 +++++------- src/spatial/collision.js | 29 ++++++---------- src/spatial/math.js | 25 +++++++------- src/spatial/spatial-grid.js | 24 +++++++------ 24 files changed, 261 insertions(+), 199 deletions(-) diff --git a/src/controls/device.js b/src/controls/device.js index 7a026331..e8e6525d 100644 --- a/src/controls/device.js +++ b/src/controls/device.js @@ -5,6 +5,8 @@ Crafty.extend({ /**@ * #Crafty.device * @category Misc + * + * Methods relating to devices such as tablets or phones */ device: { _deviceOrientationCallback: false, @@ -87,10 +89,10 @@ Crafty.extend({ * Do something with normalized device orientation data: * ~~~ * { - * 'tiltLR' : 'gamma the angle in degrees the device is tilted left-to-right.', - * 'tiltFB' : 'beta the angle in degrees the device is tilted front-to-back', - * 'dir' : 'alpha the direction the device is facing according to the compass', - * 'motUD' : 'The angles values increase as you tilt the device to the right or towards you.' + * tiltLR : 'gamma -- the angle in degrees the device is tilted left-to-right.', + * tiltFB : 'beta -- the angle in degrees the device is tilted front-to-back', + * dir : 'alpha -- the direction the device is facing according to the compass', + * motUD : 'The angle's values increase as you tilt the device to the right or towards you.' * } * ~~~ * @@ -126,11 +128,11 @@ Crafty.extend({ * Do something with normalized device motion data: * ~~~ * { - * 'acceleration' : ' Grab the acceleration including gravity from the results', - * 'rawAcceleration' : 'Display the raw acceleration data', - * 'facingUp' : 'Z is the acceleration in the Z axis, and if the device is facing up or down', - * 'tiltLR' : 'Convert the value from acceleration to degrees. acceleration.x is the acceleration according to gravity, we'll assume we're on Earth and divide by 9.81 (earth gravity) to get a percentage value, and then multiply that by 90 to convert to degrees.', - * 'tiltFB' : 'Convert the value from acceleration to degrees.' + * acceleration : 'Grab the acceleration including gravity from the results', + * rawAcceleration : 'Display the raw acceleration data', + * facingUp : 'Z is the acceleration in the Z axis, and if the device is facing up or down', + * tiltLR : 'Convert the value from acceleration to degrees. acceleration.x is the acceleration according to gravity, we'll assume we're on Earth and divide by 9.81 (earth gravity) to get a percentage value, and then multiply that by 90 to convert to degrees.', + * tiltFB : 'Convert the value from acceleration to degrees.' * } * ~~~ * diff --git a/src/controls/inputs.js b/src/controls/inputs.js index 57d6eb05..07bfbaf0 100644 --- a/src/controls/inputs.js +++ b/src/controls/inputs.js @@ -7,13 +7,12 @@ Crafty.extend({ mousePos: {}, lastEvent: null, touchObjs: 0, - keydown: {}, selected: false, /**@ * #Crafty.keydown * @category Input - * Remembering what keys (referred by Unicode) are down. + * Check which keys (referred by Unicode values) are currently down. * * @example * ~~~ @@ -28,6 +27,8 @@ Crafty.extend({ * ~~~ * @see Keyboard, Crafty.keys */ + keydown: {}, + detectBlur: function (e) { var selected = ((e.clientX > Crafty.stage.x && e.clientX < Crafty.stage.x + Crafty.viewport.width) && (e.clientY > Crafty.stage.y && e.clientY < Crafty.stage.y + Crafty.viewport.height)); @@ -46,19 +47,21 @@ Crafty.extend({ /**@ * #Crafty.multitouch * @category Input - * @sign public this .multitouch([Boolean bool]) - * @param bool - Turns multitouch on and off (default is off - false) - * @sign public this .multitouch() + * @sign public this .multitouch(Boolean bool) + * @param bool - Turns multitouch on and off. The initial state is off (false). + * + * @sign public Boolean .multitouch() + * @returns Whether multitouch is currently enabled; + * * Enables/disables support for multitouch feature. * * If this is set to true, it is expected that your entities have the Touch component instead of Mouse component. * If false (default), then only entities with the Mouse component will respond to touch. + * * If no boolean is passed to the function call, it will just return whether multitouch is on or not. * - * Notice that the Touch component (and multitouch feature) is incompatible with the Draggable component or other - * mouse dependent stuff. + * @note The Touch component (and thus the multitouch feature) is currently incompatible with the Draggable component. * - * ~~~ * @example * ~~~ * Crafty.multitouch(true); @@ -604,7 +607,9 @@ Crafty.bind("CraftyStop", function () { /**@ * #Mouse * @category Input + * * Provides the entity with mouse related events + * * @trigger MouseOver - when the mouse enters - MouseEvent * @trigger MouseOut - when the mouse leaves - MouseEvent * @trigger MouseDown - when the mouse button is pressed on - MouseEvent @@ -613,21 +618,20 @@ Crafty.bind("CraftyStop", function () { * @trigger DoubleClick - when the user double clicks - MouseEvent * @trigger MouseMove - when the mouse is over and moves - MouseEvent * - * To be able to use the events on a entity, you have to remember to include the Mouse component, - * else the events will not get triggered. + * If you do not add this component, mouse events will not be triggered on an entity. * * You can read more about the MouseEvent, which is the parameter passed to the callback. * https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent * - * Crafty adds the mouseButton property to MouseEvents that match one of + * Crafty will add the mouseButton property to MouseEvents that match one of * * - Crafty.mouseButtons.LEFT * - Crafty.mouseButtons.RIGHT * - Crafty.mouseButtons.MIDDLE * - * If you're targeting mobiles, you must know that by default Crafty turns touch events into mouse events, - * making mouse dependent components work with touch. However, in case you need multitouch, you'll have - * to make use of the Touch component instead, thus losing compatibility with Mouse dependent stuff. + * @note If you're targeting mobile, you should know that by default Crafty turns touch events into mouse events, + * making mouse dependent components work with touch. However, if you need multitouch, you'll have + * to make use of the Touch component instead, which can break compatibility with things which directly interact with the Mouse component. * * @example * ~~~ @@ -665,17 +669,16 @@ Crafty.c("Mouse", { * @trigger TouchStart - when entity is touched - TouchPoint * @trigger TouchMove - when finger is moved over entity - TouchPoint * @trigger TouchCancel - when a touch event has been disrupted in some way - TouchPoint - * @trigger TouchEnd - when the finger is raised over the entity, or when finger leaves entity - won't send touch point + * @trigger TouchEnd - when the finger is raised over the entity, or when finger leaves entity. (Passes no data) - null * - * To be able to use multitouch, you must do Crafty.multitouch(true), and also you have to remember to include - * the Touch component in your entity, else the events will not get triggered. - * - * If you don't need multitouch, you can use the Mouse component instead. + * To be able to use multitouch, you must enable it with `Crafty.multitouch(true)`. + * + * If you don't need multitouch, you can probably use the Mouse component instead, since by default Crafty will trigger mouse events for touch input. * - * You can read more about the TouchEvent. See TouchEvent.touches and TouchEvent.changedTouches. - * https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent - * TouchPoint is the parameter passed to the event callback in the related touch. - * http://www.w3.org/TR/touch-events/#dfn-active-touch-point + * You can read more about the TouchEvent. + * - [TouchEvent.touches and TouchEvent.changedTouches](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) + * - [TouchPoint](http://www.w3.org/TR/touch-events/#dfn-active-touch-point) is the parameter passed to the event callback in the related touch. + * * * @example * ~~~ @@ -864,14 +867,16 @@ Crafty.c("MouseDrag", { /**@ * #Keyboard * @category Input - * Give entities keyboard events (`keydown` and `keyup`). + * + * Give entities keyboard events (`Keydown` and `Keyup`). * * In particular, changes to the key state are broadcasted by `KeyboardEvent`s; interested entities can bind to these events. + * * The current state (pressed/released) of a key can also be queried using the `.isDown` method. + * * All available key codes are described in `Crafty.keys`. * * @see KeyboardEvent - * @see Keyboard.isDown * @see Crafty.keys */ Crafty.c("Keyboard", { diff --git a/src/core/core.js b/src/core/core.js index 20a3af6f..e81f37db 100644 --- a/src/core/core.js +++ b/src/core/core.js @@ -3,12 +3,25 @@ var version = require('./version'); /**@ * #Crafty * @category Core + * + * `Crafty` is both an object, and a function for selecting entities. + * Its many methods and properties are discussed individually. + * Below is the documentation for use as a selector. + * + * @sign public EntitySelection Crafty( String selector) + * @param selector - A string representing which entities to select + * + * @sign public Entity Crafty( Number selector ) + * @param selector - An entity's id + * * Select a set of or single entities by components or an entity's ID. * * Crafty uses syntax similar to jQuery by having a selector engine to select entities by their components. * * If there is more than one match, the return value is an Array-like object listing the ID numbers of each matching entity. If there is exactly one match, the entity itself is returned. If you're not sure how many matches to expect, check the number of matches via Crafty(...).length. Alternatively, use Crafty(...).each(...), which works in all cases. * + * @note You can treat an entity as if it was a selection of length 1 -- it implements all the same methods. + * * @example * ~~~ * Crafty("MyComponent") @@ -33,8 +46,8 @@ var version = require('./version'); * * The event related methods such as `bind` and `trigger` will work on selections of entities. * - * @see .get - * @see .each + * @see Crafty Core#.get + * @see Crafty Core#.each */ var Crafty = function (selector) { @@ -69,7 +82,7 @@ initState(); * @trigger RemoveComponent - when a component is removed from the entity - String - Component * @trigger Remove - when the entity is removed by calling .destroy() * - * Set of methods added to every single entity. + * A set of methods added to every single entity. */ Crafty.fn = Crafty.prototype = { @@ -393,7 +406,7 @@ Crafty.fn = Crafty.prototype = { * #.getId * @comp Crafty Core * @sign public Number .getId(void) - * Returns the ID of this entity. + * @returns the ID of this entity. * * For better performance, simply use the this[0] property. * @@ -413,7 +426,8 @@ Crafty.fn = Crafty.prototype = { * #.has * @comp Crafty Core * @sign public Boolean .has(String component) - * Returns `true` or `false` depending on if the + * @param component - The name of the component to check + * @returns `true` or `false` depending on if the * entity has the given component. * * For better performance, simply use the `.__c` object @@ -445,8 +459,8 @@ Crafty.fn = Crafty.prototype = { * Use this method to set multiple properties of the entity. * * Setter options: - * `silent`: If you want to prevent it from firing events. - * `recursive`: If you pass in an object you could overwrite sibling keys, this recursively merges instead of just merging it. This is `false` by default, unless you are using dot notation `name.first`. + * - `silent`: If you want to prevent it from firing events. + * - `recursive`: If you pass in an object you could overwrite sibling keys, this recursively merges instead of just merging it. This is `false` by default, unless you are using dot notation `name.first`. * * @sign public Any .attr(String property) * @param property - Property of the entity to modify @@ -925,7 +939,6 @@ Crafty.fn = Crafty.prototype = { * ent.customData = "2" // set customData to 2 * console.log(ent.customData) // prints 2 * ~~~ - * @see Crafty.defineField */ defineField: function (prop, getCallback, setCallback) { Crafty.defineField(this, prop, getCallback, setCallback); @@ -961,7 +974,10 @@ Crafty.fn.init.prototype = Crafty.fn; /**@ * #Crafty.extend * @category Core - * Used to extend the Crafty namespace. + * @sign public this Crafty.extend(Object obj) + * @param obj - An object whose fields will be copied onto Crafty. This is a shallow copy. + * + * Used to extend the Crafty namespace by passing in an object of properties and methods to add. * */ Crafty.extend = Crafty.fn.extend = function (obj) { @@ -1216,9 +1232,8 @@ Crafty.extend({ /**@ * #Crafty.isPaused * @category Core - * @sign public this Crafty.isPaused() - * - * Check whether the game is already paused or not. + * @sign public Boolean Crafty.isPaused() + * @returns Whether the game is currently paused. * * @example * ~~~ @@ -1433,6 +1448,7 @@ Crafty.extend({ * @sign public void Crafty.timer.FPS(Number value) * @param value - the target rate * @trigger FPSChange - Triggered when the target FPS is changed by user - Number - new target FPS + * * Sets the target frames per second. This is not an actual frame rate. * The default rate is 50. */ @@ -1566,9 +1582,13 @@ Crafty.extend({ * ~~~ * * - * WARNING: - * - * in the examples above the field _message is local to the entity. That is, if you create many entities with the Annoying component they can all have different values for _message. That is because it is a simple value, and simple values are copied by value. If however the field had been an object or array, the value would have been shared by all entities with the component because complex types are copied by reference in javascript. This is probably not what you want and the following example demonstrates how to work around it: + * @warning In the examples above the field _message is local to the entity. + * That is, if you create many entities with the Annoying component, they can all have different values for _message. + * That is because it is a simple value, and simple values are copied by value. + * If however the field had been an object or array, + * the value would have been shared by all entities with the component, + * because complex types are copied by reference in javascript. + * This is probably not what you want and the following example demonstrates how to work around it. * * ~~~ * Crafty.c("MyComponent", { @@ -1616,7 +1636,7 @@ Crafty.extend({ /**@ * #Crafty.bind * @category Core, Events - * @sign public Number bind(String eventName, Function callback) + * @sign public Function bind(String eventName, Function callback) * @param eventName - Name of the event to bind to * @param callback - Method to execute upon event triggered * @returns callback function which can be used for unbind @@ -1637,7 +1657,7 @@ Crafty.extend({ /**@ * #Crafty.uniqueBind * @category Core, Events - * @sign public Number uniqueBind(String eventName, Function callback) + * @sign public Function uniqueBind(String eventName, Function callback) * @param eventName - Name of the event to bind to * @param callback - Method to execute upon event triggered * @returns callback function which can be used for unbind @@ -1654,7 +1674,7 @@ Crafty.extend({ /**@ * #Crafty.one * @category Core, Events - * @sign public Number one(String eventName, Function callback) + * @sign public Function one(String eventName, Function callback) * @param eventName - Name of the event to bind to * @param callback - Method to execute upon event triggered * @returns callback function which can be used for unbind @@ -1707,7 +1727,7 @@ Crafty.extend({ * #Crafty.frame * @category Core * @sign public Number Crafty.frame(void) - * Returns the current frame number + * @returns the current frame number */ frame: function () { return frame; @@ -1815,7 +1835,7 @@ Crafty.extend({ * ent.customData = "2" // set customData to 2 * console.log(ent.customData) // prints 2 * ~~~ - * @see .defineField + * @see Crafty Core#.defineField */ defineField: function(obj, prop, getCallback, setCallback) { Object.defineProperty(obj, prop, { @@ -1848,7 +1868,7 @@ function UID() { * @sign public Object .clone(Object obj) * @param obj - an object * - * Deep copy (a.k.a clone) of an object. + * Deep copy (a.k.a clone) of an object */ function clone(obj) { diff --git a/src/core/extensions.js b/src/core/extensions.js index eb914b8e..f7e788c1 100644 --- a/src/core/extensions.js +++ b/src/core/extensions.js @@ -150,9 +150,13 @@ module.exports = { * * Callbacks are passed with event data. * + * @note This is related to DOM events only, not Crafty's own event system. + * Of course, you can trigger Crafty events in the callback function! + * * @example - * Will add a stage-wide MouseDown event listener to the player. Will log which button was pressed - * & the (x,y) coordinates in viewport/world/game space. + * Normally you'd use Crafty's built-in mouse component, but for the sake of an example let's pretend that doesn't exist. + * The following code will add a stage-wide MouseDown event listener to the player, and log both which button was pressed + * and the (x,y) coordinates in viewport/world/game space. * ~~~ * var player = Crafty.e("2D"); * player.onMouseDown = function(e) { @@ -226,7 +230,7 @@ module.exports = { /**@ * #Crafty.background * @category Graphics, Stage - * @sign public void Crafty.background(String value) + * @sign public void Crafty.background(String style) * @param style - Modify the background with a color or image * * This method is a shortcut for adding a background diff --git a/src/core/loader.js b/src/core/loader.js index c9f8ac07..69161a7a 100644 --- a/src/core/loader.js +++ b/src/core/loader.js @@ -13,7 +13,7 @@ module.exports = { * ~~~ * var isLoaded = !!Crafty.assets["images/sprite.png"]; * ~~~ - * @see Crafty.loader + * @see Crafty.load */ assets: {}, __paths: { audio: "", images: "" }, @@ -142,7 +142,7 @@ module.exports = { */ image_whitelist: ["jpg", "jpeg", "gif", "png", "svg"], /**@ - * #Crafty.loader + * #Crafty.load * @category Assets * @sign public void Crafty.load(Object assets, Function onLoad[, Function onProgress[, Function onError]]) * @param assets - Object JSON formatted (or JSON string), with assets to load (accepts sounds, images and sprites) diff --git a/src/core/storage.js b/src/core/storage.js index 7ae2ece6..e3f0519a 100644 --- a/src/core/storage.js +++ b/src/core/storage.js @@ -1,24 +1,32 @@ /**@ * #Storage * @category Utilities + * + * * Very simple way to get and set values, which will persist when the browser is closed also. Storage wraps around HTML5 Web Storage, which is well-supported across browsers and platforms, but limited to 5MB total storage per domain. */ /**@ - * #.storage + * #Crafty.storage * @comp Storage - * @sign .storage(String key) - * @param key - a key you would like to get from the storage. It will return null if the key does not exists. - * @sign .storage(String key, String value) + * @sign Crafty.storage(String key) + * @param key - a key you would like to get from the storage. + * @returns The stored value, or `null` if none saved under that key exists + * + * @sign Crafty.storage(String key, String value) * @param key - the key you would like to save the data under. * @param value - the value you would like to save. - * @sign .storage(String key, [Object value, Array value, Boolean value]) + * + * @sign Crafty.storage(String key, [Object value, Array value, Boolean value]) * @param key - the key you would like to save the data under. * @param value - the value you would like to save, can be an Object or an Array. * - * Storage function is very simple and can be used to either get or set values. - * You can store both booleans, strings, objects and arrays. + * `Crafty.storage` is used synchronously to either get or set values. + * + * You can store booleans, strings, objects and arrays. * - * Please note: You should not store data, while the game is playing, as it can cause the game to slow down. You should load data when you start the game, or when the user for an example click a "Save gameprocess" button. + * @note Because the underlying method is synchronous, it can cause slowdowns if used frequently during gameplay. + * You should aim to load or save data at reasonable times such as on level load, + * or in response to specific user actions. * * @example * Get an already stored value @@ -70,9 +78,9 @@ var storage = function(key, value) { }; /**@ - * #.storage.remove + * #Crafty.storage.remove * @comp Storage - * @sign .storage.remove(String key) + * @sign Crafty.storage.remove(String key) * @param key - a key where you will like to delete the value of. * * Generally you do not need to remove values from localStorage, but if you do diff --git a/src/core/systems.js b/src/core/systems.js index 39d33727..bdbc9cfb 100644 --- a/src/core/systems.js +++ b/src/core/systems.js @@ -8,12 +8,10 @@ Crafty._systems = {}; * #Crafty.s * @category Core * - * Objects which handle entities might want to subscribe to the event system without being entities themselves. - * When you declare a system with a template object, all the methods and properties of that template are copied to a new object. - * This new system will automatically have the following event related methods, which function like those of components: `.bind()`, `unbind()`, `trigger()`, `one()`, `uniqueBind()`, `destroy()`. - * Much like components, you can also provide `init()` and `remove()` methods, as well as an `events` parameter for automatically binding to events. + * Registers a system. * - * *Note*: The `init()` method is for setting up the internal state of the system -- if you create entities in it that then reference the system, that'll create an infinite loop. + * @trigger SystemLoaded - When the system has initialized itself - obj - system object + * @trigger SystemDestroyed - Right before the system is destroyed - obj - system object * * @sign void Crafty.s(String name, Obj template[, Boolean lazy]) * Register a system @@ -26,8 +24,12 @@ Crafty._systems = {}; * @param name - The system to return * @returns The referenced system. If the system has not been initialized, it will be before it is returned. * - * @trigger SystemLoaded - When the system has initialized itself - obj - system object - * @trigger SystemDestroyed - Right before the system is destroyed - obj - system object + * Objects which handle entities might want to subscribe to the event system without being entities themselves. + * When you declare a system with a template object, all the methods and properties of that template are copied to a new object. + * This new system will automatically have the following event related methods, which function like those of components: `.bind()`, `unbind()`, `trigger()`, `one()`, `uniqueBind()`, `destroy()`. + * Much like components, you can also provide `init()` and `remove()` methods, as well as an `events` parameter for automatically binding to events. + * + * *Note*: The `init()` method is for setting up the internal state of the system -- if you create entities in it that then reference the system, that'll create an infinite loop. */ Crafty.s = function(name, obj, lazy) { if (obj) { diff --git a/src/core/time.js b/src/core/time.js index 0759bf73..17481813 100644 --- a/src/core/time.js +++ b/src/core/time.js @@ -1,6 +1,10 @@ /**@ * #Delay * @category Utilities + * + * A component for triggering functions after a given amount of time. + * + * This syncs with Crafty's internal clock, and so should generally be preferred to using methods such as `setTimeout`. */ module.exports = { init: function () { diff --git a/src/graphics/canvas-layer.js b/src/graphics/canvas-layer.js index 13e3c8f7..77b26016 100644 --- a/src/graphics/canvas-layer.js +++ b/src/graphics/canvas-layer.js @@ -137,7 +137,7 @@ Crafty.extend({ * do the naive method redrawing `Crafty.canvasLayer.drawAll` instead * - Otherwise, clear the dirty regions, and redraw entities overlapping the dirty regions. * - * @see Canvas.draw + * @see Canvas#.draw */ _drawDirty: function () { diff --git a/src/graphics/dom-layer.js b/src/graphics/dom-layer.js index de4d44ea..88d7b143 100644 --- a/src/graphics/dom-layer.js +++ b/src/graphics/dom-layer.js @@ -74,7 +74,7 @@ Crafty.extend({ * * When "RenderScene" is triggered, draws all DOM entities that have been flagged * - * @see DOM.draw + * @see DOM#.draw */ _render: function () { var layer = Crafty.domLayer; diff --git a/src/graphics/dom.js b/src/graphics/dom.js index d73f97e3..40122926 100644 --- a/src/graphics/dom.js +++ b/src/graphics/dom.js @@ -4,7 +4,8 @@ var Crafty = require('../core/core.js'), /**@ * #DOM * @category Graphics - * Draws entities as DOM nodes, specifically `
    `s. + * + * A component which renders entities as DOM nodes, specifically `
    `s. */ Crafty.c("DOM", { /**@ diff --git a/src/graphics/drawing.js b/src/graphics/drawing.js index 54204662..5131dd57 100644 --- a/src/graphics/drawing.js +++ b/src/graphics/drawing.js @@ -5,8 +5,10 @@ Crafty.extend({ * #Crafty.pixelart * @category Graphics * @sign public void Crafty.pixelart(Boolean enabled) + * @param enabled - whether to preserve sharp edges when rendering images + * + * Sets the image smoothing for drawing images (for all layer types). * - * Sets the image smoothing for drawing images (for both DOM and Canvas). * Setting this to true disables smoothing for images, which is the preferred * way for drawing pixel art. Defaults to false. * @@ -17,10 +19,11 @@ Crafty.extend({ * be aware that canvas entities won't be drawn in the new style until something else invalidates them. * (You can manually invalidate all canvas entities with `Crafty("Canvas").trigger("Invalidate");`) * - * Note that Firefox_26 currently has a [bug](https://bugzilla.mozilla.org/show_bug.cgi?id=696630) + * @note Firefox_26 currently has a [bug](https://bugzilla.mozilla.org/show_bug.cgi?id=696630) * which prevents disabling image smoothing for Canvas entities that use the Image component. Use the Sprite * component instead. - * Note that Webkit (Chrome & Safari) currently has a bug [link1](http://code.google.com/p/chromium/issues/detail?id=134040) + * + * @note Webkit (Chrome & Safari) currently has a bug [link1](http://code.google.com/p/chromium/issues/detail?id=134040) * [link2](http://code.google.com/p/chromium/issues/detail?id=106662) that prevents disabling image smoothing * for DOM entities. * diff --git a/src/graphics/html.js b/src/graphics/html.js index d3f65f15..1ea23d91 100644 --- a/src/graphics/html.js +++ b/src/graphics/html.js @@ -4,7 +4,10 @@ var Crafty = require('../core/core.js'); /**@ * #HTML * @category Graphics - * Component allow for insertion of arbitrary HTML into an entity + * + * A component which allows for the insertion of arbitrary HTML into a DOM entity. + * + * Adding this to an entity will automatically add the `DOM` component. */ Crafty.c("HTML", { inner: '', diff --git a/src/graphics/image.js b/src/graphics/image.js index f68b9ca0..05e0fa12 100644 --- a/src/graphics/image.js +++ b/src/graphics/image.js @@ -40,17 +40,18 @@ Crafty.c("Image", { * @trigger Invalidate - when the image is loaded * @sign public this .image(String url[, String repeat]) * @param url - URL of the image - * @param repeat - If the image should be repeated to fill the entity. + * @param repeat - If the image should be repeated to fill the entity. This follows CSS syntax: (`"no-repeat", "repeat", "repeat-x", "repeat-y"`), but defaults to `no-repeat`. * - * Draw specified image. Repeat follows CSS syntax (`"no-repeat", "repeat", "repeat-x", "repeat-y"`); + * Draw the specified image. * - * *Note: Default repeat is `no-repeat` which is different to standard DOM (which is `repeat`)* + * @note The default value of repeat is `no-repeat`, which is different than the standard CSS default * * If the width and height are `0` and repeat is set to `no-repeat` the width and * height will automatically assume that of the image. This is an * easy way to create an image without needing sprites. * - * If set to `no-repeat` and given dimensions larger than that of the image, the exact appearance will depend on what renderer (WebGL, DOM, or Canvas) is used. + * If set to `no-repeat` and given dimensions larger than that of the image, + * the exact appearance will depend on what renderer (WebGL, DOM, or Canvas) is used. * * @example * Will default to no-repeat. Entity width and height will be set to the images width and height diff --git a/src/graphics/particles.js b/src/graphics/particles.js index 9a9107de..124b5466 100644 --- a/src/graphics/particles.js +++ b/src/graphics/particles.js @@ -5,9 +5,12 @@ var Crafty = require('../core/core.js'), * #Particles * @category Graphics * @trigger ParticleEnd - when the particle animation has finished + * * Based on Parcycle by Mr. Speaker, licensed under the MIT, Ported by Leo Koppelkamm - * **This is canvas only & won't do anything if the browser doesn't support it!** - * To see how this works take a look in https://github.com/craftyjs/Crafty/blob/master/src/particles.js + * + * @note This requires the canvas element, and won't do anything if the browser doesn't support it! + * + * For implementation details, check out the source code. */ Crafty.c("Particles", { init: function () { @@ -25,35 +28,35 @@ Crafty.c("Particles", { * @example * ~~~ * var options = { - * maxParticles: 150, - * size: 18, - * sizeRandom: 4, - * speed: 1, - * speedRandom: 1.2, - * // Lifespan in frames - * lifeSpan: 29, - * lifeSpanRandom: 7, - * // Angle is calculated clockwise: 12pm is 0deg, 3pm is 90deg etc. - * angle: 65, - * angleRandom: 34, - * startColour: [255, 131, 0, 1], - * startColourRandom: [48, 50, 45, 0], - * endColour: [245, 35, 0, 0], - * endColourRandom: [60, 60, 60, 0], - * // Only applies when fastMode is off, specifies how sharp the gradients are drawn - * sharpness: 20, - * sharpnessRandom: 10, - * // Random spread from origin - * spread: 10, - * // How many frames should this last - * duration: -1, - * // Will draw squares instead of circle gradients - * fastMode: false, - * gravity: { x: 0, y: 0.1 }, - * // sensible values are 0-3 - * jitter: 0, - * // Offset for the origin of the particles - * originOffset: {x: 0, y: 0} + * maxParticles: 150, + * size: 18, + * sizeRandom: 4, + * speed: 1, + * speedRandom: 1.2, + * // Lifespan in frames + * lifeSpan: 29, + * lifeSpanRandom: 7, + * // Angle is calculated clockwise: 12pm is 0deg, 3pm is 90deg etc. + * angle: 65, + * angleRandom: 34, + * startColour: [255, 131, 0, 1], + * startColourRandom: [48, 50, 45, 0], + * endColour: [245, 35, 0, 0], + * endColourRandom: [60, 60, 60, 0], + * // Only applies when fastMode is off, specifies how sharp the gradients are drawn + * sharpness: 20, + * sharpnessRandom: 10, + * // Random spread from origin + * spread: 10, + * // How many frames should this last + * duration: -1, + * // Will draw squares instead of circle gradients + * fastMode: false, + * gravity: { x: 0, y: 0.1 }, + * // sensible values are 0-3 + * jitter: 0, + * // Offset for the origin of the particles + * originOffset: {x: 0, y: 0} * }; * * Crafty.e("2D,Canvas,Particles").particles(options); diff --git a/src/graphics/sprite.js b/src/graphics/sprite.js index 9783da8d..99717430 100644 --- a/src/graphics/sprite.js +++ b/src/graphics/sprite.js @@ -161,7 +161,13 @@ Crafty.extend({ * #Sprite * @category Graphics * @trigger Invalidate - when the sprites change - * Component for using tiles in a sprite map. + * + * A component for using tiles in a sprite map. + * + * This is automatically added to entities which use the components created by `Crafty.sprite` or `Crafty.load`. + * Since these are also used to define tile size, you'll rarely need to use this components methods directly. + * + * @see Crafty.sprite, Crafty.load */ Crafty.c("Sprite", { __image: '', diff --git a/src/graphics/text.js b/src/graphics/text.js index de35dc70..20e23d68 100644 --- a/src/graphics/text.js +++ b/src/graphics/text.js @@ -10,19 +10,19 @@ var Crafty = require('../core/core.js'); * * By default, text will have the style "10px sans-serif". * - * Note 1: An entity with the text component is just text! If you want to write text + * @note An entity with the text component is just text! If you want to write text * inside an image, you need one entity for the text and another entity for the image. * More tips for writing text inside an image: (1) Use the z-index (from 2D component) * to ensure that the text is on top of the image, not the other way around; (2) * use .attach() (from 2D component) to glue the text to the image so they move and * rotate together. * - * Note 2: For DOM (but not canvas) text entities, various font settings (like + * @note For DOM (but not canvas) text entities, various font settings (like * text-decoration and text-align) can be set using `.css()` (see DOM component). But * you cannot use `.css()` to set the properties which are controlled by `.textFont()` * or `.textColor()` -- the settings will be ignored. * - * Note 3: If you use canvas text with glyphs that are taller than standard letters, portions of the glyphs might be cut off. + * @note If you use canvas text with glyphs that are taller than standard letters, portions of the glyphs might be cut off. */ Crafty.c("Text", { _text: "", @@ -99,9 +99,12 @@ Crafty.c("Text", { * #.text * @comp Text * @sign public this .text(String text) - * @sign public this .text(Function textgenerator) * @param text - String of text that will be inserted into the DOM or Canvas element. * + * @sign public this .text(Function textGenerator) + * @param textGenerator - A function that returns a string. + * It will be immediately invoked in the context of the entity, with the result used as the text to display. + * * This method will update the text inside the entity. * * If you need to reference attributes on the entity itself you can pass a function instead of a string. diff --git a/src/graphics/viewport.js b/src/graphics/viewport.js index c25bb6ad..8d72c43e 100644 --- a/src/graphics/viewport.js +++ b/src/graphics/viewport.js @@ -515,7 +515,7 @@ Crafty.extend({ /**@ * #Crafty.domLayer._div - * @comp Crafty.stage, Crafty.domLayer + * @comp Crafty.domLayer * `Crafty.domLayer._div` is a div inside the `#cr-stage` div that holds all DOM entities. * If you use canvas, a `canvas` element is created at the same level in the dom * as the the `Crafty.domLayer._div` div. So the hierarchy in the DOM is diff --git a/src/graphics/webgl.js b/src/graphics/webgl.js index 5288fe37..42bae28d 100644 --- a/src/graphics/webgl.js +++ b/src/graphics/webgl.js @@ -182,7 +182,7 @@ RenderProgramWrapper.prototype = { * * Crafty.webgl.init() will be automatically called if it is not called already to initialize the canvas element. * - * **Note:** For better performance, minimize the number of spritesheets used, and try to arrange it so that entities with different spritesheets are on different z-levels. + * @note For better performance, minimize the number of spritesheets used, and try to arrange it so that entities with different spritesheets are on different z-levels. * * Create a webgl entity like this * ~~~ @@ -337,7 +337,7 @@ Crafty.c("WebGL", { * #Crafty.webgl * @category Graphics * - * Collection of methods to handle webgl contexts. + * A collection of methods to handle webgl contexts. */ Crafty.extend({ @@ -423,7 +423,7 @@ Crafty.extend({ * @sign public void Crafty.webgl.init(void) * @trigger NoWebGL - triggered if `Crafty.support.webgl` is false * - * Creates a `canvas` element inside `Crafty.stage.elem`. + * This will create a `canvas` element inside `Crafty.stage.elem`, used for displaying "WebGL" components. * * This method will automatically be called by any "WebGL" component if no `Crafty.webgl.context` is * found, so it is not neccessary to call this manually. diff --git a/src/isometric/isometric.js b/src/isometric/isometric.js index 8828b8ed..ea5639b2 100644 --- a/src/isometric/isometric.js +++ b/src/isometric/isometric.js @@ -74,12 +74,12 @@ Crafty.extend({ /**@ * #Crafty.isometric.pos2px * @comp Crafty.isometric - * @sign public this Crafty.isometric.pos2px(Number x,Number y) - * @param x - * @param y - * @return Object {left Number,top Number} + * @sign public Object Crafty.isometric.pos2px(Number x,Number y) + * @param x - A position along the x axis + * @param y - A position along the y axis + * @return An object with `left` and `top` fields {left Number,top Number} * - * This method calculate the X and Y Coordinates to Pixel Positions + * This method converts a position in x and y coordinates to one in pixels * * @example * ~~~ @@ -96,12 +96,12 @@ Crafty.extend({ /**@ * #Crafty.isometric.px2pos * @comp Crafty.isometric - * @sign public this Crafty.isometric.px2pos(Number left,Number top) - * @param top - * @param left - * @return Object {x Number,y Number} + * @sign public Object Crafty.isometric.px2pos(Number left,Number top) + * @param top - Offset from the top in pixels + * @param left - Offset from the left in pixels + * @return An object with `x` and `y` fields representing the position * - * This method calculate pixel top,left positions to x,y coordinates + * This method converts a position in pixels to x,y coordinates * * @example * ~~~ @@ -119,11 +119,15 @@ Crafty.extend({ /**@ * #Crafty.isometric.centerAt * @comp Crafty.isometric - * @sign public this Crafty.isometric.centerAt(Number x,Number y) - * @param top - * @param left * - * This method center the Viewport at x/y location or gives the current centerpoint of the viewport + * @sign public Obect Crafty.isometric.centerAt() + * @returns An object with `top` and `left` fields represneting the viewport's current center + * + * @sign public this Crafty.isometric.centerAt(Number x, Number y) + * @param x - The x position to center at + * @param y - The y position to center at + * + * This method centers the Viewport at an `x,y` location or gives the current centerpoint of the viewport * * @example * ~~~ @@ -148,10 +152,11 @@ Crafty.extend({ /**@ * #Crafty.isometric.area * @comp Crafty.isometric - * @sign public this Crafty.isometric.area() - * @return Object {x:{start Number,end Number},y:{start Number,end Number}} + * @sign public Object Crafty.isometric.area() + * @return An obect with `x` and `y` fields, each of which have a start and end field. + * In other words, the object has this structure: `{x:{start Number,end Number},y:{start Number,end Number}}` * - * This method get the Area surrounding by the centerpoint depends on viewport height and width + * This method returns an object representing the bounds of the viewport * * @example * ~~~ diff --git a/src/spatial/2d.js b/src/spatial/2d.js index 67ca0a20..c9ce2d26 100644 --- a/src/spatial/2d.js +++ b/src/spatial/2d.js @@ -547,17 +547,14 @@ Crafty.c("2D", { /**@ * #.pos * @comp 2D - * @sign public Object .pos(void) + * @sign public Object .pos([Object pos]) + * @param pos - an object to use as output * - * @param {{}=obj} pos + * @returns An object with this entity's `_x`, `_y`, `_w`, and `_h` values. + * If an object is passed in, it will be reused rather than creating a new object. * - * Returns the x, y, w, h properties as a new rect object if - * no object is included. If object is inclued adds x, y, w, h - * to included object. - * (a rect object is just an object with the keys _x, _y, _w, _h). - * - * The keys have an underscore prefix. This is due to the x, y, w, h - * properties being merely setters and getters that wrap the properties with an underscore (_x, _y, _w, _h). + * @note The keys have an underscore prefix. This is due to the x, y, w, h + * properties being setters and getters that wrap the underlying properties with an underscore (_x, _y, _w, _h). */ pos: function (pos) { pos = pos || {}; @@ -1355,7 +1352,6 @@ Crafty.c("AngularMotion", { * #.resetAngularMotion * @comp AngularMotion * @sign public this .resetAngularMotion() - * @return this * * Reset all motion (resets velocity, acceleration, motionDelta). */ @@ -1681,7 +1677,7 @@ Crafty.c("Motion", { * #Crafty.polygon * @category 2D * - * Polygon object used for hitboxes and click maps. Takes a set of points as an + * The constructor for a polygon object used for hitboxes and click maps. Takes a set of points as an * argument, giving alternately the x and y coordinates of the polygon's vertices in order. * * The constructor accepts the coordinates as either a single array or as a set of individual arguments. @@ -1768,10 +1764,10 @@ Crafty.polygon.prototype = { * Returns a clone of the polygon. * * @example - * + * ~~~ * var poly = new Crafty.polygon([50, 0, 100, 100, 0, 100]); * var shiftedpoly = poly.clone().shift(5,5); - * //[[55, 5, 105, 5, 5, 105], but the original polygon is unchanged + * //[55, 5, 105, 5, 5, 105], but the original polygon is unchanged * ~~~ */ clone: function() { diff --git a/src/spatial/collision.js b/src/spatial/collision.js index 7193201c..5cdc7173 100644 --- a/src/spatial/collision.js +++ b/src/spatial/collision.js @@ -6,7 +6,7 @@ var Crafty = require('../core/core.js'), * #Collision * @category 2D * @trigger HitOn - Triggered when collisions occur. Will not trigger again until collisions of this type cease, or an event is requested once more (using `resetHitChecks(component)`). - { hitData } - * @trigger HitOff - Triggered when collision with a specific component type ceases - { componentName } + * @trigger HitOff - Triggered when collision with a specific component type ceases - String - componentName * * Component to detect collision between any two convex polygons. * @@ -14,25 +14,15 @@ var Crafty = require('../core/core.js'), * multiple types occur simultaniously, each collision will cause an individual * event to fire. * - * **Note:** All data received from events is only valid for the duration of the event's callback. + * @note All data received from events is only valid for the duration of the event's callback. * If you wish to preserve the data, make a copy of it. * * For a description of collision event data (hitData above), see the documentation for * `.hit()`. * - * @see .hit, .checkHits, .onHit */ Crafty.c("Collision", { - /**@ - * #.init - * @comp Collision - * Set up collision handling. - * - * By default, the collision hitbox will match the dimensions (x, y, w, h) and rotation of the object. - * - * **Note:** If the entity this component is applied to does not have its - * dimensions set the default hit area will not be set properly. - */ + init: function () { this.requires("2D"); this._collisionData = {}; @@ -250,11 +240,12 @@ Crafty.c("Collision", { * overlap: [number] * }] * ~~~ - * **obj:** The entity with which the collision occured. - * **type:** Collision detection method used. One of: - * + *MBR:* Standard axis aligned rectangle intersection (`.intersect` in the 2D component). - * + *SAT:* Collision between any two convex polygons. Used when both colliding entities have the `Collision` component applied to them. - * **overlap:** If SAT collision was used, this will signify the overlap percentage between the colliding entities. + * + * - **obj:** The entity with which the collision occured. + * - **type:** Collision detection method used. One of: + * - *MBR:* Standard axis aligned rectangle intersection (`.intersect` in the 2D component). + * - *SAT:* Collision between any two convex polygons. Used when both colliding entities have the `Collision` component applied to them. + * - **overlap:** If SAT collision was used, this will signify the overlap percentage between the colliding entities. * * @see 2D */ @@ -394,7 +385,7 @@ Crafty.c("Collision", { * Calling this method more than once for the same component type will not * cause redundant hit checks. * - * **Note:** Hit checks are performed upon entering each new frame (using + * @note Hit checks are performed upon entering each new frame (using * the *EnterFrame* event). It is entirely possible for object to move in * said frame after the checks were performed (even if the more is the * result of *EnterFrame*, as handlers run in no particular order). In such diff --git a/src/spatial/math.js b/src/spatial/math.js index 54ee563e..2f7648d7 100644 --- a/src/spatial/math.js +++ b/src/spatial/math.js @@ -3,8 +3,9 @@ var Crafty = require('../core/core.js'); /**@ * #Crafty.math - * @category 2D - * Static functions. + * @category Utilities + * + * A set of utility functions for common (and not so common) operations. */ Crafty.math = { /**@ @@ -25,12 +26,11 @@ Crafty.math = { * @comp Crafty.math * @sign public Number Crafty.math.amountOf(Number checkValue, Number minValue, Number maxValue) * @param checkValue - Value that should checked with minimum and maximum. - * @param minValue - Minimum value to check. - * @param maxValue - Maximum value to check. - * @return Amount of checkValue compared to minValue and maxValue. + * @param minValue - Bottom of the range + * @param maxValue - Top of the range + * @return The position of the checked value in a coordinate system normalized such that `minValue` is 0 and `maxValue` is 1. * - * Returns the amount of how much a checkValue is more like minValue (=0) - * or more like maxValue (=1) + * If checkValue is within the range, this will return a number between 0 and 1. */ amountOf: function (checkValue, minValue, maxValue) { if (minValue < maxValue) @@ -64,8 +64,9 @@ Crafty.math = { * #Crafty.math.degToRad * Converts angle from degree to radian. * @comp Crafty.math - * @param angleInDeg - The angle in degree. - * @return The angle in radian. + * @sign public Number degToRad(angleInDeg) + * @param angleInDeg - The angle in degrees. + * @return The angle in radians. */ degToRad: function (angleInDeg) { return angleInDeg * Math.PI / 180; @@ -108,10 +109,10 @@ Crafty.math = { * #Crafty.math.negate * @comp Crafty.math * @sign public Number Crafty.math.negate(Number percent) - * @param percent - If you pass 1 a -1 will be returned. If you pass 0 a 1 will be returned. + * @param percent - The probability of returning `-1` * @return 1 or -1. * - * Returnes "randomly" -1. + * Returns `1` or `-1` randomly. */ negate: function (percent) { if (Math.random() < percent) @@ -154,7 +155,7 @@ Crafty.math = { * @param end - Biggest int value that can be returned. * @return A random int. * - * Returns a random int in within a specific range. + * Returns a random int within a specific range. */ randomInt: function (start, end) { return start + Math.floor((1 + end - start) * Math.random()); diff --git a/src/spatial/spatial-grid.js b/src/spatial/spatial-grid.js index f02e032c..0ea80565 100644 --- a/src/spatial/spatial-grid.js +++ b/src/spatial/spatial-grid.js @@ -32,12 +32,15 @@ var Crafty = require('../core/core.js'); * @comp Crafty.map * @sign public Object Crafty.map.insert(Object obj) * @param obj - An entity to be inserted. - * + * @returns An object representing this object's entry in the HashMap + * * `obj` is inserted in '.map' of the corresponding broad phase cells. An object of the following fields is returned. * ~~~ - * - the object that keep track of cells (keys) - * - `obj` - * - the HashMap object + * { + * keys: the object that keep track of cells + * obj: The inserted object + * map: the HashMap object + * } * ~~~ */ insert: function (obj) { @@ -65,11 +68,12 @@ var Crafty = require('../core/core.js'); * @comp Crafty.map * @sign public Object Crafty.map.search(Object rect[, Boolean filter]) * @param rect - the rectangular region to search for entities. - * @param filter - Default value is true. Otherwise, must be false. + * @param filter - If false, only performs a broad-phase collision check. The default value is true. * * - If `filter` is `false`, just search for all the entries in the give `rect` region by broad phase collision. Entity may be returned duplicated. * - If `filter` is `true`, filter the above results by checking that they actually overlap `rect`. - * The easier usage is with `filter`=`true`. For performance reason, you may use `filter`=`false`, and filter the result yourself. See examples in drawing.js and collision.js + * + * The easier usage is with `filter == true`. For performance reason, you may use `filter == false`, and filter the result yourself. See examples in drawing.js and collision.js */ search: function (rect, filter) { @@ -120,7 +124,7 @@ var Crafty = require('../core/core.js'); * @comp Crafty.map * @sign public void Crafty.map.remove([Object keys, ]Object obj) * @param keys - key region. If omitted, it will be derived from obj by `Crafty.HashMap.key`. - * @param obj - need more document. + * @param obj - An object to remove from the hashmap * * Remove an entity in a broad phase map. * - The second form is only used in Crafty.HashMap to save time for computing keys again, where keys were computed previously from obj. End users should not call this form directly. @@ -163,7 +167,7 @@ var Crafty = require('../core/core.js'); * @sign public void Crafty.map.remove(Entry entry) * @param entry - An entry to update * - * Refresh an entry's keys, and its position in the broad phrase map. + * Update an entry's keys, and its position in the broad phrase map. * * @example * ~~~ @@ -211,8 +215,8 @@ var Crafty = require('../core/core.js'); * #Crafty.map.boundaries * @comp Crafty.map * @sign public Object Crafty.map.boundaries() + * @returns An object with the following structure, which represents an MBR which contains all entities * - * The return `Object` is of the following format. * ~~~ * { * min: { @@ -308,7 +312,7 @@ var Crafty = require('../core/core.js'); * Broad-phase collision detection engine. See background information at * * - [N Tutorial B - Broad-Phase Collision](http://www.metanetsoftware.com/technique/tutorialB.html) - * - [Broad-Phase Collision Detection with CUDA](http.developer.nvidia.com/GPUGems3/gpugems3_ch32.html) + * - [Broad-Phase Collision Detection with CUDA](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch32.html) * @see Crafty.map */ From dfdea36ca27577f1d3b0f215e912c3fcc0f661da Mon Sep 17 00:00:00 2001 From: Kevin Simper Date: Fri, 5 Jun 2015 10:59:58 +0200 Subject: [PATCH 09/15] A link where you can easily see the example online and edit yourself --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f13f8b09..1aacfdcb 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Crafty.e("RightPoints, DOM, 2D, Text") .attr({ x: 515, y: 20, w: 100, h: 20, points: 0 }) .text("0 Points"); ``` - +[Check it out online and try to modify it yourself here](http://requirebin.com/?gist=4f76e88be389f2fe8f7f). ##Developing From dd9af23d40435a8ddbfe56df22c56530615c4c58 Mon Sep 17 00:00:00 2001 From: Kevin Kirsche Date: Wed, 10 Jun 2015 18:04:39 -0400 Subject: [PATCH 10/15] Remove moot `version` property from bower.json Per bower/bower.json-spec@a325da3 --- bower.json | 1 - 1 file changed, 1 deletion(-) diff --git a/bower.json b/bower.json index 3aec2d91..1b5c826c 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,5 @@ { "name": "crafty", - "version": "0.6.2", "main": "dist/crafty.js", "license": "MIT", "ignore": [ From 31937ba65d11a9c9830556884aed741574d09270 Mon Sep 17 00:00:00 2001 From: Tim Martin Date: Thu, 11 Jun 2015 16:47:13 -0400 Subject: [PATCH 11/15] Fix bugs with NewDirection (and angular version) - Fixes a rounding issue when calculating the sign of negative fractions - Triggers NewDirection in the frame where the direction changes, instead of the next frame - Renames NewRotation to NewAngularDirection and fixes the same issues - Adds/fixes related tests --- src/spatial/2d.js | 39 ++++++++++++++++++++---------------- tests/2d.js | 50 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/spatial/2d.js b/src/spatial/2d.js index c9ce2d26..5353dbea 100644 --- a/src/spatial/2d.js +++ b/src/spatial/2d.js @@ -1268,7 +1268,7 @@ var __motionVector = function(self, prefix, setter, vector) { * #AngularMotion * @category 2D * @trigger Rotated - When entity has rotated due to angular velocity/acceleration a Rotated event is triggered. - Number - Old rotation - * @trigger NewRevolution - When entity has changed rotational direction due to rotational velocity a NewRevolution event is triggered. The event is triggered once, if direction is different from last frame. - -1 | 0 | 1 - New direction + * @trigger NewRotationDirection - When entity has changed rotational direction due to rotational velocity a NewRotationDirection event is triggered. The event is triggered once, if direction is different from last frame. - -1 | 0 | 1 - New direction * @trigger MotionChange - When a motion property has changed a MotionChange event is triggered. - { key: String, oldValue: Number } - Motion property name and old value * * Component that allows rotating an entity by applying angular velocity and acceleration. @@ -1369,14 +1369,6 @@ Crafty.c("AngularMotion", { */ _angularMotionTick: function(frameData) { var dt = frameData.dt * this._dtFactor; - - var _vr = this._vrotation, - dvr = _vr >> 31 | -_vr >>> 31; // Math.sign(this._vrotation) - if (this.__oldRevolution !== dvr) { - this.__oldRevolution = dvr; - this.trigger('NewRevolution', dvr); - } - var oldR = this._rotation, vr = this._vrotation, ar = this._arotation; @@ -1385,6 +1377,14 @@ Crafty.c("AngularMotion", { var newR = oldR + vr * dt + 0.5 * ar * dt * dt; // v += a * Δt this.vrotation = vr + ar * dt; + + var _vr = this._vrotation, + dvr = _vr ? (vr<0 ? -1:1):0; // Quick implementation of Math.sign + if (this.__oldRevolution !== dvr) { + this.__oldRevolution = dvr; + this.trigger('NewRotationDirection', dvr); + } + // Δs = s[t] - s[t-1] this._drotation = newR - oldR; @@ -1635,14 +1635,6 @@ Crafty.c("Motion", { var dt = frameData.dt * this._dtFactor; var oldDirection = this.__oldDirection; - var _vx = this._vx, dvx = _vx >> 31 | -_vx >>> 31, // Math.sign(this._vx) - _vy = this._vy, dvy = _vy >> 31 | -_vy >>> 31; // Math.sign(this._vy) - if (oldDirection.x !== dvx || oldDirection.y !== dvy) { - var directionEvent = this.__directionEvent; - directionEvent.x = oldDirection.x = dvx; - directionEvent.y = oldDirection.y = dvy; - this.trigger('NewDirection', directionEvent); - } var oldX = this._x, vx = this._vx, ax = this._ax, oldY = this._y, vy = this._vy, ay = this._ay; @@ -1653,6 +1645,19 @@ Crafty.c("Motion", { // v += a * Δt this.vx = vx + ax * dt; this.vy = vy + ay * dt; + + + // Check to see if the velocity has changed + var _vx = this._vx, dvx = _vx ? (_vx<0 ? -1:1):0, // A quick implementation of Math.sign + _vy = this._vy, dvy = _vy ? (_vy<0 ? -1:1):0; + if (oldDirection.x !== dvx || oldDirection.y !== dvy) { + var directionEvent = this.__directionEvent; + directionEvent.x = oldDirection.x = dvx; + directionEvent.y = oldDirection.y = dvy; + this.trigger('NewDirection', directionEvent); + } + + // Δs = s[t] - s[t-1] this._dx = newX - oldX; this._dy = newY - oldY; diff --git a/tests/2d.js b/tests/2d.js index 4cd8450b..b0f32055 100644 --- a/tests/2d.js +++ b/tests/2d.js @@ -535,6 +535,48 @@ ent.destroy(); }); + test("Motion - changing vector", function() { + var Vector2D = Crafty.math.Vector2D; + var zero = new Vector2D(); + var ent = Crafty.e("2D, Motion") + .attr({x: 0, y:0}); + var vec1 = ent.velocity(); + + ent.vx = 5; + + equal(ent.velocity().x, 5, "Velocity component changed"); + + }); + + test("Motion - NewDirection Event", function(){ + var e = Crafty.e("2D, Motion") + .attr({x: 10, y:10}); + e.vx = 0; + e.vy = 0; + e.ay = 0; + e.ax = -0.3; + var newDirectionFlag = false; + e.bind("NewDirection", function(){ + newDirectionFlag = true; + }); + Crafty.timer.simulateFrames(1); + equal(newDirectionFlag, true, "NewDirection was triggered"); + }); + + test("AngularMotion - NewRotationDirection Event", function(){ + var e = Crafty.e("2D, AngularMotion") + .attr({x: 10, y:10}); + e.vrotation = 0; + e.arotation = -0.3; + + var newDirectionFlag = false; + e.bind("NewRotationDirection", function(){ + newDirectionFlag = true; + }); + Crafty.timer.simulateFrames(1); + equal(newDirectionFlag, true, "NewDirection was triggered"); + }); + test("Motion - Events", function() { var Vector2D = Crafty.math.Vector2D; var zero = new Vector2D(); @@ -542,15 +584,15 @@ .attr({x: 0, y:0}); var newDirectionEvents = 0, - newRevolutionEvents = 0, + newRotationDirectionEvents = 0, movedEvents = 0, rotatedEvents = 0, motionEvents = 0; e.bind("NewDirection", function(evt) { newDirectionEvents++; }); - e.bind("NewRevolution", function(evt) { - newRevolutionEvents++; + e.bind("NewRotationDirection", function(evt) { + newRotationDirectionEvents++; }); e.bind("Moved", function(evt) { movedEvents++; @@ -658,7 +700,7 @@ Crafty.timer.simulateFrames(1); equal(newDirectionEvents, 4); - equal(newRevolutionEvents, 3); + equal(newRotationDirectionEvents, 3); equal(movedEvents, 6); equal(rotatedEvents, 2); equal(motionEvents, 17); From 6ed896008dd2f374200c0e84b3394a743ffc8526 Mon Sep 17 00:00:00 2001 From: Tim Martin Date: Thu, 4 Jun 2015 11:43:55 -0400 Subject: [PATCH 12/15] Reword motion docs Add some in-line documentaiton, and tweak the wording of the API docs for the Motion component --- src/spatial/2d.js | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/spatial/2d.js b/src/spatial/2d.js index 5353dbea..da5dfc39 100644 --- a/src/spatial/2d.js +++ b/src/spatial/2d.js @@ -1079,6 +1079,8 @@ Crafty.c("Supportable", { * Component that attaches the entity to the ground when it lands. Useful for platformers with moving platforms. * Remove the component to disable the functionality. * + * @see Supportable, Gravity + * * @example * ~~~ * Crafty.e("2D, Gravity, GroundAttacher") @@ -1215,7 +1217,11 @@ Crafty.c("Gravity", { } }); - +// This is used to define getters and setters for Motion properties +// For instance +// __motionProp(entity, "a", "x", true) +// will define a getter for `ax` which accesses an underlying private property `_ax` +// If the `setter` property is false, setting a value will be a null-op var __motionProp = function(self, prefix, prop, setter) { var publicProp = prefix + prop; var privateProp = "_" + publicProp; @@ -1246,6 +1252,10 @@ var __motionProp = function(self, prefix, prop, setter) { }); }; +// This defines an alias for a pair of underlying properties which represent the components of a vector +// It takes an object with vector methods, and redefines its x/y properties as getters and setters to properties of self +// This allows you to use the vector's special methods to manipulate the entity's properties, +// while still allowing you to manipulate those properties directly if performance matters var __motionVector = function(self, prefix, setter, vector) { var publicX = prefix + "x", publicY = prefix + "y", @@ -1279,7 +1289,7 @@ Crafty.c("AngularMotion", { * #.vrotation * @comp AngularMotion * - * A number for accessing/modifying the angular(rotational) velocity. + * A property for accessing/modifying the angular(rotational) velocity. * The velocity remains constant over time, unless the acceleration increases the velocity. * * @example @@ -1297,7 +1307,7 @@ Crafty.c("AngularMotion", { * #.arotation * @comp AngularMotion * - * A number for accessing/modifying the angular(rotational) acceleration. + * A property for accessing/modifying the angular(rotational) acceleration. * The acceleration increases the velocity over time, resulting in ever increasing speed. * * @example @@ -1404,14 +1414,16 @@ Crafty.c("AngularMotion", { * * Component that allows moving an entity by applying linear velocity and acceleration. * All linear motion values are expressed in pixels per frame (e.g. an entity with `vx` of 1 will move 1px on the x axis each frame). + * + * @note Several methods return Vector2D objects that dynamically reflect the entity's underlying properties. If you want a static copy instead, use the vector's `clone()` method. */ Crafty.c("Motion", { /**@ * #.vx * @comp Motion * - * A number for accessing/modifying the linear velocity in the x axis. - * The velocity remains constant over time, unless the acceleration increases the velocity. + * A property for accessing/modifying the linear velocity in the x axis. + * The velocity remains constant over time, unless the acceleration changes the velocity. * * @example * ~~~ @@ -1428,8 +1440,8 @@ Crafty.c("Motion", { * #.vy * @comp Motion * - * A number for accessing/modifying the linear velocity in the y axis. - * The velocity remains constant over time, unless the acceleration increases the velocity. + * A property for accessing/modifying the linear velocity in the y axis. + * The velocity remains constant over time, unless the acceleration changes the velocity. * * @example * ~~~ @@ -1446,8 +1458,8 @@ Crafty.c("Motion", { * #.ax * @comp Motion * - * A number for accessing/modifying the linear acceleration in the x axis. - * The acceleration increases the velocity over time, resulting in ever increasing speed. + * A property for accessing/modifying the linear acceleration in the x axis. + * The acceleration changes the velocity over time. * * @example * ~~~ @@ -1464,8 +1476,8 @@ Crafty.c("Motion", { * #.ay * @comp Motion * - * A number for accessing/modifying the linear acceleration in the y axis. - * The acceleration increases the velocity over time, resulting in ever increasing speed. + * A property for accessing/modifying the linear acceleration in the y axis. + * The acceleration changes the velocity over time. * * @example * ~~~ From c7ac83f1b6d69c34f321060429a2ecc83a83a878 Mon Sep 17 00:00:00 2001 From: Tim Martin Date: Mon, 15 Jun 2015 14:00:57 -0400 Subject: [PATCH 13/15] Sync motion with clock rather than number of frames Instead of adjusting the speed based on the frame rate, try to saty in sync with the game clock by using frame.dt. Note that speeds are in pixels per second. This is a breaking change, because it changes how we interpret speeds. (Pixels per second instead of pixels per frame.) --- src/controls/controls.js | 29 ++--- src/spatial/2d.js | 30 ++---- tests/2d.js | 226 ++++++++++++++++++++++----------------- tests/controls.js | 140 +++++++++--------------- 4 files changed, 202 insertions(+), 223 deletions(-) diff --git a/src/controls/controls.js b/src/controls/controls.js index 3072eb4e..464f1936 100644 --- a/src/controls/controls.js +++ b/src/controls/controls.js @@ -144,7 +144,7 @@ Crafty.c("Multiway", { this._keyDirection = {}; // keyCode -> direction this._activeDirections = {}; // direction -> # of keys pressed for that direction this._directionSpeed = {}; // direction -> {x: x_speed, y: y_speed} - this._speed = { x: 3, y: 3 }; + this._speed = { x: 150, y: 150 }; this.bind("KeyDown", this._keydown) .bind("KeyUp", this._keyup); @@ -185,7 +185,7 @@ Crafty.c("Multiway", { * #.multiway * @comp Multiway * @sign public this .multiway([Number speed,] Object keyBindings) - * @param speed - Amount of pixels to move the entity whilst a key is down + * @param speed - A speed in pixels per second * @param keyBindings - What keys should make the entity go in which direction. Direction is specified in degrees * * Constructor to initialize the speed and keyBindings. Component will listen to key events and move the entity appropriately. @@ -193,8 +193,8 @@ Crafty.c("Multiway", { * * @example * ~~~ - * this.multiway(3, {UP_ARROW: -90, DOWN_ARROW: 90, RIGHT_ARROW: 0, LEFT_ARROW: 180}); - * this.multiway({x:3,y:1.5}, {UP_ARROW: -90, DOWN_ARROW: 90, RIGHT_ARROW: 0, LEFT_ARROW: 180}); + * this.multiway(150, {UP_ARROW: -90, DOWN_ARROW: 90, RIGHT_ARROW: 0, LEFT_ARROW: 180}); + * this.multiway({x:150,y:75}, {UP_ARROW: -90, DOWN_ARROW: 90, RIGHT_ARROW: 0, LEFT_ARROW: 180}); * this.multiway({W: -90, S: 90, D: 0, A: 180}); * ~~~ * @@ -234,12 +234,13 @@ Crafty.c("Multiway", { * @sign public this .speed(Object speed) * @param speed - New speed the entity has, for x and y axis. * - * Change the speed that the entity moves with. + * Change the speed that the entity moves with, in units of pixels per second. + * * Can be called while a key is pressed to change speed on the fly. * * @example * ~~~ - * this.speed({ x: 3, y: 1 }); + * this.speed({ x: 150, y: 50 }); * ~~~ */ speed: function (speed) { @@ -360,7 +361,7 @@ Crafty.c("Multiway", { * @see Supportable, Motion, Keyboard, Gravity */ Crafty.c("Jumpway", { - _jumpSpeed: 6, + _jumpSpeed: 300, /**@ * #.canJump @@ -441,7 +442,7 @@ Crafty.c("Jumpway", { * #.jumpway * @comp Jumpway * @sign public this .jumpway([Number jumpSpeed,] Array jumpKeys) - * @param jumpSpeed - Vertical jump speed + * @param jumpSpeed - Vertical jump speed in pixels per second * @param jumpKeys - Keys to listen for and make entity jump in response * * Constructor to initialize the power of jump and keys to listen to. Component will @@ -450,8 +451,8 @@ Crafty.c("Jumpway", { * * @example * ~~~ - * this.jumpway(6, ['UP_ARROW', 'W']); - * this.jumpway(['UP_ARROW', 'W']); + * this.jumper(300, ['UP_ARROW', 'W']); + * this.jumper(['UP_ARROW', 'W']); * ~~~ * * @see Supportable, Motion, Keyboard, Gravity @@ -485,7 +486,7 @@ Crafty.c("Jumpway", { * * @example * ~~~ - * this.jumpSpeed(6); + * this.jumpSpeed(300); * ~~~ */ jumpSpeed: function (jumpSpeed) { @@ -515,7 +516,7 @@ Crafty.c("Fourway", { * #.fourway * @comp Fourway * @sign public this .fourway([Number speed]) - * @param speed - Amount of pixels to move the entity whilst a key is down + * @param speed - The speed of motion in pixels per second. * * Constructor to initialize the speed. Component will listen for key events and move the entity appropriately. * This includes `Up Arrow`, `Right Arrow`, `Down Arrow`, `Left Arrow` as well as `W`, `A`, `S`, `D`. @@ -563,8 +564,8 @@ Crafty.c("Twoway", { * #.twoway * @comp Twoway * @sign public this .twoway([Number speed[, Number jumpSpeed]]) - * @param speed - Amount of pixels to move left or right - * @param jumpSpeed - Vertical jump speed + * @param speed - A speed in pixels per second + * @param jumpSpeed - Vertical jump speed in pixels per second * * Constructor to initialize the speed and power of jump. Component will * listen for key events and move the entity appropriately. This includes diff --git a/src/spatial/2d.js b/src/spatial/2d.js index da5dfc39..115aa098 100644 --- a/src/spatial/2d.js +++ b/src/spatial/2d.js @@ -1119,7 +1119,7 @@ Crafty.c("GroundAttacher", { * @see Supportable, Motion */ Crafty.c("Gravity", { - _gravityConst: 0.2, + _gravityConst: 500, init: function () { this.requires("2D, Supportable, Motion"); @@ -1133,7 +1133,7 @@ Crafty.c("Gravity", { }, _gravityCheckLanding: function(ground) { - if (this._dy < 0) + if (this._dy < 0) this.canLand = false; }, @@ -1184,9 +1184,9 @@ Crafty.c("Gravity", { * #.gravityConst * @comp Gravity * @sign public this .gravityConst(g) - * @param g - gravitational constant + * @param g - gravitational constant in pixels per second squared * - * Set the gravitational constant to g. The default is 0.2 . The greater g, the faster the object falls. + * Set the gravitational constant to g for this entity. The default is 500. The greater g, the stronger the downwards acceleration. * * @example * ~~~ @@ -1282,7 +1282,7 @@ var __motionVector = function(self, prefix, setter, vector) { * @trigger MotionChange - When a motion property has changed a MotionChange event is triggered. - { key: String, oldValue: Number } - Motion property name and old value * * Component that allows rotating an entity by applying angular velocity and acceleration. - * All angular motion values are expressed in degrees per frame (e.g. an entity with `vrotation` of 10 will rotate 10 degrees each frame). + * All angular motion values are expressed in degrees per second (e.g. an entity with `vrotation` of 10 will rotate 10 degrees each second). */ Crafty.c("AngularMotion", { /**@ @@ -1346,16 +1346,9 @@ Crafty.c("AngularMotion", { this.__oldRevolution = 0; this.bind("EnterFrame", this._angularMotionTick); - this.bind("FPSChange", this._angularChangeFPS); - this._angularChangeFPS(Crafty.timer.FPS()); }, remove: function(destroyed) { this.unbind("EnterFrame", this._angularMotionTick); - this.unbind("FPSChange", this._angularChangeFPS); - }, - - _angularChangeFPS: function(fps) { - this._dtFactor = fps / 1000; }, /**@ @@ -1378,7 +1371,7 @@ Crafty.c("AngularMotion", { * v += a * Δt */ _angularMotionTick: function(frameData) { - var dt = frameData.dt * this._dtFactor; + var dt = frameData.dt / 1000; // Time in s var oldR = this._rotation, vr = this._vrotation, ar = this._arotation; @@ -1413,7 +1406,7 @@ Crafty.c("AngularMotion", { * @trigger MotionChange - When a motion property has changed a MotionChange event is triggered. - { key: String, oldValue: Number } - Motion property name and old value * * Component that allows moving an entity by applying linear velocity and acceleration. - * All linear motion values are expressed in pixels per frame (e.g. an entity with `vx` of 1 will move 1px on the x axis each frame). + * All linear motion values are expressed in pixels per second (e.g. an entity with `vx` of 1 will move 1px on the x axis each second). * * @note Several methods return Vector2D objects that dynamically reflect the entity's underlying properties. If you want a static copy instead, use the vector's `clone()` method. */ @@ -1538,16 +1531,9 @@ Crafty.c("Motion", { this.__oldDirection = {x: 0, y: 0}; this.bind("EnterFrame", this._linearMotionTick); - this.bind("FPSChange", this._linearChangeFPS); - this._linearChangeFPS(Crafty.timer.FPS()); }, remove: function(destroyed) { this.unbind("EnterFrame", this._linearMotionTick); - this.unbind("FPSChange", this._linearChangeFPS); - }, - - _linearChangeFPS: function(fps) { - this._dtFactor = fps / 1000; }, /**@ @@ -1644,7 +1630,7 @@ Crafty.c("Motion", { * v += a * Δt */ _linearMotionTick: function(frameData) { - var dt = frameData.dt * this._dtFactor; + var dt = frameData.dt / 1000; // time in s var oldDirection = this.__oldDirection; diff --git a/tests/2d.js b/tests/2d.js index b0f32055..5abb403f 100644 --- a/tests/2d.js +++ b/tests/2d.js @@ -450,6 +450,7 @@ var ent = Crafty.e("2D, Motion, AngularMotion") .attr({x: 0, y:0}); + // Check the initial zeroing of values ok(ent.velocity().equals(zero), "linear velocity should be zero"); strictEqual(ent.vrotation, 0, "angular velocity should be zero"); ok(ent.acceleration().equals(zero), "linear acceleration should be zero"); @@ -457,24 +458,30 @@ ok(ent.motionDelta().equals(zero), "linear delta should be zero"); strictEqual(ent.drotation, 0, "angular delta should be zero"); + // Check that you can't overwrite the motionDeltas ent.motionDelta().x = 20; ok(ent.motionDelta().equals(zero), "linear delta should not have changed"); ent.drotation = 10; strictEqual(ent.drotation, 0, "angular delta should not have changed"); + // Set the v0 / v0_r values var v0 = new Vector2D(2,5); var v0_r = 10; + + // Check setting velocity and vrotation ent.velocity().setValues(v0); ent.vrotation = v0_r; ok(ent.velocity().equals(v0), "linear velocity should be <2,5>"); strictEqual(ent.vrotation, v0_r, "angular velocity should be 10"); + // Check setting accelerations var a = new Vector2D(4,2); var a_r = -15; ent.acceleration().setValues(a); ent.arotation = a_r; ok(ent.acceleration().equals(a), "linear acceleration should be <4,2>"); strictEqual(ent.arotation, a_r, "angular acceleration should be -15"); + // Check op assignment on various fields ent.velocity().x += 1; ent.velocity().y *= 2; ent.velocity().y -= 1; @@ -482,7 +489,7 @@ ent.arotation += 5; strictEqual(ent.arotation, a_r + 5, "angular acceleration should be -10"); - + // Reset the motion values back to 0 ent.resetMotion(); ent.resetAngularMotion(); ok(ent.velocity().equals(zero), "linear velocity should be zero"); @@ -493,44 +500,57 @@ strictEqual(ent.drotation, 0, "angular delta should be zero"); - Crafty.timer.FPS(25); + // v = (2, 5) ent.velocity().setValues(v0); + // v0_r = 10 ent.vrotation = v0_r; Crafty.timer.simulateFrames(1); + var dt = 0.020; // 20 ms in 1 frame is the default + // Check what happens to velocity over time with 0 a ok(ent.velocity().equals(v0), "velocity should be <2,5>"); strictEqual(ent.vrotation, v0_r, "angular velocity should be 10"); - ok(ent.motionDelta().equals(v0), "delta should be <2,5>"); - strictEqual(ent.drotation, v0_r, "angular delta should be 10"); - equal(ent.x, v0.x, "entity x should be 2"); - equal(ent.y, v0.y, "entity y should be 5"); - equal(ent.rotation, v0_r, "entity rotation should be 10"); + // Delta in last frame should be + equal(ent.motionDelta().x, v0.x * dt, "delta x should be .04"); + equal(ent.motionDelta().y, v0.y * dt, "delta y should be .1"); + // ok(ent.motionDelta().equals(v0), "delta should be <2,5>"); + strictEqual(ent.drotation, v0_r * dt, "angular delta should be 10"); + equal(ent.x, v0.x * dt, "entity x should be 2"); + equal(ent.y, v0.y * dt, "entity y should be 5"); + equal(ent.rotation, v0_r * dt, "entity rotation should be 10"); + + + // Goal of this test is to check that acceleration processes correctly, so reset everything first! + ent.resetMotion(); + ent.resetAngularMotion(); - var dPos = new Vector2D(a).scale(0.5).add(v0), dPos_r = v0_r + 0.5*a_r; + ent.attr({x:0, y:0, rotation:0}); + + // Set a, v values + a = new Vector2D(4,2); + a_r = -15; + v0 = new Vector2D(2,5); + v0_r = 10; + ent.acceleration().setValues(a); ent.arotation = a_r; + ent.velocity().setValues(v0); + ent.vrotation = v0_r; Crafty.timer.simulateFrames(1); - ok(dPos.equals(new Vector2D(4,6)), "should be <4,6>"); - strictEqual(dPos_r, 2.5, "should be 2.5"); - ok(ent.motionDelta().equals(dPos), "delta should be <4,6>"); - strictEqual(ent.drotation, dPos_r, "should be 2.5"); - equal(ent.x, v0.x + dPos.x, "entity x should be 6"); - equal(ent.y, v0.y + dPos.y, "entity y should be 11"); - equal(ent.rotation, v0_r + dPos_r, "entity rotation should be 12.5"); - var v1 = new Vector2D(v0).add(a), v1_r = v0_r + a_r; - ok(ent.velocity().equals(v1), "linear velocity should be <6,7>"); - strictEqual(ent.vrotation, v1_r, "angular velocity should be -5"); - - - Crafty.timer.FPS(50); - ent.attr({x: 0, y: 0}) - .resetMotion() - .resetAngularMotion(); - - ent.velocity().x = 10; - ent.acceleration().x = 5; - Crafty.timer.simulateFrames(1, (1000 / Crafty.timer.FPS()) / 2); - equal(ent.velocity().x, 10+5*0.5, "velocity x should be 12.5"); - equal(ent.x, 10*0.5+0.5*5*0.5*0.5, "entity x should be 5.625"); + + // Calculate the new configuration of the object via kinematics + dt = 0.020; // 20 ms in one frame + var dPos = new Vector2D(a).scale(0.5*dt*dt).add(v0.clone().scale(dt)), dPos_r = v0_r * dt + 0.5*a_r * dt * dt; + + ok(ent.motionDelta().equals(dPos), "delta should be equal to the new position"); + strictEqual(ent.drotation, dPos_r, "Rotation should match"); + equal(ent.x, dPos.x, "entity x should match calculated"); + equal(ent.y, dPos.y, "entity y should match calculate"); + equal(ent.rotation, dPos_r, "entity rotation should match calculated"); + var v1 = new Vector2D(a).scale(dt).add(v0), v1_r = a_r * dt + v0_r; + equal(ent.velocity().x, v1.x, "vx should match calculated"); + equal(ent.velocity().y, v1.y, "vy should match calculated"); + // ok(ent.velocity().equals(v1), "linear velocity should match calculated"); + strictEqual(ent.vrotation, v1_r, "angular velocity should match calculated"); ent.destroy(); }); @@ -604,106 +624,110 @@ motionEvents++; }); - + // group 1; setting vy and moving one frame e.one("NewDirection", function(evt) { - equal(evt.x, 0); - equal(evt.y, 1); + equal(evt.x, 0, "[1] - no motion along x axis"); + equal(evt.y, 1, "[1] - moving along +y axis"); + }); + e.one("Moved", function(evt) { + strictEqual(evt.axis, "y", "[1] - moved along y axis"); + strictEqual(evt.oldValue, 0, "[1] - old y was 0"); + }); + e.one("MotionChange", function(evt) { + strictEqual(evt.key, "vy", "[1] - vy was set"); + strictEqual(evt.oldValue, 0, "[1] - old vy was 0"); }); - e.one("Moved", function(evt) { strictEqual(evt.axis, "y"); strictEqual(evt.oldValue, 0); }); - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vy"); strictEqual(evt.oldValue, 0); }); e.vy = 1; Crafty.timer.simulateFrames(1); + // group 2: set both vy and vx to be negative + var old_y = e.y; e.one("NewDirection", function(evt) { - equal(evt.x, -1); - equal(evt.y, -1); + equal(evt.x, -1, "[2] - Now moving along -x axis" ); + equal(evt.y, -1, "[2] - Now moving along -y axis"); + }); + e.one("Moved", function(evt) { + strictEqual(evt.axis, "x", "[2] - Moved along x axis"); + strictEqual(evt.oldValue, 0, "[2] - old x was 0"); + e.one("Moved", function(evt) { + strictEqual(evt.axis, "y", "[2] - Moved along y axis"); + strictEqual(evt.oldValue, old_y, "[2] - old y value matches cached"); + }); + }); + e.one("MotionChange", function(evt) { + strictEqual(evt.key, "vx", "[2] - vx was changed"); + strictEqual(evt.oldValue, 0, "[2] - old vx was 0"); }); - e.one("Moved", function(evt) { strictEqual(evt.axis, "x"); strictEqual(evt.oldValue, 0); - e.one("Moved", function(evt) { strictEqual(evt.axis, "y"); strictEqual(evt.oldValue, 1); });}); - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vx"); strictEqual(evt.oldValue, 0); }); - e.vx = -1; - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vy"); strictEqual(evt.oldValue, 1); }); - e.vy = 0; - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vy"); strictEqual(evt.oldValue, 0); }); - e.vy = -1; - Crafty.timer.simulateFrames(1); - - e.one("Moved", function(evt) { strictEqual(evt.axis, "x"); strictEqual(evt.oldValue, -1); - e.one("Moved", function(evt) { strictEqual(evt.axis, "y"); strictEqual(evt.oldValue, 0); });}); e.vx = -1; - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vy"); strictEqual(evt.oldValue, -1); }); - e.vy = 0; - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vy"); strictEqual(evt.oldValue, 0); }); - e.vy = -1; - Crafty.timer.simulateFrames(1); - - e.one("NewDirection", function(evt) { - equal(evt.x, 0); - equal(evt.y, -1); + e.one("MotionChange", function(evt) { + strictEqual(evt.key, "vy", "[2] - vy was changed"); + strictEqual(evt.oldValue, 1, "[2] - old vy value matches cached"); }); - e.one("Moved", function(evt) { strictEqual(evt.axis, "y"); strictEqual(evt.oldValue, -1); }); - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vx"); strictEqual(evt.oldValue, -1); }); - e.vx = 0; - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vy"); strictEqual(evt.oldValue, -1); }); e.vy = 0; - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vy"); strictEqual(evt.oldValue, 0); }); + e.one("MotionChange", function(evt) { + strictEqual(evt.key, "vy", "[2] - vy was changed again"); + strictEqual(evt.oldValue, 0, "[2] - old vy value was 0"); + }); e.vy = -1; Crafty.timer.simulateFrames(1); + // group 3 -- test newdireciton when we were previously moving + e.vy = 1; + e.vx = 0; e.one("NewDirection", function(evt) { - equal(evt.x, 0); - equal(evt.y, 0); + equal(evt.x, 0, "[3] - not moving along x axis"); + equal(evt.y, 0, "[3] - not moving along y axis"); evt.x = 1; // bad boy! }); - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vy"); strictEqual(evt.oldValue, -1); }); - e.vy = 0; - Crafty.timer.simulateFrames(1); - - e.vx = 0; - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vy"); strictEqual(evt.oldValue, 0); }); - e.vy = 1; - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vy"); strictEqual(evt.oldValue, 1); }); e.vy = 0; Crafty.timer.simulateFrames(1); + + // Group 4, rotation tests e.vrotation = 0; - Crafty.timer.simulateFrames(1); - - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vrotation"); strictEqual(evt.oldValue, 0); }); + e.one("MotionChange", function(evt) { + strictEqual(evt.key, "vrotation", "[4] - change of angular speed"); + strictEqual(evt.oldValue, 0, "[4] - old vr value was 0"); + }); e.vrotation = 1; - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vrotation"); strictEqual(evt.oldValue, 1); }); + e.one("MotionChange", function(evt) { + strictEqual(evt.key, "vrotation", "[4] - change of angular speed"); + strictEqual(evt.oldValue, 1, "[4] - old value was 1"); + }); e.vrotation = 0; - Crafty.timer.simulateFrames(1); - e.one("NewRevolution", function(evt) { - equal(evt, 1); + // Group 5 + e.one("NewRotationDirection", function(evt) { + equal(evt, 1, "[5] - Rotating in the positive sense"); + }); + e.one("Rotated", function(oldValue) { + strictEqual(oldValue, 0, "[5] - Rotated from 0 position"); }); - e.one("Rotated", function(oldValue) { strictEqual(oldValue, 0); }); - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vrotation"); strictEqual(evt.oldValue, 0); }); e.vrotation = 1; Crafty.timer.simulateFrames(1); - e.one("NewRevolution", function(evt) { - equal(evt, -1); + var old_rotation = e.rotation; + e.one("NewRotationDirection", function(evt) { + equal(evt, -1, "[6] - Rotating in the negative sense"); + }); + e.one("Rotated", function(oldValue) { + strictEqual(oldValue, old_rotation, "[6] - Old rotation matches cached value"); }); - e.one("Rotated", function(oldValue) { strictEqual(oldValue, 1); }); - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vrotation"); strictEqual(evt.oldValue, 1); }); e.vrotation = -1; Crafty.timer.simulateFrames(1); - e.one("NewRevolution", function(evt) { - equal(evt, 0); + e.one("NewRotationDirection", function(evt) { + equal(evt, 0, "[7] - No longer rotating"); }); - e.one("MotionChange", function(evt) { strictEqual(evt.key, "vrotation"); strictEqual(evt.oldValue, -1); }); e.vrotation = 0; Crafty.timer.simulateFrames(1); - equal(newDirectionEvents, 4); - equal(newRotationDirectionEvents, 3); - equal(movedEvents, 6); - equal(rotatedEvents, 2); - equal(motionEvents, 17); + // TODO: break these up into separate checks + equal(newDirectionEvents, 3, "NewDirection fired 4 times."); + equal(newRotationDirectionEvents, 3, "NewRotation fired 3 times."); + equal(motionEvents, 12, "Motion fired 12 times."); + equal(rotatedEvents, 2, "Rotated fired 2 times."); e.destroy(); }); @@ -820,7 +844,7 @@ var player = Crafty.e("2D, Gravity") .attr({ x: 0, y: 100, w: 32, h: 16 }) - .gravityConst(0.3) + .gravityConst(0.3*50*50) .gravity("platform"); strictEqual(player.acceleration().y, player._gravityConst, "acceleration should match gravity constant"); @@ -849,10 +873,10 @@ vel = -1; var oldVel = this.velocity().y; - this.gravityConst(0.2); - strictEqual(this._gravityConst, 0.2, "gravity constant should have changed"); + this.gravityConst(0.2*50*50); + strictEqual(this._gravityConst, 0.2*50*50, "gravity constant should have changed"); strictEqual(this.acceleration().y, this._gravityConst, "acceleration should match gravity constant"); - strictEqual(this.velocity().y, oldVel, "velocity shouldn't have been resetted"); + strictEqual(this.velocity().y, oldVel, "velocity should not have been reset"); }); this.attr({y: 100}); } else { @@ -866,10 +890,11 @@ } }); - Crafty.timer.simulateFrames(75, 1000/50); + Crafty.timer.simulateFrames(75); ok(done, "Test completed"); }); + test("Integrationtest - Twoway", function() { var done = false; @@ -879,6 +904,7 @@ var player = Crafty.e("2D, Gravity, Twoway") .attr({ x: 0, y: 150, w: 32, h: 10 }) .gravity("platform") + .gravityConst(0.3*50*50) .twoway(2, 4); var landCount = 0, liftCount = 0; @@ -909,7 +935,7 @@ } }); - Crafty.timer.simulateFrames(75, 1000/50); + Crafty.timer.simulateFrames(75); ok(done, "Test completed"); }); diff --git a/tests/controls.js b/tests/controls.js index f7816ace..3571bb4f 100644 --- a/tests/controls.js +++ b/tests/controls.js @@ -3,7 +3,7 @@ module("Controls"); - test("Multiway", function() { + test("Multiway and Fourway", function() { var e = Crafty.e("2D, Fourway") .attr({ x: 0, y: 0}); @@ -15,83 +15,75 @@ return true; return false; }; - e.multiway(1, { W: -90 }); + e.multiway(50, { W: -90 }); Crafty.timer.simulateFrames(1); - equal(e._vy, -1); - equal(e._y, -1); + equal(e._vy, -50, "Speed is 50 in -y direction"); + equal(e._vx, 0, "Speed is 0 in x direction"); + equal(e._y, -1, "Moves 1 pixel down in 20 ms"); - e.multiway(2, { W: 90 }); - Crafty.timer.simulateFrames(1); - equal(e._vy, 2); - equal(e._y, 1); + // Change the key's direction and speed while it's held down + e.attr({x:0, y:0}); + e.multiway(100, { W: 90 }); + Crafty.timer.simulateFrames(1, 20); + equal(e._vy, 100, "Speed is 100 in +y direction"); + equal(e._vx, 0, "Speed is 0 in x direction"); + equal(e._y, 2, "Moves 2 pixels up in 20 ms"); - e.fourway(1); - Crafty.timer.simulateFrames(1); - equal(e._vy, -1); - equal(e._y, 0); + // Change the speed with fourway, (W is negative for fourway) + e.attr({x:0, y:0}); + e.fourway(50); + Crafty.timer.simulateFrames(1, 20); + equal(e._vy, -50, "Speed is 50 in -y direction"); + equal(e._vx, 0, "Speed is 0 in x direction"); + equal(e._y, -1, "Moves down 1 pixel in 20 ms"); Crafty.timer.simulateFrames(1); - equal(e._vy, -1); - equal(e._y, -1); + equal(e._y, -2, "Moves another 1 pixel down in 20 ms"); - + // Test two keys down at the same time Crafty.trigger('KeyDown', { key: Crafty.keys.UP_ARROW }); Crafty.timer.simulateFrames(1); - equal(e._vy, -1); - equal(e._y, -2); + equal(e._vy, -50, "Still speed 50 in -y direction after up arrow"); Crafty.trigger('KeyUp', { key: Crafty.keys.W }); + equal(e._vy, -50, "Still speed 50 in -y direction after W is released"); e.isDown = function(key) { return false; }; Crafty.trigger('KeyUp', { key: Crafty.keys.UP_ARROW }); - Crafty.timer.simulateFrames(1); - equal(e._vy, 0); - equal(e._y, -2); - + equal(e._vy, 0, "Speed is 0 once both keys are released"); + // Diagonal Crafty.trigger('KeyDown', { key: Crafty.keys.DOWN_ARROW }); Crafty.trigger('KeyDown', { key: Crafty.keys.LEFT_ARROW }); - Crafty.timer.simulateFrames(1); - equal(e._vy, 1); - equal(e._y, -1); - equal(e._vx, -1); - equal(e._x, -1); + equal(e._vy, 50, "Speed is 50 in +y direction when DOWN & LEFT are pressed"); + equal(e._vx, -50, "Speed is 50 in -x direction when DOWN & LEFT are pressed"); Crafty.trigger('KeyUp', { key: Crafty.keys.DOWN_ARROW }); - Crafty.timer.simulateFrames(1); - equal(e._vy, 0); - equal(e._y, -1); - equal(e._vx, -1); - equal(e._x, -2); + equal(e._vy, 0, "Speed is 0 in y direction after DOWN is released"); + equal(e._vx, -50, "Speed is still 50 in -x direction"); e.removeComponent("Multiway"); - Crafty.timer.simulateFrames(1); - equal(e._vy, 0); - equal(e._y, -1); - equal(e._vx, 0); - equal(e._x, -2); + equal(e._vy, 0, "Speed set to 0 when component removed"); + equal(e._vx, 0, "Speed set to 0 when component removed"); Crafty.trigger('KeyUp', { key: Crafty.keys.LEFT_ARROW }); - Crafty.timer.simulateFrames(1); - equal(e._vy, 0); - equal(e._y, -1); - equal(e._vx, 0); - equal(e._x, -2); + equal(e._vy, 0, "No change when key released after component removed"); + equal(e._vx, 0, "No change when key released after component is removed"); e.destroy(); @@ -102,58 +94,45 @@ .attr({ x: 0 }) .twoway(); - equal(e._vx, 0); - equal(e._x, 0); + equal(e._vx, 0, "vx starts equal to 0"); + equal(e._x, 0, "No change in _x when twoway is called"); e.enableControl(); - e.speed({ x: 1, y: 1 }); + e.speed({ x: 50, y: 50 }); Crafty.timer.simulateFrames(1); - equal(e._vx, 0); + equal(e._vx, 0, "No change in speed after Twoway speed is set"); equal(e._x, 0); Crafty.trigger('KeyDown', { key: Crafty.keys.D }); Crafty.timer.simulateFrames(1); - equal(e._vx, 1); - equal(e._x, 1); + equal(e._vx, 50, "vx = 50 when key D pressed"); + equal(e._vy, 0, "vy = 0 when key D pressed"); e.disableControl(); - Crafty.timer.simulateFrames(1); - equal(e._vx, 0); - equal(e._x, 1); + equal(e._vx, 0, "vx = 0 once control is disabled"); Crafty.trigger('KeyUp', { key: Crafty.keys.D }); - Crafty.timer.simulateFrames(1); - equal(e._vx, 0); - equal(e._x, 1); + equal(e._vx, 0, "vx = 0 when key is released while control is disabled"); e.disableControl(); - Crafty.timer.simulateFrames(1); - equal(e._vx, 0); - equal(e._x, 1); - + equal(e._vx, 0, "vx = 0 if control disabled a second time"); e.enableControl(); - Crafty.timer.simulateFrames(1); - equal(e._vx, 0); - equal(e._x, 1); + equal(e._vx, 0, "vx = 0 once control re-enabled"); Crafty.trigger('KeyDown', { key: Crafty.keys.D }); - Crafty.timer.simulateFrames(1); - equal(e._vx, 1); - equal(e._x, 2); + equal(e._vx, 50, "vx = 50 once D key pressed again"); Crafty.trigger('KeyUp', { key: Crafty.keys.D }); - Crafty.timer.simulateFrames(1); - equal(e._vx, 0); - equal(e._x, 2); + equal(e._vx, 0, "vx = 0 once key released"); Crafty.trigger('KeyDown', { @@ -162,40 +141,27 @@ Crafty.trigger('KeyDown', { key: Crafty.keys.RIGHT_ARROW }); - Crafty.timer.simulateFrames(1); - equal(e._vx, 1); - equal(e._x, 3); + equal(e._vx, 50, "vx = 50 when both RIGHT and D pressed"); e.disableControl(); - e.speed({ x: 2, y: 2 }); - Crafty.timer.simulateFrames(1); - equal(e._vx, 0); - equal(e._x, 3); + e.speed({ x: 100, y: 100 }); + equal(e._vx, 0, "vx = 0 when control disabled and speed set"); e.enableControl(); - Crafty.timer.simulateFrames(1); - equal(e._vx, 2); - equal(e._x, 5); + equal(e._vx, 100, "vx = 100 when control re-enabled while keys are still held down"); - e.speed({ x: 3, y: 3 }); - Crafty.timer.simulateFrames(1); - equal(e._vx, 3); - equal(e._x, 8); + e.speed({ x: 150, y: 150 }); + equal(e._vx, 150, "vx = 150 when speed updated"); Crafty.trigger('KeyUp', { key: Crafty.keys.D }); - Crafty.timer.simulateFrames(1); - equal(e._vx, 3); - equal(e._x, 11); + equal(e._vx, 150, "vx = 150 when D is released but RIGHT is still down"); Crafty.trigger('KeyUp', { key: Crafty.keys.RIGHT_ARROW }); - Crafty.timer.simulateFrames(1); - equal(e._vx, 0); - equal(e._x, 11); - + equal(e._vx, 0, "vx = 0 once both keys are released"); e.destroy(); }); From 182bfc6020e3739c5f85ca5bdd1cbcf2feb8c4c4 Mon Sep 17 00:00:00 2001 From: Tim Martin Date: Mon, 15 Jun 2015 14:33:11 -0400 Subject: [PATCH 14/15] Change Jumpway -> Jumper "Jumpway" is probably a bit confusing, even though it kind of makes sense in the context of Twoway and Fourway. --- src/controls/controls.js | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/controls/controls.js b/src/controls/controls.js index 464f1936..293ff405 100644 --- a/src/controls/controls.js +++ b/src/controls/controls.js @@ -350,7 +350,7 @@ Crafty.c("Multiway", { /**@ - * #Jumpway + * #Jumper * @category Controls * @trigger NewDirection - When entity has changed direction due to velocity on either x or y axis a NewDirection event is triggered. The event is triggered once, if direction is different from last frame. - { x: -1 | 0 | 1, y: -1 | 0 | 1 } - New direction * @trigger Moved - When entity has moved due to velocity/acceleration on either x or y axis a Moved event is triggered. If the entity has moved on both axes for diagonal movement the event is triggered twice. - { axis: 'x' | 'y', oldValue: Number } - Old position @@ -360,20 +360,20 @@ Crafty.c("Multiway", { * * @see Supportable, Motion, Keyboard, Gravity */ -Crafty.c("Jumpway", { +Crafty.c("Jumper", { _jumpSpeed: 300, /**@ * #.canJump - * @comp Jumpway + * @comp Jumper * * The canJump function determines if the entity is allowed to jump or not (e.g. perhaps the entity should be able to double jump). - * The Jumpway component will trigger a "CheckJumping" event. + * The Jumper component will trigger a "CheckJumping" event. * Interested parties can listen to this event and enable the entity to jump by setting `canJump` to true. * * @example * ~~~ - * var player = Crafty.e("2D, Jumpway"); + * var player = Crafty.e("2D, Jumper"); * player.hasDoubleJumpPowerUp = true; // allow player to double jump by granting him a powerup * player.bind("CheckJumping", function(ground) { * if (!ground && player.hasDoubleJumpPowerUp) { // allow player to double jump by using up his double jump powerup @@ -390,7 +390,7 @@ Crafty.c("Jumpway", { /**@ * #.enableControl - * @comp Jumpway + * @comp Jumper * @sign public this .enableControl() * * Enable the component to listen to key events. @@ -403,7 +403,7 @@ Crafty.c("Jumpway", { /**@ * #.disableControl - * @comp Jumpway + * @comp Jumper * @sign public this .disableControl() * * Disable the component to listen to key events. @@ -422,10 +422,10 @@ Crafty.c("Jumpway", { }, remove: function() { - this.unbind("KeyDown", this._keydown_jumpway); + this.unbind("KeyDown", this._keydown_jumper); }, - _keydown_jumpway: function (e) { + _keydown_jumper: function (e) { if (this.disableControls) return; if (this._jumpKeys[e.key]) { @@ -439,9 +439,9 @@ Crafty.c("Jumpway", { }, /**@ - * #.jumpway - * @comp Jumpway - * @sign public this .jumpway([Number jumpSpeed,] Array jumpKeys) + * #.jumper + * @comp Jumper + * @sign public this .jumper([Number jumpSpeed,] Array jumpKeys) * @param jumpSpeed - Vertical jump speed in pixels per second * @param jumpKeys - Keys to listen for and make entity jump in response * @@ -457,7 +457,7 @@ Crafty.c("Jumpway", { * * @see Supportable, Motion, Keyboard, Gravity */ - jumpway: function (jumpSpeed, jumpKeys) { + jumper: function (jumpSpeed, jumpKeys) { if (jumpKeys) { this._jumpSpeed = jumpSpeed; } else { @@ -471,14 +471,14 @@ Crafty.c("Jumpway", { this._jumpKeys[keyCode] = true; } - this.uniqueBind("KeyDown", this._keydown_jumpway); + this.uniqueBind("KeyDown", this._keydown_jumper); return this; }, /**@ * #.jumpSpeed - * @comp Jumpway + * @comp Jumper * @sign public this .jumpSpeed(Number jumpSpeed) * @param jumpSpeed - new vertical jump speed * @@ -552,12 +552,12 @@ Crafty.c("Fourway", { * * Move an entity left or right using the arrow keys or `D` and `A` and jump using up arrow or `W`. * - * @see Multiway, Jumpway + * @see Multiway, Jumper */ Crafty.c("Twoway", { init: function () { - this.requires("Multiway, Jumpway"); + this.requires("Multiway, Jumper"); }, /**@ @@ -575,7 +575,7 @@ Crafty.c("Twoway", { * The key presses will move the entity in that direction by the speed passed in * the argument. Pressing the `Up Arrow` or `W` will cause the entity to jump. * - * @see Multiway, Jumpway + * @see Multiway, Jumper */ twoway: function (speed, jumpSpeed) { @@ -587,7 +587,7 @@ Crafty.c("Twoway", { Q: 180 }); - this.jumpway(jumpSpeed || speed * 2 || this._jumpSpeed, [ + this.jumper(jumpSpeed || speed * 2 || this._jumpSpeed, [ Crafty.keys.UP_ARROW, Crafty.keys.W, Crafty.keys.Z From c862a41d82188b62164dc4ab16f935a3adeac7fa Mon Sep 17 00:00:00 2001 From: Airza Date: Sat, 11 Jul 2015 19:50:13 +0200 Subject: [PATCH 15/15] Documentation enhanced --- src/isometric/diamond-iso.js | 76 +++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/src/isometric/diamond-iso.js b/src/isometric/diamond-iso.js index badf5b69..fba4ebc8 100644 --- a/src/isometric/diamond-iso.js +++ b/src/isometric/diamond-iso.js @@ -26,6 +26,8 @@ Crafty.extend({ //false if there is no collision in this square _collisionMap: [], _tileLocations: {}, + //This looks totally random, but it lets the grid subdivide different parts of each tile into different integer Z layers so that entities can move + //smoothly across it. _tileZSpacing: 6, /**@ * #Crafty.diamondIso.init @@ -83,13 +85,14 @@ Crafty.extend({ * @param y - The `y` position to place the tile * @param layer - The `z` position to place the tile (only level 0 and 1 are supported) * @param keepOldPosition - If true, the code will place the code in the grid but not update its X/Y + * Useful if the entity is walking on top of the grid or sliding around and just needs to have its grid position updated. * Use this method to place an entity in an isometric grid. * * @example * ~~~ * var iso = Crafty.diamondIso.init(64,128,20,20,0,0); - * isos.place(Crafty.e('2D, DOM, Color').color('red').attr({w:128, h:128}),1,1,2,false); - * This will slot this tile into the grid + * iso.place(Crafty.e('2D, DOM, Color').color('red').attr({w:128, h:128}),1,1,2,false); + * This will slot this tile into the grid. * ~~~ * * @see Crafty.diamondIso.size @@ -157,7 +160,7 @@ Crafty.extend({ /**@ * #Crafty.diamondIso.detachTile * @comp Crafty.diamondIso - * @sign private this Crafty.diamondIso.detachTile(Entity obj) + * @sign private [number x, number y] Crafty.diamondIso.detachTile(Entity obj) * @param obj - the object to remove * When passed an entity, removes that entity from the grid and returns its previous location. * Does not delete the tile. @@ -181,8 +184,7 @@ Crafty.extend({ }, /**@ * #Crafty.diamondIso.centerAt - * @comp Crafty.centerAt - * @sign private this Crafty.centerAt(number x, number y) + * @comp Crafty.diamondIso * @param x - tile X coordinate * @param Y - tile Y coordinate * Centers the grid on the tile at X,Y (not screen pixes, tile coordinates.) @@ -195,26 +197,37 @@ Crafty.extend({ }, /**@ * #Crafty.diamondIso.getZAtLoc - * @comp Crafty.centerAt - * @sign private this Crafty.centerAt.getZAtLoc(number x, number y) - * @param x - tile X coordinate + * @comp Crafty.diamondIso + * @sign public int Crafty.centerAt.getZAtLoc(number x, number y, number layer) + * @param X - tile X coordinate * @param Y - tile Y coordinate - @ @param layer - tile layr + * @param layer - tile layer * Gets the correct Z coordinate to place this tile on so that it renders * properly in front of and behind other grid entities. * You might call this method if you are having an entity move across the top of the * grid and need to interpolate between two sides. This is the motivation behind the * tileZSpacing property: tweens need to interpolate between values but have to round to - * the nearest integer. + * the nearest integer. Usually you call this at the starting and ending coordinates of a straight + * line path and interpolate between with tween. */ getZAtLoc: function(x,y,layer){ return this.layerZLevel * layer + this._tileZSpacing *(x+y); }, + + /* + * #Crafty.diamondIso.pos2px + * @comp Crafty.diamondIso + * @sign [number x, number y] Crafty.diamondIso.pos2px(number x, number y) + * @param X - tile coordinate X + * @param Y - tile coordinate Y + * This returns the correct coordinates to place the + * object's top and left to fit inside the grid, which is + * NOT inside of the tile for an isometric grid. IF you + * want the top corner of the diamond add tile width/2, + * but it seemed easier to give the same coords which you would + * use to set the tile's attributes. + */ pos2px: function (x, y, layer,height) { - /* This returns the correct coordinates to place the - object's top and left to fit inside the grid, which is - NOT inside of the tile for an isometric grid. IF you - want the top corner of the diamond add tile width/2 */ layer = layer || 0; height= height || 0; offset = -1*(this._tile.height * (2*(height-1) + layer)); @@ -223,10 +236,15 @@ Crafty.extend({ y: this.y + ((x + y) * this._tile.height / 2) + offset }; }, - px2pos: function (left, top) { - /* This returns the x/y coordinates on z level 0. - @TODO add a specifying z level + /* + * #Crafty.diamondIso.px2pos + * @comp Crafty.diamondIso + * @sign [number x, number y] Crafty.diamondIso.px2pos(number x, number y) + * @param X - canvas/DOM x coordinate + * @param Y - canvas/DOM y coordinate + * This returns the tile coordinates that this point on the game board is inside of (on layer 0). */ + px2pos: function (left, top) { var v1 = (top - this.y)/this._tile.height; var v2 = (left - this.x)/this._tile.width; var x = v1+v2; @@ -244,7 +262,18 @@ Crafty.extend({ getTileDimensions: function(){ return {w:this._tile.width,h:this._tile.height}; }, + /* + * #Crafty.diamondIso.getTiles + * @comp Crafty.diamondIso + * @sign Tile[] Crafty.diamondIso.getTiles(number x, number y, number z) + * @param X - tile X coordinate + * @param Y - tile Y coordinate + * @param Z - tile layer coordinate + * Returns an array containing all entities at the current location on the grid. + * + */ getTiles: function(x,y,z){ + return this._grid[x][y][z]; }, _getTraversableNeighbors: function(p){ @@ -263,6 +292,17 @@ Crafty.extend({ } return points; }, + /* + * #Crafty.diamondIso.findPath + * @comp Crafty.diamondIso + * @sign GridLoc[] Crafty.diamondIso.findPath([x1,y1],[x2,y2]) + * @param [x1,y1] - Starting point + * @param [x2,y2] - Ending point + * Finds a path that an entity on layer 1 would use to path from the start to the end. + * The following blocks the path: + * - Entities on the grid that have the component "Obstacle" + * - An empty tile on layer 0 + */ findPath: function(start,end){ if (this._collisionMap[end[0]][end[1]]){ return undefined; @@ -317,4 +357,4 @@ Crafty.extend({ } } -}); \ No newline at end of file +});