From dd6a4e79d45befd1597b560d0faa8930a924c26e Mon Sep 17 00:00:00 2001 From: Quinton Ashley Date: Tue, 3 Jan 2023 13:46:08 -0500 Subject: [PATCH] 3.4.13 --- p5.play.js | 303 ++++++++++++++++++++++++++++++++------------------- package.json | 2 +- 2 files changed, 194 insertions(+), 111 deletions(-) diff --git a/p5.play.js b/p5.play.js index 4110e59f..2f9b9c90 100644 --- a/p5.play.js +++ b/p5.play.js @@ -3,29 +3,21 @@ * * @version 3.4 * @author quinton-ashley - * @year 2022 + * @year 2023 * @license gpl-v3-only * @descripton p5.play is a 2D game engine that uses planck (Box2D) to simulate * physics and provides sprites, a tile system, input handling, and animations! - * - * Created by Quinton Ashley @qashto, 2022 - * https://quintos.org - * - * Initiated by Paolo Pedercini @molleindustria, 2015 - * https://molleindustria.org/ */ p5.prototype.registerMethod('init', function p5PlayInit() { - const log = console.log; // shortcut - this.log = console.log; + if (typeof window.planck == 'undefined') { + throw new Error('planck.js must be loaded before p5.play'); + } // store a reference to the p5 instance that p5play is being added to let pInst = this; - // change the angle mode to degrees - this.angleMode(p5.prototype.DEGREES); - if (typeof window.planck == 'undefined') { - throw new Error('planck.js must be loaded before p5.play'); - } + const log = console.log; // shortcut + this.log = console.log; const pl = planck; // set the velocity threshold to allow for slow moving objects @@ -43,6 +35,9 @@ p5.prototype.registerMethod('init', function p5PlayInit() { this.p5play.mouseSprites = []; this.p5play.standardizeKeyboard = false; + // change the angle mode to degrees + this.angleMode(p5.prototype.DEGREES); + // scale to planck coordinates from p5 coordinates const scaleTo = ({ x, y }, tileSize) => new pl.Vec2((x * tileSize) / plScale, (y * tileSize) / plScale); const scaleXTo = (x, tileSize) => (x * tileSize) / plScale; @@ -126,8 +121,6 @@ p5.prototype.registerMethod('init', function p5PlayInit() { * * let line = new Sprite(x, y, [length, angle]); * - * let chain = new Sprite(x, y, [length0, angle0, length1, angle1]); - * * @class Sprite * @constructor * @param {String|SpriteAnimation|p5.Image} [aniName|ani|image] @@ -143,9 +136,9 @@ p5.prototype.registerMethod('init', function p5PlayInit() { */ class Sprite { constructor(x, y, w, h, collider) { - this.idNum = pInst.world.spritesCreated; - pInst.world.spritesCreated++; this.p = pInst; + this.idNum = this.p.world.spritesCreated; + this.p.world.spritesCreated++; let args = [...arguments]; @@ -839,9 +832,10 @@ p5.prototype.registerMethod('init', function p5PlayInit() { } /** + * EXPERIMENTAL! This function is incomplete and will be changed. + * * Adds a joint between this sprite and another sprite. * - * @method addJoint * @param {Sprite} spriteB the sprite to add a joint to * @param {String} [type] the type of joint * @param {Object} [props] the joint options @@ -1215,8 +1209,7 @@ p5.prototype.registerMethod('init', function p5PlayInit() { /** * Use .layer instead. * - * @deprecated - * @property depth + * @deprecated depth */ get depth() { console.warn('sprite.depth is deprecated, use sprite.layer instead'); @@ -1393,8 +1386,7 @@ p5.prototype.registerMethod('init', function p5PlayInit() { /** * Use .static instead. * - * @deprecated - * @property immovable + * @deprecated immovable */ get immovable() { console.warn('sprite.immovable is deprecated, use sprite.static instead'); @@ -1951,8 +1943,8 @@ p5.prototype.registerMethod('init', function p5PlayInit() { /** * Resizes the collider of the sprite. * - * @param {*} scalars - * @returns + * @private + * @param {*} scalars The x and y scalars to resize the collider by. */ _resizeCollider(scalars) { if (!this.body) return; @@ -1973,18 +1965,12 @@ p5.prototype.registerMethod('init', function p5PlayInit() { } } - _isPoly(vecs) { - let first = vecs[0]; - let last = vecs[vecs.length - 1]; - return first.x; - } - /** * Validate convexity. * * @private * @param vecs {Array} an array of planck.Vec2 vertices - * @returns true if valid + * @returns true if the polygon is convex */ _isConvexPoly(vecs) { loopk: for (let k = 0; k < 2; k++) { @@ -2255,8 +2241,6 @@ p5.prototype.registerMethod('init', function p5PlayInit() { } /** - * EXPERIMENTAL implementation for beta testing! - * * Apply a force that is scaled to the sprite's mass. * * @method applyForce @@ -2283,12 +2267,11 @@ p5.prototype.registerMethod('init', function p5PlayInit() { } /** - * Deprecated: use sprite.vel instead. + * Deprecated: set sprite.vel instead. * * Sets the velocity vector. * - * @method setVelocity - * @deprecated + * @deprecated setVelocity * @param {Number} vector|x vector or horizontal velocity * @param {Number} y vertical velocity * @example @@ -2316,8 +2299,7 @@ p5.prototype.registerMethod('init', function p5PlayInit() { * If direction is not supplied and there is no current velocity, the * current rotation angle used for the direction. * - * @method setSpeed - * @deprecated + * @deprecated setSpeed * @param {Number} speed Scalar speed * @param {Number} [direction] angle */ @@ -2540,7 +2522,7 @@ p5.prototype.registerMethod('init', function p5PlayInit() { * Pushes the sprite toward a point. * The force is added to the current velocity. * - * Legacy method, use attract, move, or moveTowards instead. + * Legacy method, use moveTo or moveTowards instead. * * @deprecated * @param {Number} magnitude Scalar speed to add @@ -2779,7 +2761,8 @@ p5.prototype.registerMethod('init', function p5PlayInit() { _changeAni(label) { let ani = this.animations[label]; if (!ani) { - for (let g of this.groups) { + for (let i = this.groups.length - 1; i >= 0; i--) { + let g = this.groups[i]; ani = g.animations[label]; if (ani) { ani = ani.clone(); @@ -2835,11 +2818,6 @@ p5.prototype.registerMethod('init', function p5PlayInit() { } } - /** - * Alias for collides - * - * @method collide - */ collide(target, callback) { return this.collides(target, callback); } @@ -2914,11 +2892,6 @@ p5.prototype.registerMethod('init', function p5PlayInit() { this._overlap[target] = true; } - /** - * Alias for overlaps - * - * @method overlap - */ overlap(target, callback) { return this.overlaps(target, callback); } @@ -2987,8 +2960,7 @@ p5.prototype.registerMethod('init', function p5PlayInit() { /** * Use sprite.animation.name instead. * - * @deprecated - * @method getAnimationLabel + * @deprecated getAnimationLabel * @returns the name of the sprite's current animation */ getAnimationLabel() { @@ -3148,10 +3120,10 @@ p5.prototype.registerMethod('init', function p5PlayInit() { this.rotation = 0; this._scale = new Scale(); - parent.addAni(this); - if (args.length == 0 || typeof args[0] == 'number') return; + parent.addAni(this); + // sequence mode if ( args.length == 2 && @@ -4097,11 +4069,6 @@ p5.prototype.registerMethod('init', function p5PlayInit() { } } - /** - * Alias for collides. - * - * @method collide - */ collide(target, callback) { return this.collides(target, callback); } @@ -4181,11 +4148,6 @@ p5.prototype.registerMethod('init', function p5PlayInit() { this._overlap[target] = true; } - /** - * Alias for overlaps. - * - * @method overlap - */ overlap(target, callback) { return this.overlaps(target, callback); } @@ -4335,15 +4297,15 @@ p5.prototype.registerMethod('init', function p5PlayInit() { } /** - * Rotates the group around its centroid. + * EXPERIMENTAL! Subject to change in the future! * - * TODO experimental function, subject to change! + * Rotates the group around its centroid. * * @method orbit * @param {Number} amount Amount of rotation */ orbit(amount) { - console.warn('group.orbit is an experimental and subject to change in the future!'); + if (this.frame == 0) console.warn('group.orbit is experimental and is subject to change in the future!'); if (!this.centroid) this.resetCentroid(); this.orbitAngle += amount; let angle = this.orbitAngle; @@ -4363,8 +4325,7 @@ p5.prototype.registerMethod('init', function p5PlayInit() { /** * Gets the member at index i. * - * @deprecated - * @method get + * @deprecated get * @param {Number} i The index of the object to retrieve */ get(i) { @@ -4372,11 +4333,18 @@ p5.prototype.registerMethod('init', function p5PlayInit() { return this[i]; } + /** + * Check if a sprite is in the group. + * + * @method includes + * @param {Sprite} sprite + * @return {Number} index of the sprite or -1 if not found + */ + /** * Use group.includes(sprite) instead. * - * @deprecated - * @method contains + * @deprecated contains * @param {Sprite} sprite The sprite to search * @return {Number} Index or -1 if not found */ @@ -4417,9 +4385,13 @@ p5.prototype.registerMethod('init', function p5PlayInit() { } /** - * Same as group.length - * - * @method size + * @property length + * @return {Number} The amount of sprites in the group + */ + + /** + * Alias for group.length + * @deprecated size */ size() { return this.length; @@ -4530,7 +4502,7 @@ p5.prototype.registerMethod('init', function p5PlayInit() { /** * Returns the highest depth in a group * - * @method maxDepth + * @deprecated maxDepth * @return {Number} The depth of the sprite drawn on the top */ maxDepth() { @@ -4546,7 +4518,7 @@ p5.prototype.registerMethod('init', function p5PlayInit() { /** * Returns the lowest depth in a group * - * @method minDepth + * @deprecated minDepth * @return {Number} The depth of the sprite drawn on the bottom */ minDepth() { @@ -4559,6 +4531,11 @@ p5.prototype.registerMethod('init', function p5PlayInit() { }, Infinity); } + /** + * Draws all the sprites in the group. + * + * @method draw + */ draw() { let g = [...this]; g.sort((a, b) => a.layer - b.layer); @@ -4923,6 +4900,12 @@ p5.prototype.registerMethod('init', function p5PlayInit() { x: this.p.mouseX, y: this.p.mouseY }; + /** + * @property {Number} mouse.x + */ + /** + * @property {Number} mouse.y + */ /** * True if the camera is active. @@ -4943,28 +4926,49 @@ p5.prototype.registerMethod('init', function p5PlayInit() { if (y) this.y = y; } + /** + * The camera's position. {x, y} + * + * @property pos + * @type {Object} + */ get pos() { return this._pos; } - + /** + * The camera's position. Alias for pos. + * + * @property position + * @type {Object} + */ get position() { return this._pos; } + /** + * The camera x position. + * + * @property x + * @type {Number} + */ get x() { return this._pos.x; } - set x(val) { this._pos.x = val; this.bound.min.x = this.x - this.p.world.hw / this.zoom - 100; this.bound.max.x = this.x + this.p.world.hw / this.zoom + 100; } + /** + * The camera y position. + * + * @property y + * @type {Number} + */ get y() { return this._pos.y; } - set y(val) { this._pos.y = val; this.bound.min.y = this.y - this.p.world.hh / this.zoom - 100; @@ -5003,6 +5007,7 @@ p5.prototype.registerMethod('init', function p5PlayInit() { } //end camera class /** + * Used internally to find a contact callback between two sprites. * * @private * @param {String} type "collide" or "overlap" @@ -5041,6 +5046,8 @@ p5.prototype.registerMethod('init', function p5PlayInit() { /** * This planck function should've be named "shouldContact", because that's what * it actually decides. + * + * Here we override it to allow for overlap events between sprites. */ pl.Fixture.prototype.shouldCollide = function (that) { // should this and that produce a contact event? @@ -5133,7 +5140,7 @@ p5.prototype.registerMethod('init', function p5PlayInit() { /** * Look at the p5.play reference pages before reading these docs. * - * https://p5play.org/learn/sprite.html + * https://p5play.org/learn * * @class p5.play */ @@ -5966,7 +5973,7 @@ canvas { }; /** - * + * @private * @param {String} func is the name of the function the error was thrown in * @param {Number} errorNum is the error's code number * @param {Array} e is an array with references to the cause of the error @@ -6050,6 +6057,28 @@ canvas { */ this.camera = new Camera(); + /** + * Get user input from the mouse. + * Stores the state of the left, center, or right mouse buttons. + * + * @property mouse + */ + /** + * Get user input from the keyboard. + * + * @property kb + */ + /** + * Alias for kb. + * + * @property keyboard + */ + /** + * Get user input from game controllers. + * + * @property contro + */ + /** * Look at the Input reference pages before reading these docs. * @@ -6081,6 +6110,12 @@ canvas { this.holdThreshold = 12; } + /** + * Initializes the input's values to zero. + * + * @private + * @method init + */ init(inputs) { for (let inp of inputs) { this[inp] = 0; @@ -6090,45 +6125,76 @@ canvas { /** * Attempt to auto-correct the user's input. Inheriting classes * override this method. + * + * @private + * @method ac */ ac(inp) { return inp; } + /** + * @method presses + * @param {string} inp + */ presses(inp) { inp ??= this.default; if (this[inp] === undefined) inp = this.ac(inp); return this[inp] == 1 || this[inp] == -2; } + /** + * @method pressing + * @param {string} inp + */ pressing(inp) { inp ??= this.default; if (this[inp] === undefined) inp = this.ac(inp); return this[inp] > 0 || this[inp] == -2; } + /** + * @method pressed + * @param {string} inp + */ pressed(inp) { return this.released(inp); } + /** + * @method holds + * @param {string} inp + */ holds(inp) { inp ??= this.default; if (this[inp] === undefined) inp = this.ac(inp); return this[inp] == this.holdThreshold; } + /** + * @method holding + * @param {string} inp + */ holding(inp) { inp ??= this.default; if (this[inp] === undefined) inp = this.ac(inp); return this[inp] >= this.holdThreshold; } + /** + * @method held + * @param {string} inp + */ held(inp) { inp ??= this.default; if (this[inp] === undefined) inp = this.ac(inp); return this[inp] == -3; } + /** + * @method released + * @param {string} inp + */ released(inp) { inp ??= this.default; if (this[inp] === undefined) inp = this.ac(inp); @@ -6167,12 +6233,33 @@ canvas { this.draggable = false; this.isOnCanvas = false; this.active = false; + + /** + * The mouse's x position. + * @property x + * @type {number} + */ + this.x; + + /** + * The mouse's y position. + * @property y + * @type {number} + */ + this.y; } + /** + * The mouse's position. + * @property pos + */ get pos() { return this._position; } - + /** + * The mouse's position. Alias for pos. + * @property position + */ get position() { return this._position; } @@ -6185,6 +6272,11 @@ canvas { return inp; } + /** + * @method dragging + * @param {string} inp + * @returns {boolean} true if the mouse is being dragged while holding the input + */ dragging(inp) { inp ??= this.default; this.draggable = true; @@ -6192,11 +6284,6 @@ canvas { } } - /** - * Stores the state of the left, center, or right mouse buttons. - * - * @property mouse - */ this.mouse = new Mouse(); class SpriteMouse extends Mouse { @@ -6205,14 +6292,26 @@ canvas { this.hover = 0; } + /** + * @method hovers + * @returns {boolean} true on the first frame that the mouse is over the sprite + */ hovers() { return this.hover == 1; } + /** + * @method hovering + * @returns {boolean} true if the mouse is hovering over the sprite + */ hovering() { return this.hover > 0; } + /** + * @method hovered + * @returns {boolean} true on the first frame that the mouse is no longer over the sprite + */ hovered() { return this.hover == -1; } @@ -6319,26 +6418,6 @@ canvas { } } - /** - * - * - * @property kb (keyboard) - * @example - // presses - if (kb.presses('x')) { - player.jump(); - } - - // holds - if (kb.holds('e')) { - player.chargeAttack(); - } - - // released - if (kb.released('q')) { - player.slide(); - } - */ this.kb = new KeyBoard(); this.keyboard = this.kb; @@ -6361,8 +6440,7 @@ canvas { /** * Obsolete: Use kb.pressing(key) instead. * - * @obsolete - * @method keyIsDown + * @obsolete keyIsDown * @param {String} key */ this.keyIsDown = function (keyCode) { @@ -6371,6 +6449,11 @@ canvas { ); }; + /** + * @private getKeyFromCode + * @param {*} e keyboard event + * @returns key name + */ function getKeyFromCode(e) { let code = e.code; if (code.length == 4 && code.slice(0, 3) == 'Key') { diff --git a/package.json b/package.json index cb2502e4..f7a631ff 100644 --- a/package.json +++ b/package.json @@ -33,5 +33,5 @@ "version": "git add -A", "postversion": "git push" }, - "version": "3.4.12" + "version": "3.4.13" }