Jump to content
  • Advertisement


Popular Content

Showing content with the highest reputation since 05/25/19 in all areas

  1. 2 points
    Hi fellas, We’d like to share the story of a game anticipated to become somewhat a hit, but a series of ill-favored circumstances we’re gonna show below ruined all our expectations. 1.5 programmers and 1 lead game designer had worked on the project, plus 1-2 artists had been engaged in the development on a part-time basis. The rest of us had been focused on other projects. It all started after we successfully released our second free-to-play title Ninja Dude vs Zombies back in June 2016 exclusively on the App Store: the game was warmly welcomed by the gamers’ community and featured by the store several times throughout summer and early autumn. It was our first self-released mobile title to put our project management and publishing skills to the test. We had updates plan for 3 months ahead — we had been prepared to support the project further. Elated with its success we’d been really looking forward to releasing its Android version along with some major features like bosses, new characters, super weapons, and some others. Ninja Dude vs Zombies early Zombie Boss prototype Ninja Dude vs Zombies early PvP prototype Lesson 1. Have a plan B In late autumn we had developed first prototypes of PvP mode. Shortly after we realized that this feature would require more burden-hours that we originally planned in terms of balancing and server side. As Ninja Dude was not the only project we’d been working on, we had to prioritize to keep the studio afloat between this and other titles needed maintenance and support (released under publishing agreements; imposing certain obligations). What’s more, we grasped that our UA and promotional resources had been limited. In other words, we couldn’t afford user acquisition and promotion campaigns both in terms of funding and burden-hours to help us boost the major update and especially the Android version. That being said, we started looking for a publishing partner to help us roll out the Android version, for starters. It was the beginning of 2017. This idea didn’t seem irrational at the time, but we wish we’d known how it’d turn out for us. After about a couple of months spent of pitching the game to various publishers and negotiating the terms we entered into the contract with really great guys: they had awesome games in the portfolio with the plethora of installs and Ninja Dude vs Zombies gameplay mechanics matched their portfolio perfectly well. The main thing we agreed upon while signing the contract was that it’ll be a full-fledged sequel of the game, not the update. It’d be easier to get a chance of being featured that way. The publisher relied heavily on the platforms’ featuring in its promotional and UA efforts in addition to cross-promotion within its already released titles. The development flared up again with renewed vigor. This time it was not only about gameplay features, but a complete overhaul in its visual style to make the game really feel like a sequel. Ninja Dude vs Zombies 2 core gameplay screenshots In December 2017 the key programmer of the project was hunted down by another bigger game development company (damn you, LinkedIn!) — we had nothing to do with that: our team member was offered higher salary and working conditions in a city bigger than ours. It all happened really fast, and of course, we didn’t find the substitution soon enough to keep up with the development pipeline. So it stalled for quite a while as it was really hard (as it turned out) to find a skillful Unity programmer in our region. After losing the programmer the coding was divided between the other 2 team members. But they could only spend about 1-2 hours a day on this project. You wouldn’t believe it, but the game was still in development when it's lead designer left our team. It was the final nail in the coffin. It was in October 2018. Throughout all those months we’d been in contact with our publisher sending them intermediate builds showing how we’re progressing on a monthly basis. They evaluated and provided feedback being quite supportive. Until the early spring of 2019. We received a letter from them where they informed us that they can no longer live up their promises under our contract: situation on the game market had changed, UA costs had increased, and it had become more difficult to get featured by the platforms. They offered us 2 options: Either terminate the contract and publish the game on our own; Or soft launch the game on our own and if the metrics are prominent keep working with them. Frankly speaking, we agreed with them and it was mostly our fault that we had been developing the game for almost 2 years. We had no plan B, so we just decided to finish the game and release it out to the wild without having any high hopes for Ninja Dude vs Zombies 2. Lesson 2. Start spreading the word about your game as early as possible We thought that our publisher would have started some early talks and sneak peeks about the game. We’d seen similar activity with its other titles on forums like TouchArcade. That time, however, the guys remained silent and no gamer knew about the upcoming sequel of the game. We were so deeply engrossed in the development of the game and working on other projects that we didn’t even announce the upcoming game on our social pages. That’s how assured we’d been that our publisher would start spreading some early news. Another thing here is the contract terms. We got used to believing that we had not been eligible to spread the word about the game prior to our publisher started doing so. It’s like breaching an embargo and releasing an article prior to the due date. If someone from the publishing side is reading this, please share your thoughts on the matter. Maybe if we had some early access or beta test program running, we’d already had feedback on the game and supporters waiting for the game to be released. The more so, because nowadays both stores provide such opportunities. Besides, we might have submitted the beta version to some game development contests out there with a publisher’s permission to gain some extra publicity. Lesson 3. Stay in the closest possible contact with the publisher This seems pretty much obvious, actually. But yeah, we screwed this up too. In fact, prior to entering into a publishing deal, we contacted the devs who had already worked with the publisher. They mentioned that the publisher had not been responding in a timely manner at times. We ourselves were not as proactive as we could. Talking with the publisher over Skype once or twice per month about the ongoing development process is not enough. The same thing goes with emailing them the versions of the build once a month and waiting for their reply for another month. Being proactive when it comes to communications with the publisher would have saved us time if we knew earlier that they’re no longer capable of fulfilling their obligations under our agreement. After their uncheerful letter, we’ve decided to complete the game and release it without any tests and almost without any prior promotional efforts: just a press release, a couple of tweets with gifs, and submissions to various industry-related portals. We just didn’t see the point in managing the project for another month. Nevertheless, the game was featured by Apple in several categories across multiple countries (well, except for the US), but it didn’t actually end up well for the game: its poor balance leads to players churning shortly after the first boss; its untested store creatives lead to faulty conversion rates. Faulty conversion rates in the App Store Zombie waves data the released sequel. Only 11% of players make it to the 2nd wave. Players breakdown by skill levels. Almost all the players stopped at level 1.
  2. 2 points
    It has been quite some time since we posted something. And it's true, for the most part we didn't really do much. Work on Lyfe just wasn't such a high priority as university for example. But we're back. And with that we switched engines. To be fair, there wasn't much work we had to replicate. Most of the time we invested so far was learning how to handle simple things in Unreal when we all had way more experience in working with Unity. A mistake. But I think we're on the right path now. This of course means there is no real gameplay footage to show. The actual gameplay is simply less of a priority compared to the editor so we're focusing on that and trying to get a stable version running. For more information on the concept behind the cell editor or at least the basic sculpting check out this entry. I won't go into detail about it here. Today I will focus on the technical side of implementing metaballs and having the calculation run on your GPU rather than your CPU. I'm doing this partly to show we're actually working again but als since it took me way too long to figure out how this works and I didn't have good resources. So feel free to use our code and adapt it to your needs. Anybody here who doesn't know how metaballs work or what they even are? Here are some links for you if you're interested: metaballs (what even are they?) metaballs in blender (a bit more detailed) maths behind metaballs Let's start with the basics: The basic shape of the cell is formed by nodes that are connected to each other. Each of these nodes is the center/anchor for a metaball. This means each of these nodes exudes a charge in the field around it. This field is simply represented by points in 3d space. If two nodes are close to each other the charges sum up. This results in smooth transitions between blobs/metaballs. For more details click on the third link or write a comment. On to the C# script of our editor. This is where we prepare our data and read the chargefield once it's done computing. private float[] CalculateCharges(Vector3Int _resolution) { float[] charges = new float[_resolution.z * _resolution.y * _resolution.x]; List<SNode> nodes = baseNode.GetAllChildNodeMetaData(new List<SNode>()); int kernel = cs_Charges.FindKernel("CSMain"); ComputeBuffer nodeBuffer = new ComputeBuffer(nodes.Count, SNODE_SIZE); nodeBuffer.SetData(nodes.ToArray()); ComputeBuffer chargeBuffer = new ComputeBuffer(charges.Length, sizeof(float)); chargeBuffer.SetData(charges); cs_Charges.SetBuffer(kernel, "nodes", nodeBuffer); cs_Charges.SetBuffer(kernel, "charges", chargeBuffer); cs_Charges.SetVector("EDITOR_GRID_DIMENSION", new Vector4(_resolution.x, _resolution.y, _resolution.z, Meta_CellEditor.SCULPTING.GRID.SCALE)); cs_Charges.SetVector("basePos", transform.position); cs_Charges.SetInt("numNodes", nodes.Count); cs_Charges.Dispatch(kernel, _resolution.x / 8, _resolution.y / 8, _resolution.z / 8); chargeBuffer.GetData(charges); chargeBuffer.Dispose(); nodeBuffer.Dispose(); return charges; } So. Since the basis for metaballs is chargefield this method takes a Vector3 for the resolution of this field. We then make a float array of that size to give to our compute shader and have it filled there. List<SNode> nodes = baseNode.GetAllChildNodeMetaData(new List<SNode>()); This line simply collects all child nodes and stores their metadata in a simple struct that can be transferred to the shader. public struct SNode { public Vector3 position; public Vector3 distortion; public float cubePortion; public float radius; } This is how the struct looks. The information in cludes the position within the charge field with 0/0/0 being the center. The distortion/deformation of the sphere so if it's more of an oval. The cube portion, so if it's more of a sphere or a cube (not fully implemented yet) and the radius. Pretty simple stuff. int kernel = cs_Charges.FindKernel("CSMain"); Next we find our kernel within our shader so we can pass values to it and run it. The actually initialized this shader in an Init method beforehand. cs_Charges = Resources.Load<ComputeShader>("Shaders/cs_Charges"); ComputeBuffer nodeBuffer = new ComputeBuffer(nodes.Count, SNODE_SIZE); nodeBuffer.SetData(nodes.ToArray()); For this next part I can only recommend using ComputeBuffers. Just initialize it with the count of elements and the size of each element. In our case this is the size of 8 floats. After that we push our data into the buffer. ComputeBuffer chargeBuffer = new ComputeBuffer(charges.Length, sizeof(float)); chargeBuffer.SetData(charges); We do exactly the same thing for our charges. And this is where buffers come in handy: You can not only use them to get data into your shader but also to read it from there if you write it into a buffer. cs_Charges.SetBuffer(kernel, "nodes", nodeBuffer); cs_Charges.SetBuffer(kernel, "charges", chargeBuffer); cs_Charges.SetVector("EDITOR_GRID_DIMENSION", new Vector4(_resolution.x, _resolution.y, _resolution.z, Meta_CellEditor.SCULPTING.GRID.SCALE)); cs_Charges.SetVector("basePos", transform.position); cs_Charges.SetInt("numNodes", nodes.Count); Next we set the buffers in our shader. It's important that every one of these strings corresponds to a variable of the same type in your shader. If you only want to transfer a single value, you don't need to use the big ComputeBuffers. The simple methods SetVector/SetInt/SetFloat will do. This is actually where the naming of your variables is shown to not be the best: resolution isn't actually the relsolution but rather the dimension and together with the scale makes up the resolution. cs_Charges.Dispatch(kernel, _resolution.x / 8, _resolution.y / 8, _resolution.z / 8); And this is where we actually run our shader code. I'll behonest here and tell you that I'm not quite sure how these last 3 parameters work but so much: each one stands for the number of core groups. So basically we're using 8 groups of 8 groups of 8. So we divide what we need to calculate to split it evenly on all these cores. This becomes really important if you want the parallelization to work. chargeBuffer.GetData(charges); chargeBuffer.Dispose(); nodeBuffer.Dispose(); return charges; At the end we simply read the data our shader stored in the buffer and dispose our buffers to free the memory. Anybody familiar with C or C++ knows this is to prevent memory leaks. That is all the C# code basically. Simple stuff and no maths. It only get's worse from here on. // Each #kernel tells which function to compile; you can have many kernels #pragma kernel CSMain struct Node { float3 position; float3 distortion; float cubePortion; float radius; }; StructuredBuffer<Node> nodes; //node positions in world space int numNodes; float4 EDITOR_GRID_DIMENSION; //xyz are dimension, w is scale float3 basePos; //position of the base node RWStructuredBuffer<float> charges; float3 GridPosToLocalPos(float3 _gridPos) { _gridPos -= EDITOR_GRID_DIMENSION.xyz / 2.f; _gridPos *= EDITOR_GRID_DIMENSION.w; return _gridPos + basePos; } float CalculateCubeCharge(Node _node, float3 _voxelPos) { return 0; } float CalculateSphereCharge(Node _node, float3 _voxelPos) { float3 d; d.x = pow(_voxelPos.x - _node.position.x, 2); d.y = pow(_voxelPos.y - _node.position.y, 2); d.z = pow(_voxelPos.z - _node.position.z, 2); float r_squared = (d.x * _node.distortion.x + d.y * _node.distortion.y * 12.f + d.z * _node.distortion.z) / pow(_node.radius * 12, 2); if (r_squared < 0.5f) { return 1.f - r_squared + pow(r_squared, 2); } else { return 0; } } float CalculateCharge(Node _node, float3 _voxelPos) { float r = (_node.cubePortion * CalculateCubeCharge(_node, _voxelPos)) + ((1.f - _node.cubePortion) * CalculateSphereCharge(_node, _voxelPos)); return r; } [numthreads(8,8,8)] void CSMain (uint3 id : SV_DispatchThreadID) { float3 voxel = id; float3 voxelPos = GridPosToLocalPos(voxel); for (int n = 0; n < numNodes; n++) { int index = id.z * (EDITOR_GRID_DIMENSION.x * EDITOR_GRID_DIMENSION.y) + id.y * EDITOR_GRID_DIMENSION.x + id.x; charges[index] += CalculateCharge(nodes[n], voxelPos); } } So. This is the entirety of our shader code for the metaballs. We still need to tweak some of the static values so please, feel free to experiment when using this code. The struct at the top is basically our SNode. After that our buffers and set values follow. Note that nodes is just a StructuredBuffer while charges is a RWStructuredBuffer. The RW means read-write. So the shader can not only read the values stored but also write in there. I think the best way to go through this is from top to bottom. float3 GridPosToLocalPos(float3 _gridPos) { _gridPos -= EDITOR_GRID_DIMENSION.xyz / 2.f; _gridPos *= EDITOR_GRID_DIMENSION.w; return _gridPos + basePos; } This method simply turns a gridposition to a position in local space. Easy as that. Calculate cube charges is not implemented yet. (sorryyyyyy... We'll add how that works once we got it figured out.) float CalculateSphereCharge(Node _node, float3 _voxelPos) { float3 d; d.x = pow(_voxelPos.x - _node.position.x, 2); d.y = pow(_voxelPos.y - _node.position.y, 2); d.z = pow(_voxelPos.z - _node.position.z, 2); float r_squared = (d.x * _node.distortion.x + d.y * _node.distortion.y + d.z * _node.distortion.z) / pow(_node.radius, 2); if (r_squared < 0.5f) { return 1.f - r_squared + pow(r_squared, 2); } else { return 0; } } And here we simply calculate the charge one node exudes on one point in space. I myself am not sure about all the maths in there but again, you can read up on that by clicking on the third link at the begininng of this. float CalculateCharge(Node _node, float3 _voxelPos) { float r = (_node.cubePortion * CalculateCubeCharge(_node, _voxelPos)) + ((1.f - _node.cubePortion) * CalculateSphereCharge(_node, _voxelPos)); return r; } This function again calculates the charge on one point from one node but factors in the cube and sphere portion of the corresponding node. [numthreads(8,8,8)] void CSMain (uint3 id : SV_DispatchThreadID) { float3 voxel = id; float3 voxelPos = GridPosToLocalPos(voxel); for (int n = 0; n < numNodes; n++) { int index = id.z * (EDITOR_GRID_DIMENSION.x * EDITOR_GRID_DIMENSION.y) + id.y * EDITOR_GRID_DIMENSION.x + id.x; charges[index] += CalculateCharge(nodes[n], voxelPos); } } And finally we come to the actual core method. And here we find our 8/8/8 again. These values need to correspond to the ones when dispatching the shader. Otherwise you won't be able to use the id correctly. In your case the id points to the point in space we want to calculate the charge for. We use our GridPosToLocalPos here. This is important or all our beautiful metaball would be anywhere but where we want them to be. Below that we iterate over all nodes and sum up their influences on this one point in space. For a 200 * 200 * 10 chargefield with 10 nodes in it this code runs in less than a second. And that's why we use compute shaders, children. But for real, this would not be feasable when running on a CPU. But I'm 100% sure this code could be improved even further. Anyway, I hope this code helps someone who wanted to use compute shaders but didn't know how or wanted to implement metaballs. Cheers and keep on evolving.
  3. 1 point
    It has been a bit of a mixed week. Some of us are starting holidays and others have other obligations that has meant that last weeks progress was less eventful than previous weeks. Renceed finished some heavy AA guns before hitting the beach: Here is the “making of” video: We’re gearing up our social media pages so that anybody interested in the project can stay up to date with what we’re doing: A weekly blogpost to our Website (badbunch.net), Gamedev.net (https://bit.ly/2XlfZhU), and IndieDB (https://bit.ly/2ZAMCps). Twitter (https://twitter.com/BunchBad) is being invigorated for additional posts during the week. And of course our Discord (https://discord.gg/8KQuC9) is where people can get a lot of the info firsthand, usually in a post from the team member that created the content. Tallying up what we need have left before we open up the development build to the public the main two things we need are; 1) a larger map to host more players 2) testing multiplayer with as many people from a single region as we can get. There are rumors of super secret groups of gamers that have signed up to playest the next build version and help show where the largest network synch sins are, as well as how easy/hard it is to figure out the controls and other gameplay details. But we'd of course have to deny that such an event is taking place. Very early concept of a map by the great Joel K. This stuff it too early in the design process to be balanced, so changes to the layout will happen: Air mines are awesome! And somethings odd with the water shader... End
  4. 1 point
    Alpha Testing It’s been a busy time with our Alpha testers these last few weeks. Lots of feedback and ideas coming in. We’ve just come out with a new update for the Alpha version. This version is including lots of bug fixes and changes from the testers. One of the larger items in the recent Alpha release is the sound. We hand picked and replaced all sound effects and added many more, and ended up with over 120 new sound effects added, along with 8 tracks for the background music. We decided to pick most sounds from Pond5, as they had the largest and best database of sounds we found. In Lelantos and Aura we have introduced a new mechanic. ‘Portals’ are devices that transfer the Alien instantly to another location on the planet. On Lelantos the Alien needs to use them to find different areas that can’t reached by mining. On Aura, they are used for portaling into the Puzzle rooms. Once a portal is found, it will be displayed on the mini-map, and each will have a unique number so you can keep track of where they go. We’ve been playing through the full game now, to try to find how long the game plays for. For us, it takes about 10+ hours to complete, but looking at the Alpha testing data, people are playing it for between 10 -> 20 hours. So it’s looking like it’s easily going to play for 10+ hours. We are still looking for testers to help us, so if you fancy helping out, follow this link to see what to do: Alpha Signup Steam Our Steam / Wish List is doing well, and we are starting to get a nice following on there. We changed our release text to specify ‘Autumn 2019’ as we are now more confident we can achieve this time. The Steam Summer Sale is starting soon, so we are hoping that will bring some extra traffic and adds. Not seen our Steam page yet? It’s got all the info about SAMA including screenshots and our feature trailer video. Click the link below and check it out. Even give us an add to your Wish List if SAMA looks like it’s for you! https://store.steampowered.com/app/1047870/Something_Ate_My_Alien/ Social Media Back in May we did our first interview. @IndieRanger asked us if we wanted to do an interview, and we thought that would be a good idea to get out some info about us and the game. It was a bit nerve wracking, since this was our first interview, but it all went well and they did a nice write up about us. If you haven’t yet, go have a read about us. Click here for the Rob & Kat Interview We also got our first YouTube streamer, Fred! He is an Alpha tester and has done a few videos about the game and his views on it. With his comical commentary during the game play, it’s a nice start to our You Tube presence. You can find him here: Fred Impossible Next things The next phase of Alpha will be introducing some more ideas from the testers. These include modifications to the ‘Somethings’, new upgrades and some changes to the Aura world. Keep tuned to see them soon. We will continue to interact with our Alpha testers and get as much feed back from them as we can. Bonus: We also did a quick little ‘fun’ video of some behind-the-scenes development, and how the game looks in the Unity editor with a ‘3D’ look: Something-Ate-My-Alien-RoKabium-Games-DevInGame3D.mp4
  5. 1 point
    The results of my SEO experiment are starting to come in. A little background on the project yesterday I started an experiment of sorts. I went back and improved the SEO of all my previous blog posts as well as a variety of other things to try and improve my number of hits. You can read about my efforts here https://gildedoctopusstudios.com/seo/ . As you can see there was an extreme uptick in both unique sessions and page views. Sure my blog doesn’t have very many unique sessions and it currently does not make me any money but it’s just started. I figure give it time and see what happens. It’s part of my multi-pronged approach to reach my goal of making as much working from home as I can working a 9-5 programming job. It’s not something that I expect to happen over night but I figure if I persevere and try several different options to figure out what works best for me in time it will happen. The blog is one of the approaches that so far I am really enjoying. I love researching tech techniques and it gives me the chance to show off a little bit of what I’m currently working on. I’m really pleased with the SEO changes I’ve made. The SEO results are quite encouraging. It definitely is an immediate and effective way to improve the number of views on a blog. I’m really looking forward to seeing the results from it over a longer period of time than just one day. It wasn’t even a full day for that matter. My plan is to continue trying to improve my site’s SEO through some additional tips I found at https://backlinko.com/seo-techniques. Most of them are about improving the actual key words and key phrases that you use. So it should mesh nicely with what I’ve already done. I’ll post updates on the SEO techniques I’m using as I discover and implement new ones. The post SEO Results: Day 1 appeared first on Gilded Octopus. View the full article
  6. 1 point
    Development has been somewhat slow but managed to get some level building work done. Main stuff worked on over the past month: Fixed issue with clothing level location updates when human actor changes levels. Work to make sure actors are cleared out of levels before new level/game is loaded. Fixed bugs handling closing of Store & Inventory dialog boxes with Escape key. Resolved collision issue where actor collision records were overwritten by tile collisions Re-enable fading out effect for walls. Level building for Level 1 Human characters can sit down on the couch. There's still work to do putting the level together. There's a couple bits of furniture and such to put into place but I gut the basic stuff I wanted to get in before posting any kind of screenshot. In the screenshot below, I have the basic layout of the house as I previously had, the fade effect on the walls is doing what it used to, and I have the main PC able to walk over and sit down on the couch. Being able to sit is an interesting addition as it looks just fine for now and I can probably continue without concern but if I have characters with robes or any kind of long clothing it'll mean that clothing will require another left and right frame to look right. Which means I should probably change the way I load the data for clothing anchors to prepare for the eventuality that I'd have other animations to add requiring additional clothing frames. Which isn't all that difficult to do but would be a diversion I didn't expect. Probably going to leave that for the time being unless I find some character that really really needs to be able to sit while wearing long clothing. I think the next step is going to be getting the navigation data back in and the script back together so that after a conversation between husband and wife completes, the wife goes and picks up a DVD from the bedroom, goes over to TV to put in the disk, and sits down to watch the movie. I also had a cat in the earlier version following the husband around everywhere which I want to include again. Only after feeding the cat can the movie begin and the story progresses. The combination of completing two events like that to progress the story was one of the whole points of this project in the first place. It's something that I've been able to do to some degree in the original version of this project and really got working the way I want in the WOA Dungeon Crawl project. So it will be good to see it all come together finally.
  7. 1 point
    Hello, my name is Olivier Girardot, I am a music composer and a sound designer, and I post here on a regular basis. I usually share my youtube videos where I talk about my sound effects and give tips and tutorials about how to make them yourselves. Today I am seeking your help, or more precisely some kind of partnership. I am looking for active gave developers to review or advertise my Sound Effect Packs. The idea is to get the packs for free, and share and honest opinion about them from a game developer's point of view, in your blogs, on your website or your youtube videos, whatever you are comfortable with. It can be a single sentence comment or a 30 second review. I am not asking for anything laudatory either, just some honest thoughts. But I never had any complaints from the people who purchased my sound effects, so I am not expecting some harsh critics... I hope The point is that you get a high quality batch of sound effects for free that hopefully you can use in your projects, and I get a little bit of publicity in exchange. I grant myself the right to select the people to whom I will give my packs for free, considering that on of the criteria is to have an active platform where you post stuff on a regular basis. That being said I am not looking for Youtubers with millions of subscribers, not even thousands... although, if you do have thousands of subscribers or readers, and that you are interest in this offer, well I am not going to be the one who turns you down Ideally, I would like to promote my packs that I sell on the Unreal market place or the Unity Asset store: Unreal: https://www.unrealengine.com/marketplace/en-US/profile/OlivierGirardot Unity: https://assetstore.unity.com/publishers/39771 But I also sell them on my online shop www.ogsoundfx.com and you can also ask me to review anything you want there, and I will gladly consider it. In the meantime here is one of my latest Youtube video where I showcase my "Dragon Land" sound atmosphere: I am looking forward to your replies ! Olivier Girardot Owner & Sound Designer @ www.ogsoundfx.com
  8. 1 point
    It’s been a while since my last update. Part of the reason was because I was sitting in a Russian hospital for two months. But I’ll leave that story for another time…… However I did manage to make quite a bit of progress. I had some adventures in threading….. I had to rewrite my thread code like four times, but eventually I got it under control so things are running a LOT faster now. I’ll try to cover that in my next update. Also I added the makings of lighting system, which brings me to today’s topic. Since I wanted to start shading my planet, I of course needed a light. But I didn’t want some non-descript photons coming invisibly in from outer space. A proper planet should orbit a sun! So before doing the lighting I decided to make one. No problem, I had my trusty voxel sphere engine! …. But wait!.... A voxel built sphere seemed like a waste of computing resources for just doing a sun. I mean a sun doesn’t have overhangs and underground caverns. It’s just really a ball in space. That being the case, I decided to add simple terrain mesh capability to my library. On the other hand, to make it useful for other things, such as space games where a ship might get close to the sun, I decided to incorporate LOD, chunking and a few bells and whistles. The implementation parallels the voxel code pretty closely, except everything is scaled down to 2D from 3D. For instance instead of organizing my mesh into an octree, I use a quadtree. The bounding shape is a pill instead of a sphere. This is because with height-mapped terrain, triangles can stretch a lot in the vertical direction and so spheres are really sub-optimal as they don’t enclose the geometry very tightly. For the sun it doesn’t matter, but I like to make stuff reusable. For example I could use this terrain code to build a simple moon. Like the voxel library it accepts functions that can generate terrain…..but back to the sun….. For shading the sun, I’m using 5D noise, 3D for the object itself and 2D for time. For the purposes of my noise function, time kind of sweeps around in a circle so I don’t run into precision problems on the GPU. I could probably have done this with 4D noise and some tiling features, but there are some issues with that and I decided it was less of a headache to just go with 5D noise. To do this you basically you take the modulus of linear time with your desired repetition interval, convert the result to radians such that 2XPi radians maps to your interval. Then you take the sin and cos of that, and multiply both by some scaling factor, and feed that into two dimensions of your noise function. The bigger the scaling factor, the faster your noise changes. Right now it looks kind of basic, but later I’ll try to make it look more sun like by applying some other functions to the raw noise and maybe adding a few more octaves. Also I was reading about god ray shaders and I think that might look good in combination with the noise functions. Here’s the video: Hopefully for my next update I’ll have the planet orbiting the sun. And after that I plan on grabbing the JIT collision code from my old project and we’ll be down on the surface!
  9. 1 point
    Hey, what's up? This is your favourite Weekly Updates blog coming to you live! Straight up, this week was really slow... Some big changes are coming soon in my life, so things got a bit slower... I was still able to cook something up and while I'm trying to keep the pace going I might not be able to keep up. Only time will tell... But anyway, let's get right to it! The Boss First, let's talk about bosses. I was finally able to check up and fix the boss behaviour tree. Turns out that my bug was due to old code that didn't get refactored properly. So kids, remember to refactor! With that, I was able to fully fix my boss and while it still needs to get upgraded it's now in a working state. Take a look : The fix I've made to the boss also applied to other enemies, and while they aren't perfect it's a big step up from before. Enemy Spawner Secondly, I've also added a bit of fancy effect with enemies spawning. I've previously talked about redesigning the progression of the game. It used to work like this: once a room is cleared the next one will open and enable all enemies at once. This meant that technically speaking if the enemies somehow spotted you form next room (either they spotted you or heard you) then they would simply get to you while you just stay where you at. Not really fun if you ask me. Especially if you're abusing the room layout to your advantage. Now things are a bit different. While the next room still opens up after clearing the current room enemies won't spawn until you walk in. This meant that you actually need to move to the next room instead of the room moving to you. Not only that, but there's now a nice spawning particle with it too. And it doesn't stop there either! Once an enemy dies and drops loot then that loot is also spawned with a pretty particle effect too! Take a look : I'm not sure about the design but the system is there and is fully working. Statuses Resistance Finally, I've added a status resistance system. Previously, entities could only have a general status resistance. This meant that they could only resist to status changes in general without having any kind of affinity with one. Now entities can have specific absolute status resistances. This effectively means that an entity can be unaffected by certain statuses. For example, a HotBurger can't catch fire anymore. This isn't restricted to enemies either. I could technically give status resistance to players too! Minor Updates Fixed a bug where events of blended animations would be launched multiple time at once. In case of steps then it would play the same sound multiple time thus making it seems louder than it actually was. Fixed a bug where the player collider was excluded from most raycast. Fixed a bug where AIs would look at the wrong position when looking at a target Extended the Wetness system. Essentially, when an entity is submerged in water it becomes wet. Wet entities are resistant to burns and burning entities can even extinguish themselves with water. It used to work only on contact, so you couldn't wet yourself preemptively. Now once an entity gets wet they'll stay wet for a bit of time, after which it gets dried up. Also, some entities can also get harmed while wet. For example, a HotBurger will get hurt if it gets submerged in water. Fixed a bug where AI would have too sensitive ears. Next week I'm continuing with the whole AI refactor and game flow redesign. Right now I'm also working on some kind of environmental enemy that can really punish players if they're not careful enough. Aside from that, I've also brainstormed about some pieces of equipment. This means that I'm really ready to start modelling and coding some new pieces of equipment too! After all of this, it's your usual suspect as usual... However, E3 is starting soon, so I'm also going to watch a couple of press conferences. This means that next week is going to be also slow (at least for the first couple of days). So what all that, I'm gonna wish you all a happy E3! See you next week... Same time same day!
  10. 1 point
    The problem of difficulty in games has been debated to great depths for a long time. Various alternatives to the traditional approach with different difficulty modes at the beginning of a particular game have been proposed, analyzed and implemented. And yet, as much as they patch up the errors of the traditional approach, within them arise numerous inherent problems and difficulties. As such, I would like to propose another alternative–not so much a mechanical solution that requires implementation, but rather a different approach to difficulty design. One thing I’d like to stress is that, this has been applied in various games quite successfully before, and I’ll mention them later on, but not to the extent to which it can deservedly become a central design philosophy, in my opinion. This I presume is due to a lack of a rather clear and deliberate approach to difficulty design. But first, let me attempt to briefly summarize a few popular criticisms of the traditional difficulty modes approach and its alternative. Problems with Difficulty Modes Picture yourself coming into a brand new game, only to be asked to choose a difficulty mode that’s suitable for yourself, and presented with a number of different menu options. And frankly, they don’t do that good of a job at giving you sufficient information to make such an important decision. This is how many games in our history have done difficulty, and it continues to be fairly prevalent among modern games. Here are its common criticisms: Asking the player to make such a decision right at the beginning is not exactly a good idea. To select a difficulty mode before the game even starts is to make a major commitment based on very little information available (e.g. a short description). Once the player has selected a difficulty, they are probably going to live with it for the entire playthrough. Even if the game allows the player to change the difficulty mode later on, it is, in itself, still not a very good idea. For one, explicitly selecting a difficulty mode in a menu-based manner is certainly not an interesting choice that games strive to offer their players. They do not have to weigh anything against anything. They do not have to analyze the risks and rewards coming as a result of each option. And generally speaking, players are not going to be good at weighting short-term convenience against long-term enjoyment. They just do not know the game enough. Such approach would defeat the entire point of progression through unlocking higher and better tools to enhance and assist with gameplay. It would go against the intended gameplay experience from the game designer. And most importantly, it would make the player feel judged for not choosing a higher difficulty. There have been several solutions to negate these issues, of which Mark Brown has gone into depths in one of his videos. However, not one of them was able to solve them all and still maintain immersion. Dynamic Difficulty Adjustment The idea of Dynamic Difficulty Adjustment (or DDA) hinges on the theory of the player’s Flow State, in which the player is completely immersed, and the game’s difficulty feels just right. Any more difficulty will cause frustration and break immersion. Any less difficulty and the player will quickly find boredom, and you guessed it, lose immersion. Therefore, as designer Andrew Glassner put it in his book Interactive Storytelling, games “should not ask players to select a difficulty level. Games should adapt themselves during gameplay to offer the player a consistent degree of challenge based on his changing abilities at different tasks.” Or in other words, games should be implemented with a performance evaluation system as well as a dynamic difficulty adjustment system in order to adjust itself to accommodate the infinitely different and ever-changing characteristics of players. More on the technical details of DDA can be found in Robin Hunicke’s 2005 paper The Case for Dynamic Difficulty Adjustment in Games. However, while the Flow State theory admittedly has its merits, the DDA approach doesn’t go without its numerous downsides: Some players, when they find out about DDA, hate it. Especially when DDA cannot be turned off, the player ends up feeling patronized, and not respected by the game as an adult, capable of taking on challenges and improving him/herself. Players can, and will, learn to exploit DDA by pretending to be worse at playing than they actually are. And oftentimes, a DDA system will require some sort of break time in order to avoid revealing itself to the player, thus not able to quickly adapt itself to the player’s ostensible skill level. DDA inhibits the player’s ability to learn and improve. As soon as the player improves, the difficulty ramps up to match their skill level, thus eliminating the possibility of positive results. If the player cannot see some sort of feedback from the game regarding their performance, they cannot know whether any changes in their approach to gameplay were effective. DDA may create absurdities. One of the popular example of DDA going awry is the rubber-band effect in racing games, where opponents speed up and slow down seemingly for no reason in order to adapt to the player’s performance. DDA is incompatible with some forms of challenge. If the challenge in question is numerically-based, then DDA can work easily. However, when the challenge is symbolical, with pre-designed elements that are nakedly visible to the player, often having only one or a few intended solutions, then DDA cannot work. There are many interesting and nuanced approaches to DDA that I won’t mention since that’s beyond the scope of this segment. While I imagine there are going to be a lot of way to make DDA functional and sufficiently inscrutable through clever algorithms and implementation, I am rather discussing the fundamentals. Organic Difficulty in Games There seems to be a number of different terms to address this approach, but just for this article I’m going to use the term “Organic Difficulty.” This is something that has been tossed around in the last decade or so. The basic idea of Organic Difficulty is that the game does not ask the players to select or adjust their preferred difficulty via GUI-based commands, nor does it automatically adapt itself to match with the player’s performance and progress. But rather, the game allows the player to interact with it in certain ways to make it easier, or harder, for themselves. These take the form of tools, approaches, strategies, input sequences or methods, etc. which should often come with some sort of trade-off. This is something that has been implemented in a number of games including From Software’s Dark Souls, which Extra Credits has dedicated an entire episode to, and which everyone should take a look. In Metal Gear Solid V, for every mission the player has completed, there’s a score rating system which provides a rough overview of the player’s performance based on a number of factors such as stealth, lethality, accuracy, completion speed, whether the player has completed any mission tasks, and what tools they used. While the player does get minus points for mistakes such as getting detected, raising enemy alert, taking hits, etc. some other factors are not as clear-cut as to how they constitute minus points aside from narrative reasons. The player can always go on a lethal rampage, tossing grenades at everybody in sight, or calling a support helicopter to airstrike the entire enemy base. The player is provided the tools to do exactly all of those, and they’re always just a few buttons away, and the worst they get is a C rank, provided they completed the mission, and a slight dip in their earnings. Another example of this can be found XCOM: Enemy Within. There's a "cheesy" tactic in the game that can almost ensure victory, which is to have a unit with the Mimetic Skin ability to safely spot the enemies, thus enabling a squadsight-sniper from across the entire map to pick them off one-by-one safely without any real repercussion. This strategy is extremely effective in virtually every mechanical aspect of combat, with the only risk being that the spotter must not be flanked for they would instantly lose invisibility. The actual problem with this strategy is that it’s incredibly boring: your snipers just simply shoot every turn, and you can only take a few shots every turn, not to mention reloading. This strategy is best suited for beginners and people who have made mistakes and want to get out of the downward spiral. While on the other end of the spectrum, there are players who understand how the game and the AI of every alien unit in the game work, so they are more confident about moving up close and personal with enemies with minimal armor. Because for them, it's not about defending against the enemies, but about manipulating, "nudging" the enemies into behaving the way these players want them to (e.g. nobody needs armor when enemies are only going to attack the tank; nobody needs to take good cover when enemies are too scared to move to flank in front of an Opportunist-overwatch unit; etc.) The above examples seem to imply a few important points regarding difficulty: Difficulty should not only be designed around the mechanics of a game. It should also take into account the aesthetics or elegance of those very mechanics. Punishment does not always have to be tangible or significant, as long as it is enough to indicate to players that they are straying off the intended experience. A good analogy would be physical pain. The pain itself is not what’s causing harm to your body. The physical wound is. Pain is merely a bodily signal to let you know that what’s happening right now is pretty bad and you probably shouldn’t let what just happened happen again. But remember, the choice is ultimately yours! It may not be a good idea to put people on the linear graph of "gaming skill" where some people are simply "softcore, not-so-good at video games" and some other are "hardcore and always challenge-seeking." The idea alone is absurd, because players on such a graph would move up and down constantly, even during a single playthrough. Some people pick things up faster than a game can predict with its tutorials' pacing. Some people due to real life reasons have to abandon the game for some time, and they lose a bit of their touch when they come back to it. Instead of judging the player’s skill and trying to accommodate every possibility, games should be judging player interactions instead, using a spectrum between Effectiveness and Aesthetics of Play (or what I shall humbly name Ludoaesthetics). The Effectiveness-Ludoaesthetics Spectrum (ELS) On the Effectiveness-Ludoaesthetics Spectrum (ELS), difficulty exists only at the lowest technical level. Each end of the ELS represents what each player wants at a certain point in the game with certain conditions. On this spectrum, games are designed with the player’s interactions, approaches and strategies in mind, each with its own degree of effectiveness and ludoaesthetics. These are not solely defined by mechanics or the player’s skill level, but rather the way in which they are experienced and perceived by the player. Effectiveness refers to how well the player can progress and achieve their goals in a game using the set of tools they’re given and the strategies they’re allowed to formulate. How easy those tools are to use, and how good they are at helping the player progress towards the game’s intended goals, primarily constitute Effectiveness. Players who aim towards and stay on this end primarily look for the most effective ways to achieve the intended goals of the game (which of course include playing the game the easy way). Ludoaesthetics refers to the perceivable aesthetic appeals of the aforementioned set of tools and strategies given to the players. Players who aim towards this end do not necessarily look for the most effective ways to achieve the intended goals. But rather they tend to look for the added intrinsic benefits derived from unconventional play. These benefits include: Superficial Attractiveness: Visual and auditory appeal of using the subject matter or the subject matter itself. It can be represented by any entity the player can recognize in the game such as a character with great visual design, a badass-looking weapon with satisfying visual and sound effects, etc. Competitiveness: a.k.a. bragging rights. This is rather self-explanatory. There is always that portion of players who keep seeking greater and greater challenges to prove themselves to the world. They may even go as far as handicapping themselves with arbitrary limitations to heighten the challenge. Greater sense of satisfaction derived from greater challenges that may go beyond the goals intended by the game. People who have been through heights of overwhelming odds know about, and may expect, the immense amount of satisfaction that comes with them. Narrative Fantasy: Players may look for things that may not be effective or productive in terms of gameplay because they would align with the narrative better (in games that understandably contain some degree of ludonarrative dissonance), or they would add an extra layer of depth and intensity to the narrative and thereby enhancing it. Essentially, they’re sacrificing gameplay optimality to elevate their narrative fantasy. Design for Ludoaesthetics The point of designing for ludoaesthetics is NOT to create increasingly harder challenges in order to accommodate the player’s increasing skills (though that is not to say such approach has no merits whatsoever). But rather, it is actually to encourage players to strive for aesthetics in their gameplay and to lean more towards the right side of the spectrum. Here are a few suggestions on how to go about it. Creating more depth Depth refers to the amount of space the player is allowed to make interesting choices using the set of tools they’re given by a game. For a more detailed explanation of what Depth is in comparison to Complexity, you can take a look at Extra Credits’ episode on Depth vs. Complexity. Essentially, Complexity is the amount of constituent elements that make up a game, and Depth is the degree of interactivity between those elements. The very nature of ludoaesthetics has to do with the deviation from the default, intended approach (a.k.a. Playing “by-the-book.”) Therefore, the more those elements “talk” to one another, the better chance it is for ludoaesthetics to emerge, because then the player will be able to find more different ways to control or manipulate each element. [Also read: Design for Theorycrafting] Depth is pretty much the prerequisite for ludoaesthetics even as a concept to exist. Without a lot of depth, the window of opportunities for ludoaesthetics get significantly lower or completely non-existent. Creating patterns suggesting the possibility of gameplay aesthetics Adding more depth is not only about simply adding more stuff in a game and making them as obscure as they possibly can be. It is also about leaving breadcrumbs to suggest that there is more than meets the eye, therefore encouraging players to explore further possibilities. What kind of depth to even add? And how does one go about communicating it? Below is a conceptual representation of a set of challenges typically found in video games. Each challenge is represented by a window of failure and a window of success. These windows can be spatial, temporal, symbolic, strategic, or a combination of all. They are the spaces in which the player enters by behaving in a certain expected way. Secondly, the black line represents the player’s interactive maneuvers: where to get across and which direction to turn to next, in order to overcome the set of challenges without stumbling into the windows of failure. For example, say we have a situation in a 3D platformer game where the player is facing a pit, and across the pit leaning towards the right side there is a narrow platform. In such a scenario, we can assume that the window of failure includes any and all sets of behaviors that lead the player plummeting down the pit, and the window of failure includes those that lead the player to landing on the platform across the pit safely. Now consider the same representation of challenge above, but this time with a slight deliberate arrangement. As you can see, the sizes of the windows of failure and the windows of success stay exactly the same, but the positions of the windows of success have been altered so that they align somewhat (but not exactly aligned to the point of being too obvious). You can see that nested within the windows of success is a narrower window where the amount of the player’s maneuvers stays extremely minimal. Stepping into this window offers the opportunity for a non-disrupted gameplay flow, where a deliberate and guided set of behaviors will let the player “breeze” through the challenges seemingly almost with ease. This window is where ludoaesthetics occur. Of course, the downsides of it are aplenty: it can be extremely difficult to realize such a window exists in a real scenario. And in order to stay inside such a narrow window, the player has to be extremely precise and/or smart in their gameplay. You can think of this window of non-disrupted flow as an intended “weak point” of the challenge, where a single and concentrated attack will break the whole thing apart in one fell swoop. But the process of identifying such a weak point, and delivering the finishing blow with great accuracy may require a lot of trials and errors, and can be extremely tedious and/or difficult. An Example from Master Spy A common manifestation of ludoaesthetics comes in the form of speedrunning. Finishing with speed is, for the majority of games, not the primary intended goal. Games are rarely ever designed to be speedrun, and most players do not have to finish any games at high speed in order to not miss anything. So speedrunning has always been a sort of arbitrary self-imposed challenge by those who seek greater sense of enjoyment from their favorite games. However, there are a few exceptions. And you can find the above mentioned window of non-disrupted flow in levels like this one from Master Spy by Kris Truitt. In this game you play the role of the Master Spy, to infiltrate ridiculously well-guarded buildings, palaces and fortresses with a huge number of different enemies, hazards and contraptions standing in your way. And you are given no tools whatsoever but an invisibility cloak that can help you sneak past the eyesight of certain enemies while halving your movement speed. In the example above, your goal is to retrieve the keycard on the other side of the wall slightly to the right of your starting point, and then to escape through the white door right above your starting point safely. And while your cloak can get you past the eyesight of the guards, it is of no use whatsoever against the dogs, who can smell you even when you’re cloaked and will sprint forwards to attack you at horrendous speed as soon as you’re on the same ground as them. So what you have to do as a sequence of actions in this level is first to cloak yourself, then drop down from the first ledge past the the first guard, then quickly decloak to regain speed as the cloak is useless against the incoming dogs. Then before the first dog reaches you, move forward to the right, then quickly jump up. Keep jumping to retrieve the keycard while avoiding the second and third dog. Cloak up, then get on the ledge with the three moving guards. Finally, jump to the left to reach your destination. However, as you can see from the footage above (courtesy of a speedrunner nicknamed Obidobi), as soon as the player reaches the ledge with the three moving guards on the right, the guards turn to the other side and begin moving away from where the player is, effectively freeing the player from having to cloak and having their movement speed halved. And then right before the player reaches for the white door, the guard on the far right is about to touch the wall and thereby turning back to the left. This is such a tiny window of success that should the player not have begun moving right after they start the level and stayed uncloaked at the end, they would have failed. The level is designed in such a way that it can be completely solved without wasting any moment and action. Is it significantly more difficult to play this way? Yes. Was this arrangement absolutely necessary? Not really. But the designer made the level with the expectation that people are going to speedrun the game and will be looking to optimize their timing with each level. Thus, the levels in Master Spy are designed so that should the player start looking to speedrun the game, they will easily recognize that sweet, sweet window of non-disrupted flow. It is an immensely satisfying experience to discover it. Ensure Usability As usual, it is easy to get too extremely logical about design and forget all about the equilibrium, which is almost always what design is about. In this case, it is important that designers must ensure that whatever tools they’re making for their players to achieve ludoaesthetics, MUST have at least some sort of usability, even if it’s incredibly niche or extremely difficult to pull off. Things that serve nothing and mean nothing are NOT aesthetic. Say you have an RPG, and one of your players goes out of their way in order to build an unconventional character because they see some sort of future potential from this build, only to find out later that when they’re finished with the build, the meta of the game has changed and the window of opportunity for such a build has long passed. This means that the entire amount of depth you added, and the ludoaesthetics you might have intended by allowing that player to go in such away, is utterly useless and entirely wasted. So always remember to ensure usability for everything you add in your game. Conclusion Organic Difficulty and the ELS are not only, and not necessarily, an alternative solution to the whole difficulty problem. But rather, they represent an entire paradigm shift away from the idea that games should find more and more complex ways to serve players with different skill levels, and towards a design philosophy where players are given integrated tools within the context of games to set their own difficulty at any point without breaking immersion and perhaps the extra baggage of shame. It is not enough to have your players stay at the same level of difficulty throughout the game, or dynamically adjust the difficulty on the fly to suit them. It is best, in my opinion, to let your players cook to their palate. Just make sure that the process of cooking and the game itself are one and the same. References The Designer's Notebook: Difficulty Modes and Dynamic Difficulty Adjustment (2008) by Earnest Adams. Retrieved at https://www.gamasutra.com/view/feature/132061/the_designers_notebook_.php The case for dynamic difficulty adjustment in games (2005) by Robin Hunicke Cognitive Flow: The Psychology of Great Game Design (2012) by Sean Baron. Retrieved at http://www.gamasutra.com/view/feature/166972/cognitive_flow_the_psychology_of_.php Depth vs. Complexity (2013) by Extra Credits. Available at https://www.youtube.com/watch?v=jVL4st0blGU The True Genius of Dark Souls II (2014) by Extra Credits. Available at https://www.youtube.com/watch?v=MM2dDF4B9a4 What Makes Celeste's Assist Mode Special | Game Maker's Toolkit (2018) by Mark Brown. Available at https://www.youtube.com/watch?v=NInNVEHj_G4
  • Advertisement
  • Advertisement
  • Popular Contributors

  • Member Statistics

    • Total Members
    • Most Online

    Newest Member
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!