• Content Count

  • Joined

  • Last visited

Everything posted by lucbloom

  1. lucbloom

    Center BitmapText

    Regardless of implementation concept, all objects that have a clear width & height should have an anchor point, *especially* when the TTF counterpart *does* have one. If you use it, and I use it, and I've seen other people use it, it's probably u useful feature. I don't see what there is to confuse? You'd use a property on an object the same way and get the same results for 2 kinds of objects. For me, this is the opposite of confusing. It would be confusing if I'd have to set one property on a TTF object and do something else on a BM font label object to get the same thing. PS: Would you mind positing your solution?
  2. lucbloom

    Center BitmapText

    In all seriousness, regardless of what internal structure an object has, I want to set its anchor point. Imagine a list of numbers, for instance a high score list. I want the back of the numbers to align. Now if these labels are TTF text or bitmap font texts are not important to me. I want to be able to align them the same way. In my vision, "align" doesn't address this issue because that specifies how the text should be aligned _within_ the label and therefore only has effect on labels with *multiple lines*. As one game engine developer (c++) to another (JS), I highly recommend adding the "anchor" property on every type of visual world object with a width & height. PS: how can I change the 'Newbie' status above my profile picture without having to make too much posts? :-)
  3. lucbloom

    Center BitmapText

    Better solution: Paste this somewhere in your 'extensions.js' (after loading phaser-min.js) and it'll work. Object.defineProperty(Phaser.BitmapText.prototype, 'anchor', { get: function() { return this._anchor; }, set: function(anchor) { this._anchor = anchor; this.dirty = true; this.updateTransform(); }});PIXI.BitmapText.prototype.updateText = function(){ var data = PIXI.BitmapText.fonts[this.fontName]; if (!data) { console.error("Bitmap font not found: '" + this.fontName + "'"); return; } var pos = new PIXI.Point(); var prevCharCode = null; var chars = []; var maxLineWidth = 0; var lineWidths = []; var line = 0; var scale = this.fontSize / data.size; for(var i = 0; i < this.text.length; i++) { var charCode = this.text.charCodeAt(i); if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) { lineWidths.push(pos.x); maxLineWidth = Math.max(maxLineWidth, pos.x); line++; pos.x = 0; pos.y += data.lineHeight; prevCharCode = null; continue; } var charData = data.chars[charCode]; if(!charData) continue; if(prevCharCode && charData[prevCharCode]) { pos.x += charData.kerning[prevCharCode]; } chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); pos.x += charData.xAdvance; prevCharCode = charCode; } lineWidths.push(pos.x); maxLineWidth = Math.max(maxLineWidth, pos.x); var lineAlignOffsets = []; for(i = 0; i <= line; i++) { var alignOffset = 0; if( === 'right') { alignOffset = maxLineWidth - lineWidths[i]; } else if( === 'center') { alignOffset = (maxLineWidth - lineWidths[i]) / 2; } lineAlignOffsets.push(alignOffset); } var lenChildren = this._pool.length; var lenChars = chars.length; var tint = this.tint || 0xFFFFFF; for(i = 0; i < lenChars; i++) { var c = this._pool[i]; if (c) c.setTexture(chars[i].texture); // check if got one before. else { c = new PIXI.Sprite(chars[i].texture); // if no create new one. this._pool.push(c); } c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; c.position.y = chars[i].position.y * scale; c.scale.x = c.scale.y = scale; c.tint = tint; if (!c.parent) this.addChild(c); } // remove unnecessary children. // and put their into the pool. for (var i = lenChars; i < this._pool.length; ++i) { this.removeChild(this._pool[i]); } /** * [read-only] The width of the overall text, different from fontSize, * which is defined in the style object * * @property textWidth * @type Number */ this.textWidth = maxLineWidth * scale; /** * [read-only] The height of the overall text, different from fontSize, * which is defined in the style object * * @property textHeight * @type Number */ this.textHeight = (pos.y + data.lineHeight) * scale; if (this._anchor) { for(i = 0; i < lenChars; i++) { var c = this._pool[i]; c.position.x -= this.textWidth * this._anchor.x; c.position.y -= this.textHeight * this._anchor.y; } }};
  4. lucbloom

    Center BitmapText

    Here is the solution: Object.defineProperty(Phaser.BitmapText.prototype, 'anchor', { get: function() { return this._anchor; }, set: function(anchor) { this._anchor = anchor; this.dirty = true; this.updateTransform(); if (!this.textBitmapSpritesParent) { this.textBitmapSpritesParent = new Phaser.Group(; this.addChild(this.textBitmapSpritesParent); } this.textBitmapSpritesParent.x = -this.textWidth * this.anchor.x; this.textBitmapSpritesParent.y = -this.textHeight * this.anchor.y; for (var i = 0; i < this.children.length;) { if (this.children[i] == this.textBitmapSpritesParent) { ++i; } else { this.textBitmapSpritesParent.add(this.children[i]); } } }}); PS: rich, this would work better (more reliable) if BitmapText would use an internal dedicated array for its Glyph sprites.
  5. I was googling how to add a SpriteBatch via game.add... Guess I'll look into the source :-) It's game.add.spriteBatch(parent, name, addToStage)
  6. That framework is really cool. I guess I had to get used to how loose JavaScript actually is, combining frameworks like that. Now my code is: if (!halo.timeline) { halo.timeline = new TimelineLite(); halo.timeline .to(halo.scale, 0, {x:0, y:0}) .to(halo, 0, {alpha:1}) .to(halo.scale, duration/1000, {x:scale, y:scale, ease:Bounce.easeOut}) .to(halo, duration*2/1000, {alpha:0}); } halo.timeline.restart();Finishing, reverting and cancelling is also in there, so yeah, exactly what I wanted. TimelineLite.prototype.finish = function(){ this.progress(1, false);}
  7. Thanks lewster32, I'm going to look into that one.
  8. Besides the necessary game.tweens.stop("halo bounce");we can also have: game.tweens.finish("halo bounce");which would unroll all the tweens in the whole tween tree so that all objects are brought into the end phase instantly.
  9. I have a question about the tweening system in Phaser. If I perform a complex animation with multiple sprites (or a simple animation involving only 1 sprite but with scale and alpha) I have to write something like this: this.halo.scale = {x:0, y:0}; this.halo.alpha = 1; if (this.halo.scaleTween) { this.halo.scaleTween.stop(); } if (this.halo.alphaTween) { this.halo.alphaTween.stop(); this.halo.alphaTween = null; } this.halo.scaleTween = game.add.tween(this.halo.scale) this.halo.scaleTween .to({x:1, y:1}, 1000, Phaser.Easing.Bounce.Out) .start() .onComplete.addOnce(function() { this.halo.alphaTween = game.add.tween(this.halo).to({alpha:0}, 1000).start(); }, this);When I'd rather write something like this:game.stop.tween("halo bounce"); // No error if not foundgame.add.tween("halo bounce") .then(this.halo.scale, {x:1, y:1}, 1000, Phaser.Easing.Bounce.Out) .then(this.halo, {alpha:0}, 1000) .start();Is this sort of system possible at all? Am I using the existing Phaser API wrong? Additionally, in our C++ engine, we had an 'also' function as well. This would allow you to add new tweens in the dot chain, but they got added at the same point as the previous one:game.add.tween("game over") // The name is optional. Anonymous tweens are the default .then(1000) // Delay before starting .then(, {alpha:1}, 100) .also(, {x:1, y:1}, 100) // This one runs ALONGSIDE the 'alpha' tween .then(function() { this.openScoreScreen(this.stats); }, this); // This one runs at the END of the 'scale' tweenIf this system looks exciting (I think it is, we've shipped a lot of triple-A casual games on all platforms (except HTML5) with it...) I would be happy to work together to add it to Phaser. Luc Bloom
  10. I have fixed a bug. This is how to repro it: At startup: this.sprite.loadTexture("walk.png"); // Sprite sheet 3x4 frames Some time later: this.sprite.loadTexture("dead.png"); // Single frame My game sets this.sprite.frame each update. If the object is 'dead', the frame number is 0. The BUG is: the old frameData in this.sprite.animations resets the texure to walk.png's first frame. I SOLVED this by executing this.animations.loadFrameData(null); in the "cache.isSpritesheet == false" part of Phaser.Sprite.prototype.loadTexture