Jonny Shaw

  • Content Count

  • Joined

  • Last visited

Everything posted by Jonny Shaw

  1. Hi does anyone know of an easy way to check gpu drawcalls either via the console or a browser plugin? Having a few issues with Spine performance on iOS/Mac and wondering whether it would be worthwhile to merge some atlases. Thanks in advance!
  2. Hah, yeah the thing is with these things, you code, you test, rinse repeat and after a while you lose all sight of whether it's actually any good or not 😆 With the lobby I really wanted to try and make it feel more like a full native game experience. It's not really important in a lot of slots I don't think, but with the needs of this for the leaderboard and IAP's it kind of warranted it really.
  3. Thanks taoprox! I worked solo on this so it did take a good few months in total. The casino has backend developers who were working on a framework that was built around the game, so they were there to help when I maybe struggling with something & of course the good folks on here too 😊 Artwork I generally find easier & always enjoy. Coding I have a very love-hate relationship with, love the eureka moments, but can often feel far & few between! 🤣
  4. Awesome thanks! Oops, not the best choice of screenshots I'll agree, the video is more for my portfolio than as a game trailer which is why it's presented that way. Have updated with more gameplay shots 😊
  5. Hi all, finished this commissioned slot game last year, but just sorting some bits out for my site so thought it maybe worth a post. Artwork & Animation I put most artwork together with a mix of 3DCoat, Blender and Photoshop to finish. Spine was used for the symbol animations, external shop & bonus round animations. GSAP was used for the UI and a few pieces in game. Development My background is more on artwork, but I have worked on the development side of things too, (I started off my freelance work as a UI Designer in Scaleform). Had worked on the previous two games for this client in PixiJS which were used as a testbed to learn the ropes. For the animation I really needed something tangible to work with, so it was decided I would put together a prototype for the game. There were a few things I would do differently now for optimisation, and have since changed in the next slot game I have been working on. PixiJS was quite easy to pick up, and felt very similar to as3 and Flash which I had used quite extensively before on Scaleform projects. One of the challenges I found in particular was that I wanted the game to be playable in both portrait & landscape. So all UI & UX had to conform to this, but was quite pleased on the solution I found for that. The UI was a bit more extensive than I think you'd normally find in slot games too, having leaderboards, a shop for bonus entry IAP's and a secondary UI for mobile deposits. Shoutouts Just want to thank all those on this forum that have helped me with a few things as well whilst I've been learning the ropes too - you've all been awesome and the activity on this forum I find quite incredible! Links Behance Post Prototype Demo Video
  6. Hi all! I've been floating around the forums for a few years now and didn't realise I hadn't posted a plug in here! 🤣 I'm Jonny Shaw, 35, & a freelance artist & designer, based in West Yorks, England. I have a background starting in UI design, but more recently have worked in 2D, 3D, animation, sculpting, & development too. Lately I've mainly been working on a lot of casino games, which also led into development with PixiJS, Spine & GSAP. The last of which ended up being a full game prototype (just minus the comms). Always on the lookout for interesting projects, so if you feel like my work may fit the bill, don't hesitate to give me a holla! Cheers 🍻 Jonny Shaw Website | Facebook | Behance | Artstation
  7. scrap that! had another look .uvs property has changed to regionUVs, works perfectly now! updateRewardFlag(bonusAmount, flagNumber){ window.Game.flags.createFlag(bonusAmount); let meshTexture = window.Game.flags.latestFlag(); let num ='rag1'); let slot =[num]; let attachment = slot.attachment; console.log(attachment); attachment.region.texture = meshTexture; attachment.updateUVs(); if(slot.currentMesh) { console.log(slot.currentMesh); slot.currentMesh.texture = meshTexture; slot.currentMesh.uvs = new Float32Array(attachment.regionUVs); slot.currentMesh.dirty = true; } }
  8. Hi sorry to bump this, but was something I've just been trying out and haven't been able to get it to work if anyone could help? Is this the correct way still to do this. I have an animation of a character with 3 different flags waving (as meshes) and need text on those flags, so thought it would be good to try and renderTexture out dynamically with the base png and text on top, then replace. rendererObject no longer seems to be a property - but have found texture under "region". With the below the texture doesnt appear updateRewardFlag(bonusAmount){ window.Game.flags.createFlag(bonusAmount); let meshTexture = window.Game.flags.latestFlag(); let num ='rag1'); let slot =[num]; let attachment = slot.attachment; attachment.region.texture = meshTexture; attachment.updateUVs(); if(slot.currentMesh !=null) { console.log(slot.currentMesh); slot.currentMesh.texture = meshTexture; slot.currentMesh.uvs = new Float32Array(attachment.uvs); slot.currentMesh.dirty = true; } } if I comment out as below it does appear but massively out of scale and rotated. updateRewardFlag(bonusAmount, flagNumber){ window.Game.flags.createFlag(bonusAmount); let meshTexture = window.Game.flags.latestFlag(); let num ='rag1'); let slot =[num]; let attachment = slot.attachment; attachment.region.texture = meshTexture; attachment.updateUVs(); if(slot.currentMesh !=null) { console.log(slot.currentMesh); slot.currentMesh.texture = meshTexture; //slot.currentMesh.uvs = new Float32Array(attachment.uvs); //slot.currentMesh.dirty = true; } } Any ideas greatly appreciated!
  9. perfect thanks, will stick to Container for now then, and try the other approach if I see any drops
  10. that's awesome thanks Ivan, will take a look at trying that out once this project is done, but might have to hold on for that one as I'm a bit behind already. For the moment I can either have 1 normal container for both emitters, or use 2 particle containers for each with one set to add. For now any idea on which of the two options may give better performance?
  11. Brilliant thanks! Guess that's what I must have been doing previously. One thing with this effect though is I have two emitters, a fire and smoke effect, whereby only the fire needs add, so it wouldn't work in this case. So do you think it would be better to have 2 particlecontainers with just the fire particlecontainer set to add or... just use one normal container for both?
  12. Hi, I've just noticed that the ParticleContainer doesn't seem to support blendModes. I thought previously it had worked when the tint property had been set to true, but may have imagined it. This still a current limitation?
  13. Have managed to get this working, but had to find some workarounds and not sure if it's a bit complex, and could be optimised further... Involved using a timer and a loop to emit manually, then track the last added fireball particles position (if I tried accessing as soon as it was emit, it would return a blank, because it seems emission rate of 0 even for one particle is not possible), so matched the delay to the emission rate and seems to work ok. I'll likely add the particles back into particle containers now to improve performance a bit too. TickerTimer is just a small util class I wrote that adds a callback function to the main app ticker with a delay (so works pretty much like setTimeout, but using the app ticker) Any further ideas greatly appreciated! import TickerTimer from "../utils/TickerTimer"; class Fireballs extends PIXI.Container{ constructor(){ super(...arguments); this.balls = []; this.trails = []; // Atlas... this.atlas = PIXI.loader.resources["./assets/fxAtlas.json"].textures; this.ballContainer = new PIXI.Container(); this.trailContainer = new PIXI.Container(); this.addChild(this.trailContainer); this.addChild(this.ballContainer); this.emitTimer = 0; this.emitRate = 6; this.fireballCount = 0; this.maxFireballs = 20; this.timer = new PIXI.ticker.Ticker(); this.timer.stop(); this.fireballs = new PIXI.particles.Emitter( this.ballContainer, [this.atlas["fireball1.psd"]], { "alpha": { list: [ {value:0, time:0}, {value:1, time:0.2}, {value:1, time:0.8}, {value:0, time:1} ], }, "scale": { list: [ {value:0, time:0}, {value:0.3, time:0.2}, {value:0.4, time:0.8}, {value:0.2, time:1} ], "minimumScaleMultiplier": 1 }, "color": { "start": "#ffffff", "end": "#ff6105" }, "speed": { "start": 800, "end": 1000, "minimumSpeedMultiplier": 1 }, "acceleration": { "x": 0, "y": this.randomRange(1000,2000) }, "maxSpeed": 1000, "startRotation": { "min": 160, "max": 380 }, "noRotation": false, "rotationSpeed": { "min": 500, "max": 2000 }, "lifetime": { "min": 1, "max": 1 }, "blendMode": "add", "frequency": 0.1, "emitterLifetime": 0.2, "maxParticles": 10, "pos": { "x": 0, "y": 0 }, "addAtBack": false, "spawnType": "point" } ); this.timer.add(this.emitLoop,this); this.timer.start(); } emitLoop(deltaTime){ this.emitTimer++; if(this.fireballCount < this.maxFireballs){ if(this.emitTimer >= this.emitRate){ this.emitTimer = 0; this.emitFireball(); } } else { this.timer.remove(this.emitLoop, this); this.emitTimer = 0; this.fireballCount = 0; } } randomRange(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } emitFireball(){ this.fireballCount++; if(this.fireballCount < this.maxFireballs){ this.fireballs.autoUpdate = true; this.fireballs.playOnce(this.fireballDestroyed.bind(this)); //this.fireballs.emit = true; let delayMe = new TickerTimer(this.timer, 0.2, this.createTrailSmoke.bind(this)); } } fireballDestroyed(ball){ this.balls.shift(); this.trails.shift(); } createTrailSmoke(){ let fireball = this.ballContainer.children[this.ballContainer.children.length-1]; // Get the last added fireball. if(fireball!=null){ let trailSmoke = this.createTrail(fireball.x, fireball.y,1); this.balls.push(fireball); this.trails.push(trailSmoke); window.Game.ticker.add(this.updateTrailSmoke, this); } } updateTrailSmoke(){ for(let i = 0; i < this.balls.length; i++){ this.trails[i].updateOwnerPos(this.balls[i].x, this.balls[i].y+20); } } createTrail(xPos, yPos, lifeSpan){ let trail = new PIXI.particles.Emitter( this.trailContainer, [this.atlas["smoke3.psd"]], { "alpha": { list: [ {value:0, time:0}, {value:1, time:0.2}, {value:0, time:1} ], }, "scale": { list: [ {value:0.2, time:0}, {value:0.1, time:0.2}, {value:0.4, time:1} ], "minimumScaleMultiplier": 1 }, "color": { list: [ {value:"#ffff5e", time:0}, {value:"#ff0000", time:0.2}, {value:"#333333", time:0.3}, {value:"#000000", time:1} ] }, "speed": { "start": 0, "end": 0, "minimumSpeedMultiplier": 1 }, "acceleration": { "x": 0, "y": 100 }, "maxSpeed": 0, "startRotation": { "min": 0, "max": 360 }, "noRotation": false, "rotationSpeed": { "min": 0, "max": 800 }, "lifetime": { "min": 0.6, "max": 0.8 }, "blendMode": "normal", "frequency": 0.008, "emitterLifetime": lifeSpan, "maxParticles": 200, "pos": { "x": xPos, "y": yPos }, "addAtBack": false, "spawnType": "point" } ); trail.autoUpdate = true; trail.playOnce(); return trail; } } export default Fireballs;
  14. Aha, silly me see gravity can be simulated with the acceleration, so will try that The only other issue I can see is accessing the fireball particles x,y position but hopefully children on the particle container, should give an option there
  15. Hi all, was just having a play with an effect for an explosion, and thought it would be cool to trial out some fireball style effects with some sort of simulated gravity. eg. 4 or 5 fireballs, with smoke trails behind.. Had a play but noticed that pixi particles doesn't really offer anything in terms of subemitters, unless I've missed it? So really been trying to find a workaround. I'm not so hot when it comes to the maths of any gravity, so have used gsaps 2dphysics plugin to get it working so each fireball itself is a sprite in a container, then onupdate with that animation, the x&y position of the fireball is sent to update the ownerposition of the trail emitter. It does work pretty well appearance wise, but performance does feel like it takes a bit of a hit, which Im guessing maybe down to the plugin. Any ideas on any more "optimal" ways in which something like this could be achieved?
  16. Hey all - was just wondering if html5gamedevs had a discord server, or if anyone had found a good one for pixi devs? Just thought it could be a nice place to float the odd question or showcase bits and pieces peeps are working on without it being topic specific?
  17. That's brilliant thanks, lots of useful info there. Might be something I'll take a look at once the project is nearly done as I still have a few bigger targets to hit first. I've been able to target each character with children, but it's just setting the anchor that has messed up the kerning. I was thinking of trying something that used the width of each character to calculate the offset and seeing if that could be adjusted manually before it was added to the stage. Either way will update if I find a solution. Many thanks!
  18. Sorry to bump but still not sure how best to approach this one (so have avoided it so far :D) @themoonrat any ideas?
  19. Apologies, just spotted a post below asking pretty much the same question. Feel free to delete
  20. Hi all Latest project I've been using a mix of bitmapfonts and pixi text (mainly bitmap fonts for the stylised displays, and pulling google fonts for the rest). One quick query. I read somewhere that changing pixi.text content on the ticker can be performance intensive and bitmap fonts would work better. I was just wondering in general if bitmap fonts are a better option overall performance wise, or if there is little in it? I have a console display I'm about to animate - e.g. terminator style headsup - it will have a series of messages in plain text that will animate through gsap and fade out. Text for this wont be stylised, but at a small size so a full glyph atlas wouldn't take up much texture space?
  21. thanks Ivan looks like updating to 4.8.4 has fixed it
  22. Currently on 4.8.1 but just updating that now. No errors in loading it in the debugger that I can see (if I'm looking in the right place here)
  23. Hi all, been trying to use the .animations feature of texturepacker for a small animated icon, but for some reason It's not finding the animations object even though it's detected and visible in the generated json file? Any clues on something probably obvious that I'm missing here, or has something changed? Error I get is Cannot read property 'electron' of undefined. Have also tried adding both .spritesheet and .textures to the sheet declaration. If I use .textures in the sheet declaration and use a single sprite it is fine, so it's definately loading the json file correctly class ScoreIcon extends PIXI.Container{ constructor(){ super(...arguments); let sheet = PIXI.loader.resources["./assets/electronAtlas.json"]; this.sprite = new PIXI.extras.AnimatedSprite(sheet.animations["electron"]); this.addChild(this.sprite); } } export default ScoreIcon;
  24. hmmm kinda still stuck on this one if anyone has any ideas? Just tried extending the bitmaptext class to see if I could alter the position values of the characters, but it has no effect - the x,y values seem to be ignored. I can kind of understand whats going on, each characters x value will be based upon the previous characters width value I assume, so would need to offset the x once the new pivot was applied. tried .x setTransform, and position.set, but none seem to work when I target a character via children.
  25. Hi, I was just wondering if anyone knew of an easy solution to this... I have a text display using bitmap font I was looking at animating per character, I can get a target to animate via gsap for each character fine through the characters array.. However if I want to set the pivot for each character to the center (for a scale/rotation tween), it will through the kerning off. Any ideas greatly appreciated. for(let i = 0; i < this.bitmapText.children.length; i++){ let target = this.bitmapText.children[i]; target.pivot.set(target.width/2, target.height/2);, 0.3, {pixi:{scale:1.2}, repeat:-1, delay:i*0.15, yoyo:true, ease:Sine.easeInOut}); }