Jump to content

Exca

Members
  • Content Count

    392
  • Joined

  • Last visited

  • Days Won

    13

Reputation Activity

  1. Like
    Exca reacted to Torsin in Lights / LUT's / Sprites   
    You can see the lighting effect in game now. Really appreciate the help you have given me!
     
     
  2. Thanks
    Exca reacted to freddyInKorea in PIXI canvas freezing 0.2 second every 10 seconds   
    @Exca
    I just had to update graphic card drivers and the problem got solved hehehe
  3. Like
    Exca got a reaction from freddyInKorea in PIXI canvas freezing 0.2 second every 10 seconds   
    Does the micro freezing happen if you close your debugger? I have a similar issue with my computer currently where if I have chrome debugger on, then there's some stuttering but if I close it then everything runs really smoothly.
  4. Like
    Exca got a reaction from ivan.popelyshev in New to PIXIjs, need help moving sprites smoothly   
    Hi and welcome to the forums!
    You have multiple options on how you could do animations:
    - Use a tweening library (for example tweenjs, pixi-tween, tweenmax etc).
    - Update the positions manually with every render tick.

    Using a tweening library would be the easiest. This is an example how you could use one with createjs's Tweenjs library to move sprite from it's current position to 100,50 in 500 milliseconds with quadratic easing in&out:
    createjs.Tween.get(sprite).to({x:100, y:50}, 500, createjs.Ease.quadInOut ); For the custom timing function you would then tell the tweening library to not use timer on it's own (most do) and instead call the updates manually with elapsed milliseconds * your speed. 
     
    The second option could be something like this for example:
    // List of your objects. The data structure here is very shortened from what might be really the case. const squares = [ { sprite, positionsAtTime: [{time, point}] }, ... ]; // A simple linear interpolation function. Returns value between a & b when t is [0,1] const lerp = (a,b,t) => a*(1-t)+b*t; // Total elapsed time. let time = 0; // Speed on how fast time moves. let speed = 1; // Add ticker. app.Ticker.shared.add( delta => { // Advance time by elapsed milliseconds and multiply by speed. time += app.Ticker.elapsedMs * speed; // Go through all the squares. for(let i = 0; i < squares.length; i++) { const s = squares[i]; // Find the first config that has larger time value that we currently have. const to = s.positionsAtTime.find( tp => tp.time >= time); // Find out the previous one. const was = s.positionsAtTime.indexOf(to)-1; // Make sure both exists. Replacing the find & indexof with better data structure would be really good performancewise. if(to && was){ // Calculate the x&y positions with linear interpolation. // (time-was.time)/(to.time-was.time) returns [0,1] when time is between was.time and to.time. s.sprite.x = lerp( was.point.x, to.point.y, (time-was.time)/(to.time-was.time) ); s.sprite.y = lerp( was.point.x, to.point.y, (time-was.time)/(to.time-was.time) ); } } }); Hopefully these help.
  5. Like
    Exca got a reaction from Snok in Smallest pixi object that i can attach to a container   
    You could use a container inside a container? Or then a sprite with empty texture? Or any displayobject with renderable as false. Or extend the DisplayObject and create your own displayobject.
  6. Like
    Exca got a reaction from Azern in Need help on Pixi demo spinner   
    The delta part there tells how much your rendering differs from the target. I don't currently remember how the default pixi ticker works in relation to that (I use a custom ticker).
    When your computer has enough processing power to handle solid 60 fps (default target in pixi and also the time browser does requestAnimationFrame on a 60 hz monitor) then having delta or just skipping it makes no difference. But if you were running the program on a very slow computer that could render only at 30 fps then the renderloop would be called only 30 times in second compared to previous 60 times. So all your updates would advance only 30 times instead of the 60.
    For example if you had a sprite that was spinning with rotation+=1 in every update. Then on pc running with 30 frames  per second it would move 30 radians during a second where as the other fullspeed rendering would rotate 60 radians. And if you had a 144hz monitor where the requestAnimationFrame might be called 144 times a second then that would be much faster.
    The delta value in the trigger measures how much time has passed since your last render and calculates a normalized delta value (normalzied into target fps) based on that. So with 30fps the delta would be 2 and your rotation update would be rotation+=1*delta -> 60 radians in a second. Then with 144hz rendering it would 60/144=0.41666 and thus the rotation would be called 144 times with rotation+=1*0.41666 -> 60 radians in a second.
    Basically the delta tells you how much your previous frame was off from the target fps. The target fps in pixi v6 is set into settings.TARGET_FPMS (how many frames should be rendered in milliseconds, so 60/1000 is the default). The target fps does not affect how many times your program gets the render call, as that is determined by the browser and is something that cannot be changed by the developer.  Though there are frame skip methods to emulate lower fps rendering.
    [Edit] Here's an article that goes into a bit more detail with images about frames deltatime https://gamedevunboxed.com/understanding-delta-time/
  7. Like
    Exca got a reaction from Azern in Need help on Pixi demo spinner   
    Delta is the numeric normalized value on how much time has passed since the last frame. Let's say your target FPS is 60 and rendering a frame takes 50ms then your delta would be 50/16.66 =  3.001. To keep everything going as fast as the intended timing then that value is used in calculations and everything updates at the same speed even if frames rendered is 3 times less.
    You could also just ignore delta and update with a fixed amount, then on slow computer then the animations etc. would just take longer if no delta calculations was done.
    There's a lot of solutions on how to handle timing differences in gameplay/rendering, but the delta calculations are the simplest.
  8. Like
    Exca got a reaction from Azern in Need help on Pixi demo spinner   
    Hi, I'm the one who made that example.
    The basic functionaly for each spinner is in their generation function and they return a function that updates that spinner.
    Here's a more detailed descriptin without any overhead related to other spinners.
    // Crete the app const app = new PIXI.Application({ backgroundColor: 0x1099bb }); document.body.appendChild(app.view); // Create a container for the stage. const container = new PIXI.Container(); app.stage.addChild(container); // Create the sprite that gets masked out. const base = PIXI.Sprite.from('examples/assets/bg_scene_rotate.jpg'); // Resize the sprite to a fixed one. This step could be skipped and you could just use it as is. const size = 100; base.width = size; base.height = size; // Create a mask and set it to center of the base sprite. const mask = new PIXI.Graphics(); mask.position.set(size / 2, size / 2); base.mask = mask; // Add the sprite & mask to container. container.addChild(base); container.addChild(mask); let phase = 0; // Function to redraw the mask. function update(delta){ // Update phase. Phase in this example is from 0 to Pi*2 (full circle). phase += delta / 60; // If phase is over Pi*2, go back to 0 to restart animation. phase %= (Math.PI * 2); // Offset the starting angle to point up instead of right. const angleStart = 0 - Math.PI / 2; // Angle to calculate with is the phase + starting angle. const angle = phase + angleStart; // Half of the size as radius. const radius = size/2; // Calculate a position on the circle at the starting angle. const x1 = Math.cos(angleStart) * radius; const y1 = Math.sin(angleStart) * radius; // Clear old graphics mask.clear(); // Set linestyle to 2, this is only for debug purposes, could be omitted. mask.lineStyle(2, 0xff0000, 1); // Start filling the mask. mask.beginFill(0xff0000, 1); // Start rendering from center. mask.moveTo(0, 0); // First draw line to starting angle. mask.lineTo(x1, y1); // Then draw an arc from starting angle to current angle. mask.arc(0, 0, radius, angleStart, angle, false); // Finally go back to center to complete the polygon. mask.lineTo(0, 0); // End filling. mask.endFill(); } // Listen to ticker updates. app.ticker.add( (delta) => { update(delta); }); Hopefully this helps.
  9. Like
    Exca got a reaction from ivan.popelyshev in Need help on Pixi demo spinner   
    Hi, I'm the one who made that example.
    The basic functionaly for each spinner is in their generation function and they return a function that updates that spinner.
    Here's a more detailed descriptin without any overhead related to other spinners.
    // Crete the app const app = new PIXI.Application({ backgroundColor: 0x1099bb }); document.body.appendChild(app.view); // Create a container for the stage. const container = new PIXI.Container(); app.stage.addChild(container); // Create the sprite that gets masked out. const base = PIXI.Sprite.from('examples/assets/bg_scene_rotate.jpg'); // Resize the sprite to a fixed one. This step could be skipped and you could just use it as is. const size = 100; base.width = size; base.height = size; // Create a mask and set it to center of the base sprite. const mask = new PIXI.Graphics(); mask.position.set(size / 2, size / 2); base.mask = mask; // Add the sprite & mask to container. container.addChild(base); container.addChild(mask); let phase = 0; // Function to redraw the mask. function update(delta){ // Update phase. Phase in this example is from 0 to Pi*2 (full circle). phase += delta / 60; // If phase is over Pi*2, go back to 0 to restart animation. phase %= (Math.PI * 2); // Offset the starting angle to point up instead of right. const angleStart = 0 - Math.PI / 2; // Angle to calculate with is the phase + starting angle. const angle = phase + angleStart; // Half of the size as radius. const radius = size/2; // Calculate a position on the circle at the starting angle. const x1 = Math.cos(angleStart) * radius; const y1 = Math.sin(angleStart) * radius; // Clear old graphics mask.clear(); // Set linestyle to 2, this is only for debug purposes, could be omitted. mask.lineStyle(2, 0xff0000, 1); // Start filling the mask. mask.beginFill(0xff0000, 1); // Start rendering from center. mask.moveTo(0, 0); // First draw line to starting angle. mask.lineTo(x1, y1); // Then draw an arc from starting angle to current angle. mask.arc(0, 0, radius, angleStart, angle, false); // Finally go back to center to complete the polygon. mask.lineTo(0, 0); // End filling. mask.endFill(); } // Listen to ticker updates. app.ticker.add( (delta) => { update(delta); }); Hopefully this helps.
  10. Like
    Exca got a reaction from Teckniel in [Sprite]Typescript Sprite.On Event Error   
    In javascript the scope of the function depends on how it's executed. For example if you have a class and you call it by myClass.foobar() then that is executed in the scope of the class. But if would do something like var func = myClass.foobar; func(); it would execute outside of the classes scope.
    Basically same thing happens when the event handler is run as you pass the info about the function only and not the scope.
    Old way of doing this was that you would do something like this:
    var that = this; function handler( ){ that.foobar(); } window.addEventListener("something", handler);   More modern solution that came to be was to bind the function you give as parameter:
    class Foo { constructor(){ window.addEventListener("something", this.handler.bind(this)); } function handler { this.doSomething() } } And if you had to remove the listener at some point then first binding and assigning that to a variable and then passing that variable to listener would be way to go.
    With typescript I use nowadays purely arrow functions when there's scoping involved. Though they also have their drawbacks.
  11. Thanks
    Exca reacted to ivan.popelyshev in PIXI.js : Blur / pixelated sprite   
    or make canvas2d of pow2, draw image there, make texture out of it in pixi, enable mipmapping. Yes, this behaviour is default for ThreeJS, but pixi does like to force users to learn stuff
  12. Like
    Exca got a reaction from jinzo7 in PIXI game as mobile app these days   
    Progressive web apps (PWA) are one way to create apps with web technologies without using wrapping.
    If on the other hand wrapping is needed, then cordova based ones are still the most common ones.
  13. Like
    Exca got a reaction from vornay in Can pixijs frames be processed individually?   
    You could extract the frames from canvas with toDataUrl or use the extract plugin to get the actual pixel data of a single frame. Then gather all of the frames and encode them into a video with some encoder, dunno if those exist in the browser, most likely someone has made one.
    You can do stacked rendering with multiple different ways.
    - Have 2 containers that move with different speeds.
    - Use overlapping canvases with each having their own renderer and move them.
    - Have each of your object in the scene have a depth value and move everything based on that.
    - Use rendertextures to create the stage and use those with tilingsprite and offset them at different speeds.
    Different methods have different limitations & benefits.
  14. Thanks
    Exca got a reaction from Zealot in Raycasting and inverse masking   
    You could make a filter that takes the world texture as input and the light mask as input and then just draw the world if light has value at that same position. And otherwise keep value hidden.
    Something like this:

    vec4 world = texture(worldTex,uv);
    float light = texture(lightTex,uv).a; //Using only one channel for light, this could also be light color + alpha for intensity
    gl_FragColor = mix( vec4(0,0,0,1), world, light);
  15. Like
    Exca got a reaction from flatliner in Rotate with mouse wheel   
    Just listen for wheel event on the window/document/element https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
  16. Thanks
    Exca got a reaction from ShoemakerSteve in Performance advice and basic concepts   
    Very simple optimization. Instead of graphics use sprites with single white rectangle as their basetexture. Then apply tint to them to color the sprite. That way the squares can be rendered as a batch. That should be good enough for 150*200 squares (30k sprites). But for 1000 x 1000  (1M squares) you need to go deep into webgl rendering or have some other optimization strategy. Or would those squares be all visible at the same time? If not, then that would be doable by separating logic from rendering and only rendering a subsection of the whole area.
    And here's a little rundown about different graphic objects:
    - Graphics: Dynamically drawn content. Use when you need to draw lines, shapes etc. Be aware that updating graphics every frame might be costly depending on the complexity.
    - Sprites: Sprites are basically just to tell what texture to draw and where, with this rotation, tint and scale. Sprites are among the cheapest objects in pixi.
    - Textures: Textures are a region of baseTexture. They tell you what part of a baseTexture should be drawn. When using spritesheets the difference between texture and baseTexture is very noticable. When using just regular images then usually textures point just to a baseTexture and say that I want to render that whole thing.
    - Basetexture: Basetextures represent a single image in memory.
    - Mesh: Meshes are renderables that have customizable vertices. You could think that sprite is also a mesh that has 4 vertex points (topleft, topright, bottomright and bottomleft). With Meshes you can control how your polygons get formed. There are some premade mesh classes that provide premade useful meshes: SimpleRope, SimpleMesh and SimplePlane. Those abstract some of the complexity away.

    And when to use them:
    Graphics: Dynamic drawn content.
    Sprites: Images with basic affine transformations (scale, rotation, position) and basic color transformation (tint, alpha).
    Textures & BaseTexture: Pretty much always if you have some images to use. Very often these get handled automatically.
    Mesh: When you need deformations.
    Also here's a short instruction on shaders:
    Modern computer graphics cards have a pipeline where you tell what program (vertex + fragment shader) you want to use, what vertices it gets as input and what uniforms (+ other stuff that I wont go into at this point). Then for each vertex it runs the vertex shader program. This basically calculates where on the screen should the point be. Then for the polygons formed by these vertices it runs the fragment shader for each pixel that is inside the polygon. The fragment shader returns the color value for that pixel. The uniforms mentioned beforehand are values that stay the same for both vertex and fragment shader on all vertex & pixel values. They are used to give values that are needed to calculate the output values. In sprite fragment shader "tint" is an uniform that is multiplied with the texture value.
    So basically your gpu renders wegbl like this (simplified): list of points to draw -> vertex shader -> find out what pixels are affected -> fragment shader -> pixel to screen.
  17. Haha
    Exca reacted to ivan.popelyshev in image texture dynamic transition   
    > is out of my scope in reasonable time.
     
    Im gonna steal that phrase
  18. Like
    Exca got a reaction from ivan.popelyshev in image texture dynamic transition   
    You could do that by creating a shader with two texture inputs which blend between those two. The actual code & math inside the shader is out of my scope in reasonable time.

    As a starting point I would propably try doing somekind of convolution with previous frame as feedback and then moving towards target image.
    This is the closest example for blending. In the example a perlin noise image is used to determine the blending. In your case that would be the shader somehow morphing the images.
    https://pixijs.io/examples/#/mesh-and-shaders/multipass-shader-generated-mesh.js
  19. Like
    Exca got a reaction from Minimog in Do not trigger interaction listener if something “covering” interactive element was clicked   
    The covering element has to have interaction enabled as well as the other item. Only those that are marked as interactive and whose parents dont have interactivechildren are taken into account when checking interactions.
  20. Thanks
    Exca got a reaction from leeda in How to create a rounded rectangle loading animation with Pixi.js v4.0+?   
    Added spinners pull request to examples. You can check that from pr or wait until it gets accepted to see it at examples.
  21. Thanks
    Exca got a reaction from Jammy in Sprite compression   
    There's plenty you can do with compression.
    For png/jpg images the amount of original image doesnt change how much memory gpu takes for that image. As those images get unpacked. But you could use compressed textures to remove decompressing and lower gpu memory usage. https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Compressed_texture_formats
    One thing I'm not really sure is that if you have 8 bit png does that become 8bit or 32bit image after decoding.
    When it comes to loading related compression (targeting minimal dl time and no compressed textures needed) my basic workflow is to do the following:

    - Use spritesheets to group similar colored assets together (without breaking batching).
    - Group assets that dont need transparency together.
    - Export all as nonpacked png.
    - For images without transparency, update the json to use jpg and pack the png with Google Guetzli (https://github.com/google/guetzli)
    - Pack the png images to 8 bit version and do a visual check if quality drops too much. I use PNGoo for this. (https://pngquant.org/)
    - Run all png assets trough PNGauntlet ( https://pnggauntlet.com/) It's a tool that combines PNGOut, OptiPNG and DeflOpt and picks the smallest png.
    And doing lots of profiling between steps to see what actually has a positive impact.
  22. Like
    Exca got a reaction from Freckles in mouseup doesn't fire (PIXI)   
    Are those standard html input fields with canvas below them?
    You could make a container that has a hitarea with the size of whole screen and set interactive = true. Then on the handler call blur for the inputfields (or focus for another element, canvas for example).
  23. Thanks
    Exca got a reaction from Freckles in Accessing variables in PIXI*   
    setInterval(() => { this.cursor.alpha = 1; //alpha is undefined setTimeout( ()=> { this.cursor.alpha = 0; }, 500); }, 1000); You could use arrow functions instead. The scope to which this refers in javascript changes in your first example to functions scope.
    For more info on how this gets scoped check out this https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
  24. Like
    Exca got a reaction from b10b in PIXI Sound mp3 loop 'pause'   
    The mp3 looping problem is caused by the format. It can be mitigated by fiddling around the original sound source and compression: https://www.compuphase.com/mp3/mp3loops.htm
    I'd suggest using multiple formats and drop them based on browser support. Most of the audio libraries have alternateExtension -configuration (or something similar) to handle this. I usually go with ogg as first choice and then mp3 for those that dont support ogg.
  25. Like
    Exca got a reaction from charlie_says in PIXI Sound mp3 loop 'pause'   
    The mp3 looping problem is caused by the format. It can be mitigated by fiddling around the original sound source and compression: https://www.compuphase.com/mp3/mp3loops.htm
    I'd suggest using multiple formats and drop them based on browser support. Most of the audio libraries have alternateExtension -configuration (or something similar) to handle this. I usually go with ogg as first choice and then mp3 for those that dont support ogg.
×
×
  • Create New...