nkholski Posted September 26, 2014 Share Posted September 26, 2014 I just finished an effect to make enemies in my game explode into pieces when getting killed. What it does is to create an emitter at the coordinates of the enemy bursting subparts extracted from the sprite. I think the result was kind of cool so I spent some extra time cleaning up the code a bit so I can contribute with something (after being given so much from Phaser and the forums). Edit: Basic online demo "Before and after" After the preloader finishes it allows you to define explosions (entityExplode.setup) based on sprites in a SpriteAtlas (I'm using TexturePacker). The entityExplode.setup will add references to subparts of a selected subsprite but not add or alter any of the imagedata. When defining a new state you need to call entityExplode.init in Create. If the setup was correctly done you will be able to explode a sprite with entityExplode.play (you need to remove the sprite yourself after calling play if you don't want both the sprite and the explosion to show). If you call entityExplode.bounceAndFade in your state's update function the pieces will bounce on a tilemap layer and fade away before being removed. Any suggestion on how to improve this is appreciated. You are free to use and modify the code any way you want. Notes:* A lot of hard coded values fits my game well, but is probably not the best fit for everyone (such as size of the parts, speed of the emitter or number of parts to send out).* I haven't checked out the Atlas object-stuff enough to know what everything does, I'm just cloning the original frame and changes the things that makes this work (including duplicating UUID). * There is for sure things that could improve the emitter. I would love to find a way to get the pieces to stop sliding on the ground and I would prefer that the stopped their rotation once on ground.entityExplode = { init: function (that) { // Called from Create for any state that will use entityExplode that.explosionEmitters = game.add.group(); }, setUp: function (explodeName, frameName, atlasName, fragmentSize) { // Can be called anytime after Preloader finishes (at least after the atlas json is loaded) // Prepare a possible explosion so that can be called by the play method later. // explodeName = name of the explosion to create // frameName = frame name in atlas to build from (I only define one explosion per entity since the sprite get distorted and it doesn't matter much if the entity was jumping or walking or something else when exploding.) // atlasName = name of atlas to use // fragmentSize = size of fragment in pixels (default = 8) var sourceFrame = false; var xcount, ycount, temp; var frameNames = []; if (!("explosionFrames" in this)) { this.explosionFrames = []; } if (explodeName in this.explosionFrames) { return; // No double-trouble } if (frameName in game.cache._images[atlasName].frameData._frameNames) { sourceFrame = game.cache._images[atlasName].frameData._frames[game.cache._images[atlasName].frameData._frameNames[frameName]]; } else { console.log("ERROR! FrameName not found"); return } if (typeof (fragmentSize) === "undefined") { fragmentSize = 8; } xcount = Math.floor(sourceFrame.width / fragmentSize); ycount = Math.floor(sourceFrame.height / fragmentSize); temp = JSON.parse(JSON.stringify(sourceFrame)); // Kind of a hacky way to copy an object for (var x = 0; x < xcount; x++) { for (var y = 0; y < ycount; y++) { temp.name = explodeName + "_explode" + (x * ycount + y); temp.x = sourceFrame.x + x * fragmentSize; temp.y = sourceFrame.y + y * fragmentSize; temp.width = ((temp.x + fragmentSize) > (sourceFrame.x + sourceFrame.width)) ? (sourceFrame.x + sourceFrame.width - temp.x) : fragmentSize; // stay within the sprite-size temp.height = ((temp.y + fragmentSize) > (sourceFrame.y + sourceFrame.height)) ? (sourceFrame.y + sourceFrame.height - temp.y) : fragmentSize; // Add the fragment to the atlas data (this works, but it also just duplicates a lot of values I don't know what they do) game.cache._images[atlasName].frameData._frameNames[temp.name] = game.cache._images[atlasName].frameData._frames.length; game.cache._images[atlasName].frameData._frames.push(JSON.parse(JSON.stringify(temp))); frameNames.push(temp.name); } } this.explosionFrames[explodeName] = { atlas: atlasName, frames: frameNames // A list of framenames to select from when doing an explosion! } game.explosionFrames = this.explosionFrames; }, play: function (entity, explodeName, that, hitFrom) { // Called to initate explosion of entity // entity is the object to explode, typically sprite // explodeName is a explosion previously defined in setUp // hitFrom is optional, from right or left (could be replaced by sprite object and then calculate the direction of explosion from velocity of impacting bullet using trigometry but I don't need that) var explode = game.add.emitter(entity.x, entity.y, 100); // Add the explosion at the entity coordinates if (!(explodeName in this.explosionFrames)) { console.log("Error: Nothing to explode!"); return; } explode.bounce.setTo(0.5, 0.5); if (hitFrom === "right") { explode.setXSpeed(-100, -10); } else if (hitFrom === "left") { explode.setXSpeed(10, 100); } else { explode.setXSpeed(-50, 50); } explode.setYSpeed(-100, -200); explode.makeParticles(game.explosionFrames[explodeName].atlas, game.explosionFrames[explodeName].frames, 100, 250, 100, true); explode.particleFriction = 10; // Makes no difference! explode.start(true, 2000, 1, 20, 20) game.time.events.add(Phaser.Timer.SECOND * 3, function () { explode.destroy(); }); that.explosionEmitters.add(explode); }, bounceAndFade: function (that, tilemapLayer) { // Called from update for (var i in that.explosionEmitters.children) { that.physics.arcade.collide(that.explosionEmitters.children[i], tilemapLayer); that.explosionEmitters.children[i].forEachAlive(function (p) { p.alpha = p.lifespan / that.explosionEmitters.children[i].lifespan; }); } }} TNelson and quiphop 2 Link to comment Share on other sites More sharing options...
stupot Posted September 27, 2014 Share Posted September 27, 2014 Looks great, an online demo would be x10 better to see exactly what it does. Jsfiddle, something like that? Link to comment Share on other sites More sharing options...
nkholski Posted September 27, 2014 Author Share Posted September 27, 2014 I tried jsFiddle but couldn't get it to load the spriteAtlas properly. I will try to have a demo up in a couple of hours. Link to comment Share on other sites More sharing options...
nkholski Posted September 27, 2014 Author Share Posted September 27, 2014 Just uploaded a basic demo: http://niklasberg.se/entityExplode/index.html quiphop 1 Link to comment Share on other sites More sharing options...
stupot Posted September 27, 2014 Share Posted September 27, 2014 A picture paints a 1000 words as they say, a demo paints a 1000 more! That looks pretty good, I can see myself using that somehow. The advantage of jsfiddle would be that you don't have the burden of maintaing the link. If I were you, I'd put it up on github and assign a license. nkholski 1 Link to comment Share on other sites More sharing options...
Binary Moon Posted September 28, 2014 Share Posted September 28, 2014 Looks really nice - thanks for the share Link to comment Share on other sites More sharing options...
valueerror Posted September 28, 2014 Share Posted September 28, 2014 nice.. could this be done with a normal sprite from a single png too? Link to comment Share on other sites More sharing options...
nkholski Posted September 28, 2014 Author Share Posted September 28, 2014 Yes. I think so, but not without modifying the code quite a lot and I don't think I will add support for it. If it's a sprite sheet I think you could copy the content of game.cache._images[nameofimage] and change frameHeight and frameWidth to a size that can divide the sprite to an even number. If it's just one image I guess you could try to reproduce a spriteAtlas or the method I just suggested and set the url to match whatever the image you want to explode refers to. I'm not sure if any of this will work, and I will stick to my spriteAtlas solution for myself. Link to comment Share on other sites More sharing options...
ForgeableSum Posted February 25, 2016 Share Posted February 25, 2016 This looks neat, but I can't read your code because the comments are messing up any beautifier I try to use. Also, your demo links aren't working. Any chance you can post a beautified version of the code or a version with comments stripped out? Link to comment Share on other sites More sharing options...
nkholski Posted February 25, 2016 Author Share Posted February 25, 2016 Thanks. I uploaded the latest version I could find on my hard disk to Git. It's the unmodified version from that one I used in "Robotic Conflict" (http://dev.niklasberg.se/roboticConflict/). It will contain bugs for sure and probably some ugly hacks just to get it to work. This version can blow up both sprites and tiles on a tilemap, and requires Phaser 2.4.x (The code I posted in the first post will not work in Phaser 2.4+ because of changes on how cache works). If there is a demand I might update it and make a proper repository. Gist: https://gist.github.com/nkholski/533cfbf0272a3c41273c quiphop 1 Link to comment Share on other sites More sharing options...
Recommended Posts