• Content Count

  • Joined

  • Last visited

1 Follower

About html5gamedev

  • Rank

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Thanks for a swift reply! Unfortunately the issue remains. I updated the live example with the suggested code.
  2. I am creating new AnimatedSprites on pointerdown event (and deleting them on next pointerdown event) over the course if application lifetime. At some point around 20 clicks, the app crashes with an error: Rats! webGl crashed. At that point no error is displayed in console. Crash happens on a mobile device, and would probably also happen on desktop, if someone perform plenty of clicks. Code that is repeatedly used is below. I also include live example at Can someone please point out what am I doing wrong? From other answers I deduced that you need to reset the loader and call destroy() on animated sprite. I call both of this methods, but there is still an issue. function createNewAnimatedSprite(resources,newLoader){ var tmpSprite = new PIXI.extras.AnimatedSprite(setupFrames(resources["nextSprite"].texture.baseTexture)); app.stage.addChild(tmpSprite); spritesArray.push(tmpSprite); setupNextSprites(tmpSprite); app.renderer.plugins.prepare.upload(tmpSprite, function(){ console.log("updoaded now"); canRunNext = true; newLoader.reset(); //console.log("kill"); delete tmpSprite; }); } function setupNextSprites(nextSprite){ nextSprite.x = app.renderer.width / 2; nextSprite.y = app.renderer.height / 2; nextSprite.anchor.set(0.5); nextSprite.loop = false; nextSprite.animationSpeed = 0.5; nextSprite.visible = false; nextSprite.onComplete = function (){ console.log("animation finished"); isAnimating = false; }; } function setupNextAnimation(){ var randomNumber = getRandomInt(0,3); switch (randomNumber) { case 0: nextColor = "red"; break; case 1: nextColor = "aqua"; break; case 2: nextColor = "green"; break; case 3: nextColor = "purple"; break; } } app.stage.on("pointerdown", function () { if (firstRun && !isAnimating) { firstRun = false; isAnimating = true; currentSprite.gotoAndPlay(0); currentSprite.gotoAndPlay(0); }else{ if (canRunNext && !isAnimating){ isAnimating=true; if (currentSprite.visible){ currentSprite.visible = false; currentSprite.destroy(true); } spritesArray[spritesArray.length-1].visible = true; spritesArray[spritesArray.length-1].gotoAndPlay(0); app.stage.removeChild(spritesArray[spritesArray.length-2]); spritesArray[spritesArray.length-2].destroy(true); canRunNext = false; setupNextSpritesAnimation(); } } }); function setupSpritesAnimation(){ //created currentSprite just once at the start of app spritesArray.push(currentSprite); }
  3. I am trying to replace a texture atlas of the animated sprite with another one, and play it. On every click I first fetch the texture atlas image from server. Than I make periodic checks if there is any animation still running. Once there is no animation running, I replace animatedSprite.textures with the new on and upload that texture atlas to the gpu. After it is uploaded, I set canRunNext to true, signaling, that everything is uploaded and ready to go. The issue is that app.renderer.plugins.prepare.upload uploads every second texture, for reasons unknown to me. Now this could be hard to visualize so I created a dummy example. After each animation, I run a random next one. you MUST run this on a slow mobile device to see my issue. Well, just don't run it on latest iphones and androids and you should see the issue. The textures in use are just placeholders to convey message. Link: Now, the first and second texture are uploaded as expected. if you click on square, the animation is triggered right away. But watch out, the 3. one is not, then the 4. is uploaded, then the 5. again, is not and so on. On every second click, my animation is not uploaded to gpu. I am not getting why is this happening. How would you fix this issue? All the code is available at the website I posted. The meat are these two functions: setupSpritesAnimation() setupNextSpritesAnimation() setupNextSpritesAnimation has a case statement (I trimmed that off to save some space), but inside the case I am basically just fetching a new image from server, and waiting for animation to be over. Once it is over, I create frames for each animation frame and upload them to the gpu. function setupNextSpritesAnimation(){ var newLoader = new PIXI.loaders.Loader() .add('nextSprite', 'pathToSprote.png') .load(function (loader, resources){ start = +new Date(); var interval = setInterval(function(){ if (!isAnimating){ clearInterval(interval); if (!firstRun){ nextSprite.textures = setupFrames(resources["nextSprite"].texture.baseTexture); app.renderer.plugins.prepare.upload(nextSprite, function(){ console.log("updoaded now"); canRunNext = true; isAnimating = false; newLoader.reset(); //console.log("kill"); end = +new Date(); var diff = end - start; console.log(diff); }); } } },50); }); } I hope you can help me out with this stubborn issue. This question is a follow up question on with the live example included. The previous question got no response, probably because of lack of live example.Best regards, Mitt
  4. I am trying to replace a texture atlas of the animated sprite with another one, and play it. I play it once all animations are stopped (variable isAnimation is false). To play it at the time of click, I need to pre upload it to gpu. I am using the following code prepare new texture atlas on each click. It seems that prepare.upload does not work everytime! In fact, it only uploads texture every second time. I've put timers into the code, and I can observer that when the prepare.upload uploads to gpu, time difference (variable diff) is 200ms, but when it does not, time difference is just 60ms. Based on that I conclude that prepare.upload didn't upload the textures. Now this is a real pain in the ass, because it messes up my animations, sound effect..pretty much renders code useless. What could I do to fix that? I've got over 1000 lines of code and I posted just the relevant stuff. Basically I need to just replace the texture atlas once the animations are over and upload it to gpu. How hard can it be, right? function setupNextSprite(){ var newLoader = new PIXI.loaders.Loader() .add('nextSprite', 'pathToSprote.png') .load(function (loader, resources){ start = +new Date(); var interval = setInterval(function(){ if (!isAnimating){ clearInterval(interval); if (!firstRun){ nextSprite.textures = setupFrames(resources["nextSprite"].texture.baseTexture); app.renderer.plugins.prepare.upload(nextSprite, function(){ console.log("updoaded now"); canRunNext = true; isAnimating = false; newLoader.reset(); //console.log("kill"); end = +new Date(); var diff = end - start; console.log(diff); }); } } },50); }); } // event trigger code nextSprite.gotoAndPlay(0); canRunNext = false; setupNextSprite();
  5. Yeah, I am passing resources["out2"].texture.baseTexture to it, so that's okay. I guess I have bad naming convention. I am trying to fetch the new texture atlas from the server. I've managed to do it if I preload everything, but there are too many texture atlases to preload all of them. So i created this function to fetch them 1 by 1 when it is necessary: var nextSprite; function fetch(){ var newLoader = new PIXI.loaders.Loader() .add('nextSprite', 'pathToSpriteSheet') .load(function (loader, resources){ nextSprite = new PIXI.extras.AnimatedSprite(setupFrames(resources["nextSprite"].texture.baseTexture)); //setupSprites(nextSprite); app.renderer.plugins.prepare.upload(nextSprite, function(){ if (firstRun){ app.stage.addChild(nextSprite); } newLoader.reset(); }); }); } I call it in this way: //on click event, each click should load a new texture nextSprite.gotoAndPlay(0); fetch() To my disappointment, this doesn't seem to work with periodic clicking. Any idea how to load new texture atlases, stuff them in the same AnimatedSprite and play the animation?
  6. I use this code to setup a texture atlas animation: PIXI.loader .add('out2', 'assets/out2.png') .load(function (loader, resources){ onRotationsLoaded(loader, resources) }); function onRotationsLoaded(loader, resources) { first = new PIXI.extras.AnimatedSprite(setupFrames(resources["out2"].texture.baseTexture)); app.renderer.plugins.prepare.upload(first, function(){ console.log("loaded first"); // ready to go }); } function setupFrames(name) { var frames = []; array is an array that stores correct position for each frame of animation for (var i = 0; i < array.length; i++) { var rect = new PIXI.Rectangle(array[i].frame.x, array[i].frame.y, array[i].frame.w, array[i].frame.h); frames.push(new PIXI.Texture(name, rect)); } return frames; } I would like to change the texture of the AnimatedSprite first in a click event or something. The new texture needs to be fetched from the server(I do not want to load it at start, because there are too many of them). I could destroy first and create second AnimatedSprite, but is there a way to just change it's texture atlas image?
  7. ah, I am such a noob. there was some test code somewhere else in the project. you can safely delete this thread.
  8. I am creating animation frames from image the hard way -I am using PIXI.Texture and passing baseTexture and Rectangle (I don't use json directly, because of reusability of json instructions). See code below. I am getting an error: baseTexture.once is not a function. I don't know what is causing this error, but the animation is working as expected. Is this error something I shouldn't worry? function loadAssets() { PIXI.loader .add('first', 'assets/first.png') .load(function (loader, resources){ onLoaded(loader, resources) }); } function onLoaded(loader, resources) { console.log(resources.rot1.texture.baseTexture);// all rotations loaded var first = new PIXI.extras.AnimatedSprite(createFrames(resources["first"].texture.baseTexture)); .... } function createFrames(name) { var frames = []; for (var i = 0; i < 39; i++) { var rect = new PIXI.Rectangle(arr[i].frame.x, arr[i].frame.y, arr[i].frame.w, arr[i].frame.h); // stored in an array generated from json frames.push(new PIXI.Texture(name, rect)); } return frames; }
  9. I have a couple of texture atlases. The order of textures that create animation is the same in all of them. In other words, my first frame of animation is always (0,0,100,100), my second frame is in all atlases (100,0,100,100) and so on. The only thing that changes is meta's image: "image1.png". It changes to "image3.png" and so on. Frames in all texture atlases are named the same { "meta": { "image": "image1.png", "size": {"w"1000,"h":2000}, "scale": "1" }, "frames": { "image_0000.png": { "frame": {"x":0,"y":0,"w":100,"h":100}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":100,"h":100}, "sourceSize": {"w":100,"h":100} }, "image_0001.png":{...} } } It is kinda wasteful to load 10 different json files, because the positions and frame names are always the same for all of the animations. How can I load images instead of json files? PIXI.loader .add(['assets/file1.json']); // don't wanna load 10 json files function createFrames(name, imageToUse) { var frames = []; for (var i = 0; i < 30; i++) { var val = i < 10 ? '0' + i : i; frames.push(PIXI.Texture.fromFrame(name + val + '.png')); // use imageToUse to tell PIXI from which image should it create frames. } return frames; }
  10. Thank you so much. I've spent a week puzzling with this issue (and I would probably spent another one) just to find out that I can't code it the way I want with pixi (and possibly any other tool). The box example is just a placeholder to represent my issue. Are you aware of any tricks I can use with plain css and JS, that could mimic a smooth texture atlas animation, when big images are in use? I've already used css's step() method (can't run it smooth), I've tried setting up timer and changed background-position of the image (also can't run it smoothly) and I've used plain canvas("canvas") (Thats the worse of all 3 methods). I think I am gonna try to recreate the issue with canvas("webGL") next.
  11. Ooh, I see! So if you want to load multiple texture atlases this big, the bottle neck is actually RAM of mobile devices. Thanks, you are very informative. regarding upload time of atlases... I am totally fine with 4-5 second upload time, as long as the loading and preparing happens when another animation is running (and the atlas can play immediately when requested), so the user won't even notice. What bugs me (this issue shows in the updated version is that little freeze of the currently running animation when the next atlas is loaded into the gpu. Maybe it freezes for just about 100ms, but it is very noticeable. If you can point me in the right direction regarding this issue, I will me most thankful.
  12. Thanks. You know, this is exactly what I want to achieve. Load new texture atlases and run them without any freeze or delay. As far as texture atlas size goes, I found this page, which states that 4096 by 4096 is universally supported (not sure what they mean by VRAM though..). What do you recommend that I do? there is gotta be some way to load textures atlases and run them..
  13. Thanks for stopping by. I have a huge number of textures(and they won't be used at the same time). The idea was to upload one by one dynamically, since I cannot leave user staring at the loading screen for 10min I used your suggestion and it works. Kinda. This is what I used in load next: app.renderer.plugins.prepare.upload(next, () => { canRunNext = true; $("body").css("background-color","green"); }); The new problem is that when the animation finishes uploading to the gpu, there is a freeze. I change color of body to signify this event. You can see it here: Now this rectangle animation is jaggy itself, but you can definitively see it even on desktop machines. A small freeze when the body turns green. How can I fix this?
  14. I am trying to load texture atlas dynamically. The load happens when the user clicks on canvas. At the same time an animation fires. The next time the user clicks on canvas, previously loaded animation runs. Perhaps it is best to demonstrate the problem. I uploaded the files on a test server. You can see the delay here: I hardcoded the first animation load, meaning that you will see a delay on second canvas click. Run this code on a low end mobile device, and you will se a huge delay. I am getting a 4s delay on a motorola G and 0.5s on an iphone 5. What can I do solve this annoying issue? you can inspect the code on a website, but I will also paste it here: $(function(){ var current; var next; var canRunNext = false; var isAnimating = false; var firstRun = true; var container = document.getElementById("canvas-container"); var app = new PIXI.Application(550,584,{transparent:true}); var canvas = container.appendChild(app.view); setupCanvas(); loadRotationsAndCurrent(); var infiniteLoader = PIXI.loader; function setupCanvas(){ $(canvas).attr("id","canvas"); if (window.screen.width < 600){ $(canvas).css("width","100%"); $(canvas).css("height","100%"); $("#canvas-container").css("width","100%"); }else{ $("#canvas-container").css("width","50%"); } } function loadRotationsAndCurrent(){ PIXI.loader .add(['jimages/1s.png.json']) // load all rotations .load(onRotationsLoaded); } function loadNext(){ if (firstRun){ infiniteLoader.add('jimages/2s.png.json'); infiniteLoader.load(function(loader, resources) { next = new PIXI.extras.AnimatedSprite(setupFrames("2_000")); next.visible=false; next.animationSpeed = 0.5; next.loop= false; next.x = app.renderer.width / 2; next.y = app.renderer.height / 2; next.anchor.set(0.5); next.onComplete = function() { console.log('onComplete'); isAnimating=false; }; app.stage.addChild(next); // app.renderer.bindTexture(next); canRunNext=true; console.log("next loaded"); }); }else{ infiniteLoader.add('jimages/2s.png.json'); infiniteLoader.load(function(loader, resources) { next = new PIXI.extras.AnimatedSprite(setupFrames("2_000")); canRunNext=true; console.log("next loaded"); }); } } function setupFrames(name){ var frames = []; for (var i = 0; i < 30; i++) { var val = i < 10 ? '0' + i : i; // magically works since the spritesheet was loaded with the pixi loader frames.push(PIXI.Texture.fromFrame(name + val + '.png')); } return frames; } function onRotationsLoaded(){ // all rotations loaded current = new PIXI.extras.AnimatedSprite(setupFrames("1_000")); current.x = app.renderer.width / 2; current.y = app.renderer.height / 2; current.anchor.set(0.5); current.loop=false; current.animationSpeed = 0.5; current.visible = true; isAnimating = false; current.onComplete = function() { console.log('onComplete'); isAnimating=false; }; app.stage.addChild(current); } var run = true; $("#canvas").on("click touch touchstart",function(){ if (firstRun && !isAnimating){ loadNext(); isAnimating=true; current.gotoAndPlay(0); console.log("first run"); firstRun=false; }else{ if (canRunNext && !isAnimating){ isAnimating=true; next.visible=true; current.visible=false; next.gotoAndPlay(0); console.log("can run next"); }else{ console.log("cannot run next"); } } }); });
  15. I am trying to load a texture atlas into the app when the user clicks on the canvas. 2 things happen on canvas click: 1. the animation already loaded plays, and 2. I fetch a new texture atlas from server. Newly fetched texture atlas plays on the next canvas click, and a new texture atlas is fetched. Think of it as endless loop. On every click, previously loaded animation is played, and the next one is fetched and repeat. It is absolutely essential that there is no freeze between animating. What approach do you recommend I take? My tests showed that there is some issues with dynamically loaded texture atlases - animation freezes, if texture atlas is being loaded at the same time. The issue really shows on mobile devices. I've got a hunch that there might be a problem that both PIXI.loader and object.gotoAndPlay() use the main thread, and they block each other, but I really don't know that much about Pixi. I've posted a similar question earlier today: , but I think I didn't correctly identify the reason for my bad performance. So this question is more in general terms. What is the best way to run texture atlas animation and load another texture atlas at the same time, so that the animation can run without any delay when wanted?