• Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by mobileben

  1. I started the process of adding audio to my game. I'm building using Typescript and Webpack. I'm using version 5.2.0. I installed pixi-sound via npm using npm install --save pixi-sound I've tried to follow the examples from here: I've noticed a couple of things. The resource loaded for the sound does not have the `sound` property. And if I try and play like in the demo code doing `'test')`, `sound` is undefined. The version of pixi-sound is 3.0.4.
  2. One thing you should do if you are using WebFont is ensure before you proceed, the load is already done. You can use the active callback for this. I use some fonts which are web based or are local to my game. I do something like the following. WebFont.load({ google: { families: ['Pacifico'] }, active: function() { app.webFontsLoaded = true; if (app.coreAssetsLoaded) { app.nextState = GameState.Game; } } }); There are two flags in use here since I have 2 async things loading: font and and "core assets". So both loading mechanisms check to see if the other one is done. If you don't have this need, you can remove it.
  3. There are numerous physics libraries out there. If you're sill undecided, I would recommend making some benchmark test to compare the functionality you need (which is what I did). I'd also look at how active that project is. Some of those listed above haven't been touched in years, so you'd def be on your own. One advantage of box2d is it is well known and used a lot. So while the version I am using may perhaps be dead, it's easy to find out some explanation on how to do what I need to do ... though generally the answer will be C/C++ based, I found it translates over. Just be prepared to wade through the source code for confirmation as well as how that particular implementation of Box2D named stuff :D. The variant I am using is actually pretty close to the C names. Oh, for the version I'm running, I didn't install via npm. I'm actually directly including it with my source files. It makes it easier for me to debug.
  4. @macshemp, I'm using this version, as I'm using Typescript. Although it is possible it is now a dead project (see my issues). My issues are minor and more about some incompleteness in the interface. It is possible once I finish up this prototype that I make my own fork and mod it some. I have, however, found it to be stable and what I would deem as accurate (enough). Those tests I ran in my matterjs were tested against this version of box. I also compared "theoretical" trajectory with actual, and unlike matterjs, the box2d ones were "accurate". While I initially liked matter ... I now really like Box2D. It has some minor quirks, but it works well. I also did what you did ... didn't want to bother with the conversion of pixel to metric and vice versa. However, it is easy to work with. I use game objects with a gfx and physics property, where gfx is the PIXI graphics object (well my wrapped version of it) and physics is a wrapper to Box2D. I have a PhysicsManager which also has some methods for the conversion. Snippet look like this: get ppm(): number { return this._ppm; } set ppm(val: number) { this._ppm = val; this._ppmInv = 1.0 / val; } get ppmInv(): number { return this._ppmInv; } scalarToPhysicsWorld(s: number): number { return s * this._ppmInv; } pointToPhysicsWorld(pos: Point): Point { return { x: pos.x * this._ppmInv, y: pos.y * this._ppmInv }; } scalarFromPhysicsWorld(s: number): number { return s * this._ppm; } pointFromPhysicsWorld(pos: Point): Point { return { x: pos.x * this._ppm, y: pos.y * this._ppm }; } And in my GameObject update code I do the following if (this._physics && this._gfx) { // If we have both physics and gfx, update the gfx based on our physics const pos = this._physics.position; this._gfx.setPosition(pos); // Use rotation because this is in radians this._gfx.setRotation(-this._physics.rotation); } You may need to drop that negative rotation I'm doing. Oh, yeah, on the PhysicsObject, the position code looks like get position(): Point { const pos = this.body.GetPosition(); return { x: PhysicsManager.shared.scalarFromPhysicsWorld(pos.x), y: PhysicsManager.shared.scalarFromPhysicsWorld(pos.y) }; } So essentially I treat everything that doesn't have a special naming to it as "game space". So, box2D lives in "Physics" space. And actually, PIXI lives in Screen space. My game space is cartesian coords with center in the middle of the screen. Forgive any nastiness with the code, I'm a C++ guy that's on the learning curve of Typescript.
  5. Okay. I guess I'll just live with what I have now and cross fingers. There is some witchcraft going on, because I found that certain combos required me to clear the cache in BaseTexture versus Texture. These were all spritesheet cases. But right now I really don't want to crawl through that code to figure out why. Actually I think this could be cleaned up with some small tweaks. Essentially making Texture and BaseTexture (and perhaps Spritesheet) supporting getting or even destroying a texture by name versus destroying by object. To make this work right, you would probably want to have the texture hold a reference to the loader that loaded it so it could clean it up. The draw back here being it should actually be a weak reference object, and I do not know if Javascript supports that. There are ways around this, for example, requiring creating new loaders through a factory and then having a unique name assigned to them. You could then something later like: const texture = Texture.getTexture(key); Then later do either texture.destroy(); Or even Texture.destroyTexture(key); This could probably be made so that it would not break any existing implementation. Really the part the makes it harder is the dependency of Loader and resource, which really should probably not exist once a resource is loaded.
  6. I would say do your due diligence with MatterJS. I originally was going to use it but then abandoned it due to inconsistent behavior and you cannot (or rather I could not figure out how to) project trajectories with accuracy. I actually figured out how to mostly do it, but there was still a constant value multiplier off. That was unsettling to me. For reference
  7. @jonforum Cool, thanks that looks very helpful and always good to learn new tricks. I was using WebFonts at first, but from what I could tell, it didn't quite work with "local" assets. As I am also using Cordova for mobile, it seemed silly to do a fetch over the network for fonts I can bundle in.
  8. Thanks for the reply. This seems to work, however I have found that there is far more razing that needs to be done :(. Here is the snippet I am using. I tried removing items, but it seems all those items are required, which is a lot. // Purge old spritesheet const oldSheet = this._game.loader.resources[oldName].spritesheet; if (oldSheet) { oldSheet.destroy(); } // PIXI does not clean up the loader or caches const oldAtlasName = 'assets/' + oldName + Layout.LayoutManager.shared.decoratedSuffix + '.png'; const oldAtlasKey = oldName + '_image'; delete this._game.loader.resources[oldName]; delete this._game.loader.resources[oldAtlasKey]; PIXI.BaseTexture.removeFromCache(oldAtlasKey); PIXI.BaseTexture.removeFromCache(oldAtlasName); PIXI.Texture.removeFromCache(oldAtlasKey); PIXI.Texture.removeFromCache(oldAtlasName); I would say there is a bit of code smell here. This also makes me wonder whether or not the OpenGL textures are actually truly released, or if I have simply just removed cache entries and references. The reason I cite this is in the destroy code for Texture and BaseTexture, it should in theory clear the cache. I am assuming that PIXI.utils.TextureCache points to one of these caches. Does the above look about correct, and is it fair to assume the texture memory has actually been released? Or did I just simply cover the tracks of a texture that still exists? It would seem better served to decouple loaders with the actual resulting resources. Those resources could have their own managers (or whatever you want to call them). This way if there are multiple loaders, there is still consistency. A user does something like app.loader.resources[key].texture or app.loader.resources[key].spritesheet to get a Texture or Spritesheet, respectively. Thus they are already in effect showing intent. If they did something like TextureManager.getTexture(key) Or SpritesheetManager.getSpritesheet(key) The intent is still covered. Any explicit destroy is then easier to handle. Since Spritesheets know they are dependent on textures, it can use TextureManager to do proper cleanup, for example. Also one last question. How does one access the specific SpritesheetLoader for an Application? I assume there is one created by default. This is one weakness I think pixi has. Too much "cleverness" being applied in trying to insulate end users from certain things. But the reality with game dev is at some point of time, when you have a lot of assets, control over loaders and assets is actually quite important. Or perhaps that's just the nature of JS coding :D.
  9. Just wanted to add something else. I tried to explicitly purge the Loader resources via something like delete this._game.loader.resources[name]; I have found that after this is done, on the next load, the spritesheet property is undefined. I load this asset using this code if (!this._game.loader.resources[bname]) { const tname = Layout.LayoutManager.shared.decoratedAssetName('assets/' + bname + '.json'); this._game.loader.add(bname, tname); this._game.loader.load((loader: PIXI.Loader, resources: Partial<Record<string, PIXI.LoaderResource>>) => { postLoadHandler(); }); } postLoadHandler tries to access the spritesheet via this code (note that resource is split out as a const right now to make it easier to inspect in the debugger). const resource = this._game.loader.resources[bname]; let spritesheet = resource.spritesheet; spritesheet is undefined when I try to reload a spritesheet which was forcibly removed using delete as described above.
  10. I have an in-game asset that can be swapped out. I want to do the right thing by loading the new asset on-demand and then be a good citizen and release the older textures. Code looks something like the following: // Purge old spritesheet spritesheet = this._game.loader.resources[oldName].spritesheet; if (spritesheet) { spritesheet.destroy(); } I notice the side effect is the loader does not realize the sprite sheet has been destroyed. So once I try and re-use the original asset, it causes problems since I check for existence in the loader resources to see if I should reload the asset. Most APIs I've worked with or built have texture systems which are independent of the loader and also clean up properly. So any query for the texture, once destroyed is consistent. Has there been any thought of, instead of grabbing stuff from Loader's resources, having a TextureManager or SpritesheetManager (you actually could get away with just one which is what typically do)? Anyways, what is my best way to handle this? Just set the entry to null? Also, another question I had was related to PIXI.utils.TextureCache. I've found there are times I actually need to use PIXI.utils.TextureCache to find textures. I know it's not ideal and I think I read one shouldn't use it, but there are times I need to get a sub-texture but do not have the atlas name. Oh, I tested and it does appear the TextureCache is actually cleaned up.
  11. Okay, a quick update on this. I solved it, though it really doesn't answer why the strange behavior existed. It seems the trick is adding "sans-serif". As an example, the data I store to define the font looks like this. fontStyle: { family: [ "Roboto", "sans-serif" ], size: 20, weight: "bold", alignment: "center", color: 0xFFFFFF } @d13, I load the font this way <style type="text/css"> @font-face { font-family: "Roboto", sans-serif; src: url("assets/Roboto-Regular.ttf") format('truetype'); } </style>
  12. So the one quirky thing about this problem is that it the font fails at times after it's already been used. So, for example, if I am creating a PIXI.Text for the following strings: ONE, TWO, 3, FOUR. The PIXI.Text are instantiated in that order. ONE, TWO, and FOUR will be Roboto 3 will be the browser default, Times Roman From what I can tell the PIXI.TextStyle is the same. Since ONE and TWO are created before 3, I can assume that Roboto is loaded.
  13. I have a bit of a head scratcher. I am using web fonts, which I load prior to starting. I've defined these as @font-face in the style tags. I include these in my assets folder with all my assets. I can verify via the Developer tools the font is indeed loaded. I've noticed a strange behavior where the font is not always used. I am currently using Roboto as my standard font during prototyping. This is a sans-serif font. It seems that when I try and use a font that doesn't "exist", it defaults to a serif font which is probably Times Roman, as I'm testing on Chrome. So visibly, it is obvious when the text is Roboto versus Times Roman. I've noticed that for certain text, it seems to use the default font versus Roboto. I've dumped out the text style and it's the same for the text. The TextStyle settings I set are fontFamily (Roboto), fontSize, fontStyle (always normal), fill, and align. I do sometimes set fontWeight (either normal or bold). What is bizarre is that the exact same TextStyle will fail for some text. I've noticed in particular, numbers will fail. By fail I mean it ends up using the default font, Times Roman. Another odd thing I noticed is the fontFamily should be "Roboto". In Chrome, if I use "Robots-Regular" everything will work. However, when I try and use this on iOS (Cordova), then it uses the default Times Roman. Note usage of PIXI.Text doesn't matter. It's interleaved, but always the same items use the default. So I'm investigating it more for user error. But it seems very strange behavior that using Roboto-Regular versus Roboto will make it always work on Chrome (but then fail in iOS). I'm trying to find in the pixi code where it makes the decision point on the font to see if I can at least try and better deduce why this is happening.
  14. @RomainMazB got it, I perused the code. Some unsolicited suggestions (feel free to ignore) which may make your life easier, especially given the actual behavior is to make `onClick` part of the CardSprite class and avoid using `event` to derive the target to use. I would also recommend you wrap setting the card to be interactive and listening to events into another `CardSprite` method. You can control enabling and disabling a card from being interactive as well as listening to the mouse over. This will be helpful if you have several cards where some are interactable but others are not ... and the state can change depending on user actions.
  15. @ivan.popelyshev I created a issue here:
  16. Nice code sample! Obviously doesn't use ``, but I think this type of approach works well.
  17. I think the problem is the implementation and the definition of how `target` gets assigned. Keep in mind that how the browser handles the mouse events is different than how pixi does. Pixi essentially transforms it into "pixi space" or rather the node hierarchy. Mozilla documentation indicates that mouseout would have an assigned target. Based on the code base, `processInteractive` is responsible for `target` assignment and that is assigned based on hit, where hit has several criteria much of which is dependent upon the point being within the DisplayObject. Since, when there is a mouseout, the point is no longer in the affected DisplayObject, target will be null. So what ends up happening (at least in my test cases) is that target == null and currentTarget = parent. @RomainMazB you may want to think about creating a class for your cards. This would make it easier to manage your cards.
  18. Bizarre. I'm nascent with Javascript/Typescript. Try this variant. card.on('pointerout', event => { card.position3d.y -= 10; }); It is probably grabbing the `this` context from the current scope that card is in.
  19. Fair point about the new function objects 😁! I think the reason there is not target is that it fails the hit test. The actual DisplayObject in question no longer has the point within the object. Hence target cannot be set to it (I looked at the code in a debugger). I believe in this case, if currentTarget is set, it is the parent. This is the normal code that should set the appropriate target (Pixi.js code). if (displayObject.interactive) { if (hit && ! { = displayObject; } if (func) { func(interactionEvent, displayObject, !!hit); } }
  20. Have you tried to use pointerout? The currentTarget is set for that. I use pointerover/pointerout for my hover code. Are you just trying to animate an object on hover? I don't care about target. If card has the position3d property, then just use an arrow function to get the proper this context. This would change your code. to look like. card.interactive = true; card.on('mouseover', event => { this.position3d.y += 10; }); card.on('mouseout', event => { this.position3d.y -= 10; });
  21. I figured it out. It's assigned in bundles/pixi.js/src/index.js. I believe it's assembled through lerna/rollup. The rollup config I believe references that index file.
  22. I took a better look at the custom game loop and it makes sense. Not sure if I'll go that route just quite yet. A question I have when looking at the code. I can't seem to see where Application actual assigns properties such as Ticker. I've run a grep on the code base and it isn't obvious to me how this is done. For the most part, Application.js (in packages/app/src) look pretty "empty". I also don't see assignment to other things such as view, etc. Where is this all done?
  23. BTW, as a heads up doesn't load/do anything. I've tried on Chrome and Safari.
  24. I very may well have to go this route. I generally try and deviate as little as possible when using 3rd party. I've been burned too many times doing my own things and then running into incompatibilities. Plus my relative lack of JS/TS experience has me focusing a bit more on getting up and running versus getting things cleaner. Up to now, I think my scaling handling has been smattered across different places. This one is more application based. I'll dabble with the game loop a bit today. I'm still tying some pieces together and then will see if I can handle the resizing of assets dynamically. I don't expect the handling to be real time, since that is dependent on assets. I also expect the ease of doing this to be dependent upon the actual number of assets involved. My initial stuff here is "toy" in size, so manageable.
  25. It is indeedy an Application thing. It takes the HTML Element or window. It works, I tried it. I also tried using renderer.resize(w, h), which seems to work. For now I'll assume it correctly resizes the frame buffer versus scaling. Once I get further along I can verify if this hypothesis is correct or not.