Parasyte

Members
  • Content count

    147
  • Joined

  • Last visited

About Parasyte

  • Rank
    Advanced Member

Contact Methods

  • Twitter
    kodewerx

Recent Profile Visitors

1,541 profile views
  1. Parasyte

    registerPointerEvent not emitting in 5.1

    Do any of these examples work for you? http://melonjs.github.io/melonJS/examples/multitouch/ http://melonjs.github.io/melonJS/examples/drag-and-drop/ http://melonjs.github.io/melonJS/examples/shapes/ http://melonjs.github.io/melonJS/examples/UI/ http://melonjs.github.io/melonJS/examples/particles/ http://melonjs.github.io/melonJS/examples/whack-a-mole/ The drag-and-drop and particles examples no longer work for me, but the other examples do. They all use registerPointerEvent
  2. @Growler No problems with that! It's conceptually similar to using shape entities for things like doors or kill planes. I guess in this case it's most similar to me.ParticleEmitter
  3. What kind of events would trigger the entities to "actually load"? Would it be something that just happens nondeterministically, or when loading the map with certain state? If the latter, I would probably lean toward using a copy of the map with the various different states. I know this won't work for every situation, but it's definitely the easiest to implement. For a longer-term solution, you might consider using the object layers supported by Tiled. IIRC, you can change the visibility (on/off, but melonJS just uses it to set the entity opacity to 0) and melonJS won't render invisible layers. But the entity would still be active and needs to be "disabled" or else it will continue to be updated and will be included in collision detection tests, etc. One idea that just came to me is that each object layer can be implemented as a me.Container, if you pass options.flatten=false to me.levelDirector.loadLevel. In short, the most naïve approach is to grab the container reference by the layer's name in the options.onLoaded callback, then remove it from the scene and store it somewhere for later until you need it again. It might look something like this: me.levelDirector.loadLevel('my_map', { flatten: false, onLoaded: () => { // Save an array of every layer named 'quest' to a global object game.quest_layers = me.game.world.getChildByName('quest'); // Remove all of the quest layers from the scene game.quest_layers.forEach((layer) => { me.game.world.removeChild(layer, true); // The second arg preserves the layer }); }, }); setTimeout(() => { // ... Some time passes and we can trigger the quest entities to appear // We'll just use a random layer index for illustration ... let x = Math.floor(Math.random() * game.quest_layers.length); // Remove the layer from the global array, and add it to the scene let layer = game.quest_layers.splice(x, 1); me.game.world.addChild(layer); }, 5000); This is super simplified. A more complex implementation might take layers by multiple names, and store them in a hash map, or even iterate the entire world container looking for invisible containers... There's a lot that can be done to customize it, but the takeaway is that it's desirable to remove children from the scene graph, and add them back in later. And this can be done with the optional keepalive argument when removing children. That might be a good place to start, anyway. Hope it helps.
  4. I am familiar with immediate mode GUI! Never really considered it in the web stack, though. The DOM is already the opposite of immediate mode, and trying to reimplement the entire collection of GUI elements in webGL would be insane. 😅 I also can't see the immediate mode working well with a batching GL compositor that melonJS uses, since the compositor relies on the fact that GL is a stateful API; It tries to optimize rendering by uploading everything early and reusing state often. It is possible to stream vertices to the GPU, though. And that's exactly how dear imgui works.
  5. Forgive me if this sounds skeptical, but most of the existing abstractions are already lightweight, and you'll just end up reinventing the wheel in many areas. The one major exception is probably the observable vector classes. On the other hand, there's really no requirement to use them, nor any of the physics classes, or particle emitters, or tile maps, etc. if you don't plan to use any of that functionality. The existing game loop is about as bare-bones as it gets: https://github.com/melonjs/melonJS/blob/acf776161b421d64509c87bbedfe00501104c863/src/state/state.js#L153-L167 The update and draw loops are likewise very light: https://github.com/melonjs/melonJS/blob/97ede483f5798651e7a7c225df2bb77df66a4a27/src/game.js#L262-L363 ... handling various things like pausable timers and accurate frame skipping/interpolation logic. me.game.world is a container which hosts an array of children to update and draw. The complexity that you envision comes from the nested hierarchy of containers, that can build a complete-but-flexible scene graph. The added flexibility comes at the cost of added complexity. Containers are also fairly lightweight: https://github.com/melonjs/melonJS/blob/acf776161b421d64509c87bbedfe00501104c863/src/renderable/container.js#L758-L849 Everything else in this module is a collection of utility methods to help support nesting. It is conceivable to replace the root container (me.game.world) with a non-nestable container, if that's what you're going for... Which is exactly what the ParticleContainer is. It's unclear just how much benefit you can extract from doing such a thing, but it is certainly an option. So to answer your question, you just need to determine at which level you want to replace the game loop, and patch out that part. You can either monkeypatch it through the me.game references, or using the builtin patching APIs. And then you need to determine which pieces you need to reimplement for a solid foundation beyond just drawing textures.
  6. The code in the OP shows that you return true from the collision handler unconditionally. (Remember, this is the only information I have to go on! I can't see all of your code, and I definitely don't see any conditions checking the shape index.) Which means it would apply the collision response (repel the entities by adjusting the velocity). The code I linked above shows how it calls respondToCollision on the body when the collision handler returns true. And this method adjusts the velocity accordingly. Thus, my observation.
  7. I think what you're seeing has something to do with the misunderstanding of collision shapes on a body. Collision detection does not happen on a "per-shape basis", but on a "per-body basis". In short, bodies collide with other bodies, not with shapes. The shapes are only there to add a physical structure to the body. Under this axiom, it doesn't make sense to have a large rectangle with a smaller inner rectangle, because only the larger rectangle "matters" when performing collision detection. Secondly, you are using two competing collision processes and expecting them to operate independently (I guess). In reality, they are just two sides of the same feature; the me.collision.check() call is the caller, and the onCollision handler is the callee. Obviously, the check ignores itself, but it will call onCollision on the same object in addition to other objects that implement the handler. What you're seeing in the console log is this exact behavior: one of the entities somewhere in the scene is not colliding with anything, and somewhere else, two or more entities are colliding. Thirdly, the scenario that you are testing is artificial, since it should not be possible (under normal circumstances) to end up with two solid entities in the configuration shown in the screenshot. What I mean by artificial is that you have set explicit coordinates to "force" the smaller entity inside the larger one. If they were moved using only the physics properties such as velocity, they would instead repel one another by responding to the collision; adjusting the velocities to counteract any motion that would result in overlapping like that. I believe that describes the situation, at least in short. To fix it, you want to use the collision detection system only as a way to respond to collisions (e.g. pushing solid entities apart, taken damage from projectiles, etc.) and use something else like distanceTo() for the interaction range. You can use me.collision.quadTree.retrieve() to gather a list of potential candidates for performing distance checks. edit: I had mistakenly asserted that onCollision will not be called on the same object that calls me.collision.check(). The handler is definitely called on both entities when they collide. You can see the implementation here: https://github.com/melonjs/melonJS/blob/97ede483f5798651e7a7c225df2bb77df66a4a27/src/physics/collision.js#L486-L492
  8. Parasyte

    Hybrid GFX test - scaling tilemap

    @Growler I think you might want to try it the other way; Set the video mode into the highest resolution supported, and scale up the tile background layer. I don't have any code on hand for this, and I'm not 100% sure it will work with collision shapes and stuff, but you definitely want to go with this approach. Going through some old github issues, it looks like the new Renderable transformation matrices will make this significantly easier to work with: https://github.com/melonjs/melonJS/issues/335#issuecomment-231292730 The problem you are facing in the screenshots is that the canvas size is very small, and you're stretching the whole thing, making big chunky pixels. Scaling down a GUI element onto that canvas is the same thing as scaling the image down in photoshop, and then scaling it back up with nearest neighbor (this is the "stretching" that I just described).
  9. Parasyte

    How do I tween the rotation

    I used it in Neverwell Moor for the intro scrolling: https://github.com/blipjoy/nm-prototype/blob/gh-pages/js/objects/screens.js#L357-L384
  10. Parasyte

    How do I tween the rotation

    The me.Tween class provides a callback that is called with a delta on each frame. The delta can be passed directly to the rotate method; no need to manage state on the class at all.
  11. Parasyte

    Do you build your UI's in MelonJS or DOM?

    For a quest log, yes. For other bits of status GUI, no, probably not. You want to avoid moving DOM elements as much as possible, since that will cause the UA to reflow the DOM. Status bars are easy to render in melonJS, using either the canvas context drawing methods (like fillRect()) or by clipping a texture. Using the melonJS font classes are also pretty decent performance-wise (except when you want to update the text on every frame, that doesn't work well with the WebGL compositor).
  12. Parasyte

    Do you build your UI's in MelonJS or DOM?

    Simple elements like buttons can be implemented with the melonJS GUI_Button class. The advantages with this are immediate feedback (DOM click events have a delay on mobile devices), and they use the WebGL compositor (great for all-in-one über textures) For more complex UIs, use the DOM. DOM should definitely be in your toolbelt for rich GUIs. The advantages are obvious, and there are very few disadvantages (more like just caveats). It's great for any form input fields, scrollable areas, etc. DOM also has the advantage that the text rendering is really fantastic, especially with web fonts, and certain character sets (CJK, RTL, etc) One of the caveats you might run into is that by default all DOM elements consume pointer events. There are some useful CSS properties that can help you workaround it if needed: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events and https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action
  13. Parasyte

    Fix position after scale

    If you are using the collision shapes for pointer events, you can create a plugin to patch me.input.globalToLocal() to apply the same scaling transformation. This won't make the debugPanel render the collision shapes scaled, but your plugin could also patch the debugPanel's draw method to apply the scaling transformation, if you needed to. If, however, you aren't using pointer events, why would you want to scale the collision shapes at all?
  14. Parasyte

    Run without rendering (for online game)

    I think you will find it significantly more difficult than it appears at first. I'm not trying to discourage you, that's just the reality. But if you can manage to make it successful, then that is awesome.
  15. Parasyte

    Run without rendering (for online game)

    Out of curiosity, how do you expect running melonJS on the server to prevent cheating? This is a topic which I have studied fairly extensively. Unless you implement a mechanism to actively address cheating, you're going to get a very sad surprise one day when your players start complaining about cheaters. For starters, here's a short list of relevant resources on the subject: Deterministic Lockstep Lag Hacking Pick your favorite anti-cheat tools; EAC, Punkbuster, ... To followup with an idea provided in that Stack Overflow answer, running the game only server-side is effective against cheaters if you can guarantee low latency while streaming an audio/video feed (or the procedural equivalent). But that's way beyond the scope of what melonJS intends to provide. By the way, are you familiar with the concepts of prediction, dead reckoning, and jitter buffering for networked multiplayer? If you miss these, you're going to have an unpleasant experience because the network is unreliable. Once your game goes multiplayer, you've entered the realm of distributed computing. And as with the CAP theorem, you can't sacrifice partition tolerance. This is a fun can of worms that many platform engineers will spend their entire careers learning and dealing with. Isn't it amazing how extending a simple game to play on even two computers suddenly raises the complexity exponentially?