mattstyles

Moderators
  • Content Count

    1633
  • Joined

  • Last visited

  • Days Won

    20

Everything posted by mattstyles

  1. Have you tried profiler to see where the bottlenecks are? If you're testing on the same device, the only difference being the browser and a webview contained within a 'hollow' app then we could naturally assume not too much difference, not on modern devices anyway (I've done this a couple of times and never had a problem, but, on the inverse, I've never done anything to strain the device either so that experience is probably not too relevant here). My understanding was that CrossWalk was deprecated as newer (as in, a couple of years at least, I think) devices don't need it, they'll use the same webview that Chrome uses. I'm not an Android developer so maybe there are some magic settings somewhere but I doubt it, Android are pretty cool with cross-platform utilisation, its just that the crappy Android platform hasn't really been good enough to support it until lately. Shame that crosswalk deemed it necessary to take down all their stuff without any sort of redirection, a blog archive (and a redirection) in git would have been nice and would probably have helped here. Ho hum.
  2. Pixi definitely does (or did) as I used it a couple of times, I would also imagine Phaser would have no issues being used for this purpose. Google are hot on making sure you bundle correctly (which we all should be). How are you bundling your code in to the zip? If you use a tool like Uglify or Closure (yep, Google are still pushing that) then you get dead-code removal with no real effort, although from the error report can't be totally sure thats what the issue is.
  3. Without meaning to seem terse but isn't the solution here obvious? Disable zooming and scrolling.
  4. I've done a few of these for clients without any real issue as the standards Google set out are all very straight-forward standards that we all should be following anyway. It has been a few years since I've done this but from the link you shared only the name has changed, not the standards. The guidelines are really clear and the verification process gives you (or, at least, it used to, I don't why it would change) detailed steps where your product does not meet the requirements. What did the verification process come back with for you to fix?
  5. If an 'adequate' amount of time has elapsed then I think it makes sense, it turns their license in to what is something like an 'early access' license (and, by that, I mean, they get it before everyone else, not like steam early access which is before its ready), which almost certainly isn't what is written in the license but it almost certainly isn't prohibited either. As you have a good relationship with them, maybe ask them what they think and how they think they might react? I'd like to say that they understand business and you're just driving profits and that it is all really rather understandable and totally normal for you to make enough money to feed yourself and buy a few nice things, but some people are hard to judge. For what its worth, so long as a decent amount of time has passed since the initial (and often only) license was sold I don't see any conflict with attempting to monetise your back catalog. Keep them sweet by promising lots more top notch games they can license before everyone else
  6. It's actually a trickier question than many assume, due to asynchronicity. Ignore Pixi for now, Pixi is for rendering and that is usually the easy bit. What have you tried so far?
  7. I have a slightly different css snippet pinched from 'I do not know where' -ms-interpolation-mode: nearest-neighbor; image-rendering: -webkit-optimize-contrast; image-rendering: -webkit-crisp-edges; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: pixelated; Not sure where I got it, probably CSS Tricks. Don't think I've ever applied it to a canvas though.
  8. Procedural generation can be a load of fun, but its a butt-ton of work to get working well. You could even use a genetic algorithm (GA) to create levels, have an automated actor play them, test the 'success' of the actor using fitness functions and then loop that process until you get levels (again, based on a heuristic function) that are fun to play. The up-shoot is that you can, potentially, create a near infinite number of levels like this. Or at least generate a manageable amount (say, 30) and manually curate them. Depending on how good your heuristics are you can create levels that are harder or easier for humans to play. It's a ton of work though. So depends on your mindset. Some crazy people find that a wonderful coding challenge.
  9. Procedural Generation. Enter the deep deep pit that is procedurally generating all of your levels, and the everlasting plight to make them interesting and fun.
  10. If your goal is to develop games then jump on it, any company that offers internship probably can support you, but be sure to clarify this (explicitly ask about how they will help you develop) before accepting. Some things to consider: * How long is the internship for? Can you afford to go unpaid? (or the flip side, its a competitive market, can you afford *not* to get the experience?) * What is their personal development plan for interns? How much input do you get in to that? * Do you have other offers on the table? Or are *very* likely to have in the short-term future? * How actively are the company hiring? Is there a decent chance at getting a job with them following a successful internship? (the answer here is almost always yes, just make sure they pay you correctly should you get a job offer at some point, gaming isn't the highest paid development role but beginners usually short-change themselves, weigh it up with 'not' taking the job, but always make sure you get paid correctly, this is way easier said than done) The market for any developer is reasonably competitive, gaming even more so, having demonstrable coding with live applications is a huge boost to your CV, not to mention the experience itself should, hopefully, be a very positive one. edit: Actually, I should clarify my point on payment, favour good experience over pay at the start of your career, if a company offers you a superb level of support with ongoing and regular training and excellent mentors, jump at it, even if it slightly under paid. Don't chase the cash too early, you need to ensure you hit the relevant level of developer skill and experience in a couple of years so that you are in a strong pay negotiation position later on. In the long-run you'll earn way more than squeezing salary at a crap company early on, not to mention you'll likely be far happier this way too.
  11. Howdy, sounds good. What methods did you use to get your map generation?
  12. I'm still playing with various different ways of representing maps and have now come to handling entities within maps. Naively I have the static 2d tilemap and I have a list of entities that are just an array of all entities currently in play. My question is about how to relate the underlying map structure with the entity array: Should I tie the two structures together? i.e. Should each tile have an array with a load of references to instances within the entity array? Or should both of these structures be entirely independent? How do you do it? What are the pros/cons you have found to each approach? Entities within tiles const entities = { <id>: <entityData> } const tilemap = [ <tile<tileObject | array:entityId>> ] i.e. const entities = { 'id1': { name: 'an entity instance' ... }, 'id2': { name: 'another entity instance' ... }, ... } const tilemap = [ { tileType: 'stone', entities: [] }, { tileType: 'ground', entities: [ 'id1' ] }, ... ] The advantages I can see is that rendering and access could be simpler, i.e. rendering can just iterate the tilemap, draw the base tile, then iterate that tiles entity list, perform a lookup on the entity object (or an array and perform a find operation on the id) and draw that entity at the current tile position. Similarly, if an entity is at [10, 10] and can view 1 tile in any direction then I can just use a tilemap search function to find the [3, 3] block of tiles that that entity can 'see' and they'll also get all the entities in that area as well. Downside is that movement now becomes harder as I'd have to update the entity data in the entity object/array and also change references in the tilemap (i.e. remove from old location, add to new location). Additionally, would you make any distinction about static vs dynamic entities? i.e. a cave on the tile map could be a tileEntity that is pretty much static, whereas a creature/enemy/ally would be more dynamic, would you differentiate between entity types? I can also see that this sort of system can be quite easily generalised to allow tiles/entities to have inventories, but I am a little worried about creating two-way links between 'things' in the game world. Any advice you have for me would make a good discussion
  13. @b10b yep, thats it exactly. I have a central 'store', which is just a big object, technically you could pass class instances (or functions) through as well but I'm not sure the exact downsides of that (easy serialisation is one, but could be worked around easily enough). Re-rendering is a side effect of changes to that central object and will only occur when changes are detected (standard React rendering, which is the same as many true FP languages). You could have both systems side-by-side and have a more manual system to 'tell' certain UI elements to that they need to re-render, I've tried that too with varying success. I think, in my case at least, I could get a lot of benefits from memoizing some transform functions as I'm effectively running the same thing several times each render tick.
  14. Yeah, only issue I have with that is that I only pass data around, not classes, and I'll have to sacrifice quite a lot of good stuff to be able to do it in a different way. I kind-of end-up in a similar place though with utility functions, but they generally run to the signature of: getCell(data, meta, position) // Could be curried: getCell(data, meta)(position) // Data could include meta (height, width etc for example) getCell(data, position) getCell(data)(position) The only difference is that I have to specifically pass in the data and meta for the map, rather than rely on `this` and grab it from the instance. It's a good point though, and there are multiple advantages for the class-based approach. I _think_ a good half-way house for me would be to expand the `data` object shape to include any meta-data about the map structure (I currently end up passing the raw data array—or array of arrays, whatever—and also supply meta, which is, to be honest, a bit annoying). My current patch code is reliant on being a 2d array, but I could get rid of that with a few more helpers and passing more information in via the `data` variable: /** * Gets a patch of tiles based on an initial [x, y] location * @param data <Array<Array[Tile]>> the 2d raw map * @param position <Array[Number, Number]> [x, y] position to center on * @param dim <Array[Number, Number]> patch size. Defaults to [-1, 1], can be * used to alter the center. * @returns <Array<Array[PositionTile]>> */ export const getPatch = (data, position, dim = [-1, 1]) => { const [w, h] = [data[0].length, data.length] const [x, y] = position const [min, max] = dim const patch = [] for (let i = y + min; i <= y + max; i++) { for (let j = x + min; j <= x + max; j++) { const tile = getPatchTile(data, [j, i], [w, h]) if (tile) { patch.push({ ...tile, x: j, y: i }) } } } return patch } So I think it works pretty similar to your method, albeit without classes and instances being involved. There are a couple of improvements I can see immediately, I'm effectively passing too much to `getPatchTile`, which also does bounds checking, and I don't like imperatively using nested for loops (which litter the codebase) so they could be generalised in to a helper function also. In any case, I'm happy with scrappy code as this is mostly a POC but it is interesting as it exposes that there are indeed many different ways to skin this cat, and many of those ways aren't clearly better or worse than the other ways. Trade-offs and decisions.
  15. I hadn't considered the recreating of arrays, I will effectively be recreating the array each operation, although I may be able to optimise that if it becomes a problem. For my current project, like yours, it isn't a top priority, but might be in subsequent ones.
  16. Is representing a 2D map using an array of arrays `[][]` really that nasty? My knee-jerk reaction is that it is pretty nasty and I tend to always represent maps as one-dimensional arrays, however, whilst there are some advantages there are also some disadvantages, mostly around access to the structure as to get an [x, y] location involves knowing the dimensions of the structure i.e. var size = [2, 2] var data = [1, 2, 3, 4] var get = (x, y) => (y + size[0]) + x This is fine, but any time I want to use the map I need to also know the intended dimensions, which is just another thing to carry and pass around. So... what things are nasty using nested arrays, my requirements seem to suggest it would be fine: * I am not converting the map i.e. I am not rotating, shearing or skewing the map in any way * My map dimensions are known ahead-of-time and never change during the life of the map * I am generating the data myself, so working with a pre-existing structure/representation is not a concern Using nested arrays mean I can access via [x, y] trivially and dimensions of the map are easy to ascertain by querying on array.length. So, should I get over my disgust at using `[[],[]]` nested arrays and just get on with using the right tool for the job?
  17. Also, love the typo in the title, a new sign-in method, sing in to your microphone to gain access to stuff! 🤣
  18. I wouldn't expect `.middleware()` to do too much either i.e. it shouldn't be super-problematic if you used a different (JS) serving solution like koa or hapi etc etc etc
  19. I'm really surprised, but I've just been reading through some parcel issues and the actual response seems to be to fire up a separate static file server. The argument given (in one issue, with a specific use-case) is that this matches what you'd do in prod. I actually disagree. I want to bundle things up, with the index.html that parcel dictates you have (no dynamically generating it), and do exactly as you have in code. With a separate dev server running you'd have to change urls based on whether you're in dev or prod mode which kinda sucks. Which kinda leaves you (in dev anyway) with two options: * Import the json as you suggest, which bundles the assets and may not be what you want * Set up static file serving (which is trivial) but also have to handle asset paths based on dev vs prod builds, which is fairly normal for non-trivial apps, but sucks Ooo, I thought of a third, but its not quite zero-config: * Use parcel as middleware for an express app where you also serve the statics This would work well and isn't much above zero-config, most importantly it means you don't change your source code for dev vs prod builds. const Bundler = require('parcel-bundler'); const app = require('express')(); const file = 'index.html'; // Pass an absolute path to the entrypoint here const options = {}; // See options section of api docs, for the possibilities // Initialize a new bundler using a file and options const bundler = new Bundler(file, options); // Let express use the bundler middleware, this will let Parcel handle every request over your express server app.use(bundler.middleware()); // Listen on port 8080 app.listen(8080); (ripped from parcel docs, you'd have to add the static serving bit but thats trivial. https://parceljs.org/api.html)
  20. @rich this is probably one for you. I can't see anything obvious from inspecting network traffic. Chrome has recently gotten stricter on https to http stuff, I haven't checked in other browsers so not sure if it lies in there. It's probably some settings somewhere.
  21. I think you've maybe misunderstood how these frameworks get their output into your eyeballs. They *all* use canvas, 3d accelerated or not, its a canvas element they output to. If you want to learn how canvas and context works, dig in, its a great learning experience. If you want to get some meaningful output to the screen, use one of the many available frameworks. Creating these canvas rendering libraries is no small task, not small at all. It's a lovely technical task to undertake, but, its really tricky so you probably need to decide if you want to invest your time creating a rendering engine, or creating a game/app/whatever to use that engine. You should get an unbiased view here, plenty of people here have invested in making their own rendering libraries. If making a game is indeed your goal, use something like Pixi or Phaser etc to do the heavy lifting and focus your effort on making the game fun. Also, on nomenclature, I tend to differentiate between library and framework, although the line is often blurred. Phaser is a framework, it handles things like audio, rendering, user input, application structure etc. Pixi just renders stuff really fast, it is a library/module. To reinforce this, Pixi is contained within Phaser 2, and is just one part of it. Your outlook on coding dictates whether you are more drawn to using a framework vs consuming libraries and, in effect, creating your own framework from those pieces. Pros and cons to either approach.
  22. With the popularity of lambda-based APIs, i.e. stateless idempotent APIs that run only when requested rather than all the time (see, serverless deployments), database-as-a-service is booming. Try a search for database-as-a-service, there are loads of providers, both AWS and Azure will offer comprehensive services to allow you to store arbitrary data without too much infrastructure work, there are probably smaller and cheaper providers also, I'd also expect you can find providers that offer one-click deploys of services. I'm not sure exactly how these work, you'd probably also need to deploy a small API to handle taking your client data and stuffing it in to a database. Services like netlify.com, apex and now.sh can make deploying these sorts of lambda functions much easier than it used to be (they're superb for client-side only apps, like many games, too). They make 'one-click' deploys pretty easy, with the caveat that they are transient lambdas, not actual servers, so you get no persistence (hence the stateless bit). The biggest problem is handling how these things connect, tools like Kubernetes and Terraform (and even docker-compose) can handle orchestrating spinning up these services and connecting them, but I doubt you'd need to go that deep. Most of these deploy tools can give you static IPs to handle connections manually, and you'd probably want to setup DNS to point at those IPs anyway to make things a little more manageable. Again, there may be providers that can abstract all of these sorts of things away from you and give you 'one-click' deploy style. I've no idea on how effective, or costings, for this sort of thing. I just did some quick searches (I find this sort of stuff super interesting), https://www.netlify.com/blog/2018/07/09/building-serverless-crud-apps-with-netlify-functions--faunadb/#2-set-up-faunadb, this outlines all the steps you'd need to get all the pros of serverless, you can use different bits and pieces of course, but I think this covers the base steps to get it up and running, and make deploying updates and new features to your codebase pretty neat (I only skimmed that article, I'm not sure if the client interacts directly with the DB or goes through an API service also in the project, either way would work, you'd probably prefer to go direct from the client if you can, but there are cons to that).
  23. Great idea, most programmers tend to enjoy a spot of gaming, using games as a medium for teaching coding sounds like a winning combo to me
  24. mattstyles

    Isometric collision

    Isometric collision is nothing special, I'm not sure you're suggesting it is but this is just (I think) a generic question on handling collisions, more specifically, in a 2D world. You need a couple of things to things to be able to do collision detection: * A map representing the state of entities in your world. This includes actors/entities and the map itself. * A representation of the desired 'next step' for an entity. You can separate your code more, but, the crux of your current problem looks like it probably lies in a few places: * In your 'keyup' (i.e. user input handler) function you manually mutate the position of your Player Character * You pass `keypressed` into your render function, although doesn't look like you use it, which is good, don't use it there. You look like you're trying to put collision handling code in your render method, don't do this either, keep your render method just 'dumbly' rendering the current state of the game * You have no concept of an update function, you almost certainly want to create this concept. * You treat your Player Character as a special case, this isn't wrong per se, but it is better to treat it as 'just another' entity/actor in your world. So, this leaves you with 3 distinct pieces (you currently only have 2) * Handling user input * Handling world updates * Rendering the world A super simplistic game loop would be: while (gameRunning) { updateWorld() renderWorld() waitAndHandleUserInput() } In the beginning, this is how they worked. You don't want to block on waiting for user input, and you aren't by using an asynchronous keypress handler. This is good. When you handle user input related to moving the PC (Player Character) you need to define a 'desired' location to move, i.e. turn that keypress into an action (a movement action) associated with the PC entity. In the update function (which you will create) you want to handle all the desired actions on entities in your world, for the sake of simplicity, this is going to handle the movement action for your PC. So, you see the PC has a movement action and where it wants to move to, this triggers your Collision code i.e. you query the map to see if the PC can move, if so, update their position, if not, do _something_ based on the type of collision (i.e. in to a wall, do not update position, in to a monster, add a 'battle' action to the queue of the PC). When you have handled this action you remove it from the PC action queue. The update function loops over all entities and drains their action queues, it then exits. Now you render the world. As you have already updated the player position (or not, depending on the outcome of a possible collision) you just render the world as it is and your users will see their beloved PC moving around, bashing in to things, starting fights, casting spells, shooting guns, picking up items, communicating, transmutating, defecating, whatever it is that they can do in your game. The above isn't the only way of doing things, but it is probably the most common. http://journal.stuffwithstuff.com/2014/07/15/a-turn-based-game-loop/ this is nice additional reading, most of the above is covered there in more depth, and with working code examples too, its a superb article (the author is also great, I highly recommend following his writings).