chriswa

Members
  • Content Count

    15
  • Joined

  • Last visited

  1. chriswa

    Farmer's Journey

    Gorgeous! Well done! The only criticism I can offer is: (1) a progress indicator on the loading screen would be nice and (2) the camera should probably be panned up a bit: I found myself wishing I could see further ahead, and I noticed that the bottom half of my screen wasn't helpful for gameplay.
  2. chriswa

    mmorpg advice 3d edition

    One advantage of using the same language to write your client and server is that you may be able to share code between them (e.g. for client-side prediction of input validation and game logic.)
  3. chriswa

    Improving performance of MMO-style canvas game

    I wasn't able to figure out how to throw a spear, as shown in your video, but I did walk around a bunch, and opened and closed a chest. I didn't register with a valid email, I just typed "qwer" and "asdf" into your two textfields. I pasted mrdoob's stats.js into your page and got a consistent 75 fps (that's the highest I seem to be able to get in Chrome) with no noticeable frame delays. Granted, I have pretty beefy hardware, so YMMV. I made a Zelda 2 clone 5 years ago with 2d drawImage calls, clearing the canvas every frame; I had at least double the drawImage calls I think you're using and it ran very quickly on older (at the time) hardware, including my phone. I'm not sure what it's costing you to use 3 canvases. Any reason why you're doing that instead of just compositing everything onto one canvas? I'm also concerned about your setTimeout loop. I think it's generally preferable to have a pure requestAnimationFrame loop and accumulate elapsed time, updating your world state when the elapsed time reaches a "tick" and rendering everything every animation frame. (As a bonus, this lets you do interpolation between update steps for even smoother animations.) I did notice a significant delay in the game responding to my keypresses. It took roughly 800ms for my character to move one tile, and when I tried queuing up several commands, some of them were dropped. There was also some very noticeable delay loading in new map chunks. I'm guessing the delays I experienced were related to your networking. Chunk loading can be solved relatively easily by pre-loading a larger border of tiles around the player, but not rendering them yet. Input lag is much trickier to solve. One common approach I've read about to deal with these kinds of delays is to predictively start player animations on the client side immediately, and deal with the server's response when it gets back. With the information the client has about the world, it can easily decide whether you will be able to move to the next tile or if a wall will prevent you. This gets tricky when there's hidden information (e.g. invisible landmines or invisible walls) or random events (e.g. hits, misses, and damage rolls.) This works well for some scenarios and poorly for others; for example, if there are invisible landmines that explode when you've finished your move, you'll probably get a response back from the server before the player finishes moving to the next tile, so that should be easy to resolve; however, invisible walls may cause players to "rubber-band" back after seemingly travelling part-way through the wall (or all the way through, if their connection is lagged more.) And things get very, very tricky when you take other players' actions into account. Modern FPS game servers temporarily rewind time when you shoot your gun to compensate for your lag, to see if your bullet would have hit anything. This means you don't have to lead your targets to account for your network latency, but it also means you can get shot immediately *after* jumping behind cover. P.S. Cool to see you're using Vue for UI, I think I might do the same for my current project!
  4. chriswa

    How many collision functions should I use?

    I'm not sure how to answer "how many", but I can suggest that you start with the simplest solution (probably checking every sprite against every other sprite,) then test it on your slowest target platform and optimize only as required. Some optimizations you may consider: do bounding box checks first, before more expensive but accurate collision checks filter collision tests for sprites which have no collision response according to your game logic (e.g. player with player bullets) filter checking stationary sprites with other stationary sprites make sure you're not making redundant checks (e.g. if sprite A collides with sprite B, there's no reason to check if B collides with A) separate physics updates from animation frames so you can run your physics at a slower rate (e.g. 30fps or 20fps) than your rendering frames (blend between physics steps to achieve smooth movement when rendering at a higher framerate) (see https://gafferongames.com/post/fix_your_timestep/) replace pixel-based collision tests with math-based geometric tests, building up a "hit area" for your sprites out of circles, triangles, etc. avoid calculating square roots when figuring out distances if you can deal with the squared values instead (e.g. if you're sorting, sqrt doesn't matter; if you're checking against a circle's radius, square the radius instead) store your bounding boxes in a quadtree to avoid checks between distant objects Hope this helps?
  5. chriswa

    When to use a database in a game

    I think the simplest solution would be to send the player their player id when they're first added to a game. Store it persistently client-side (for example in localStorage,) along with the game id. When connecting, the player should send their last known game id and player id from localStorage (if they have one.) On the server, check for a matching game id with a matching, disconnected player id. If you find one, reconnect the player, sending them a snapshot of the game state so they can keep playing. Otherwise, ask the player for a game id as normal, ultimately connecting them as a new player, with a new player id. If your game ids and player ids are likely to conflict (e.g. always 0 and 0 for the first player of the only game on the server,) you may need to worry about players mistakenly hijacking disconnected spots when they are intending to enter a different game. You could make this issue statistically impossible by generating random ids. P.S. I don't think you need a database for this game, unless you want to survive server crashes, or start tracking win/loss statistics for your players.
  6. The OP recommended WebStorm. PhpStorm = WebStorm + PHP + Database support If you don't need PHP or database support, Webstorm is better because it will load slightly faster and have fewer confusing menu options
  7. chriswa

    When to use a database in a game

    Is your game turn-based or realtime? How much data will you be storing and how frequently will it change? What is acceptable behavior if your server crashes unexpectedly? How many simultaneous players do you want to support? How many non-simultaneous players? A very simple solution could be to write a JSON file to disk ("saves/userid.dat") with their current state when a player disconnects. When they connect, look for a JSON file with their user id and load their state. If you wanted to save every player's current position 30 times a second (in case the server crashes,) quickly search for any players near a position, or support robust trading between players, this simple file-based approach isn't going to work. Databases basically improve read speed and write safety, but they have tradeoffs, including making your project more complex. I think it's important to determine what your requirements are. P.S. Mongo doesn't support ACID transactions (except within a single document,) so it can't safely support trading, at least not perfectly.
  8. chriswa

    How many simultaneous sprites can Phaser 3.6.0 handle?

    I don't see more than 1000 sprites in your screenshot. Are you drawing off-screen sprites too? That can slow things down quite a bit. Are you able to skip drawing sprites outside of an (AABB) rectangle which represents your viewable screen size?
  9. chriswa

    How many simultaneous sprites can Phaser 3.6.0 handle?

    Phaser's docs explicitly mention 1000 sprites: "...you only really need to use a SpriteBatch if you have over 1000 sprites that all share the same texture (or texture atlas)." https://phaser.io/docs/2.6.2/Phaser.SpriteBatch.html
  10. chriswa

    How many simultaneous sprites can Phaser 3.6.0 handle?

    Are you using SpriteBatch? If it's implemented correctly in Phaser, batched sprites (i.e. sprites that use parts of the same texture) can be drawn with a single WebGL draw call, which can mean tens of thousands of sprites without a noticable dip in framerate. I use a Chrome extension called Spector to inspect the WebGL calls made by web pages, which can help you determine how much room for improvement there is available.
  11. Lesson 5 is the first lesson with a texture, so my guess is this is a CORS issue. You're probably using the file:/// protocol to view the tutorial HTML files? Try using a simple HTTP server to access them via http://localhost instead. Check your browser's developer console for error messages.
  12. chriswa

    What the best 3d framework?

    Why do you want to avoid WebGL? Knowing a bit more of your specific requirements and motivations would be helpful in answering this question for you.
  13. You can squeeze a surprising amount of performance out of raw WebGL, especially for tiled backgrounds and sprites which share the same sprite sheet. In my experience, some WebGL-accelerated frameworks sometimes do a poor job of rendering these things: namely by making way too many draw calls. However, using the 2d canvas API is almost always going to be slower than WebGL. I think you made the right choice using the 2d API for your first game!
  14. That sounds like premature optimization. I would recommend ignoring pooling until you've determined that garbage collection has become a performance problem. I recently implemented pooling for some large array buffers, which eliminated the GC spikes I was seeing, but I didn't bother pooling any smaller structures. If performance becomes a problem again, I will re-evaluate that decision.