Advertisement Jump to content
  • Advertisement

jb-dev

Member
  • Content Count

    150
  • Joined

  • Last visited

Everything posted by jb-dev

  1. Why hello there, and welcome to this 27th weekly update! I've been cooking up something literally game-changing (sorry for the pun). Hang on tight and be careful not to fall, and let's get right to it! Steppin' In my previous post, I've ended on a bit of a teaser. I've talked about an algorithm that helps to create varied types of floors. In essence, the idea is to be able to "paint" different floor type onto a 2D array (or an "image" if this is abstract enough for you). Once that image is painted, we simply render it and generate special floor types all around the level. The Array Because I've previously used this Unity tutorial as a basis for building my level generate, reusing it was really ideal. I've simply added another 2D array that describes floor types at a given position. Because I've also previously worked on another 2D array algorithm for prop placement, I've also taken the liberty to reuse those drawing algorithm too. By mixing both codes I was able to create a reliable 2D array that was easy to modify and access, which is arguably really nice to have. The Rendering Now that the array is set, we now need to somehow render that array to the level, which wasn't as straight forward as it seems... Because I've followed that tutorial, the algorithm I use is the mighty Marching Square algorithm, which does work nicely on binary maps... However, my floor map isn't binary. This creates a pretty glaring issue: corners. While I can treat each floor type as their own binary map (and consequently as their own mesh altogether), their corners won't match up and will create holes where there should be none. Notice the small bright pink triangles on this map So we need to tweak the algorithm to fix that: we don't want the ground to be swiss cheese... Patching-up holes After thinking about it thoroughly I could list up the "problematic" cases. First, we could narrow down the problem by simply stating that because a square only has 4 sizes then there could only be as much as 4-floor types per square. this limits the amount of case to search. Then it was only a matter of visually scanning every problematic case possible. Here's what I've found: As we can see, there's a pattern forming. We can state that problems only occur when the following conditions are: The floor type we are currently rendering only has one active node for a problematic floor square. There are more than one floor type for that square The biggest sum of the total number of active nodes between two types of floors is less than 4. Aside from that, there's also the idea that only non-corner floors can be problematic. One thing to note is that there are two configurations that are exempt for it: As you can see, when there are exactly 3 types of floors with these configurations then there are no holes at all... The algorithm In order to fix those problematic cases, a new algorithm was in order. After snooping around and searching different marching squares tutorial and/or general discussions, I've decided that the best course of action was to use dual squares at these junctions. For those who don't know, dual squares are the more conformal cousin of marching squares. From left to right: marching, dual In essence, with marching squares, we want to create a "triangular" meshes with "rounded" corners (Think of it as a "smoothing" function for pixels), while with dual square we take their dual point. Like marching squares, dual squares also works by building indexes for particular squares. It's just that when it comes to rendering, duals are far more square that their marching counterparts. To illustrate this, here are the possible configurations for marching squares: And here's the same thing for dual squares: One particularly alluring thing about dual squares is that I can simply reuse the code for building marching cubes meshes but just create another vertices-creating function which creates those squares meshes. This is far easier to plug into the previous code. Walkable floors types Another important thing to note is that even though we now have a hole-free ground we also need to do another step in the rendering. The way the enum is organized is that there are certain floor types that are marked as "non-walkable" (i.e, they aren't your typical floors). Every non-walkable floor type has a chance to be completely invisible. This means that the player could see holes where those type of floors would be. Not really aesthetic if you ask me... So, in order to fix these, I've decided to create walls that would surround every walkable floor. Thus, if a non-walkable floor is completely invisible, there would be a wall and possibly a dark "bottomless" pit too. Because the tutorial also shows how to create walls you would think that just reusing that code would be great, and you'll be partially right. Although that walkable floor map would be binary, we also need to take into consideration the aforementioned junctions, and more specifically their configuration. If we have one of these dual junction squares then the extended walls need to only encase walkable floor. Otherwise, you'll get holes in the floor again. Notice the black triangle on the upper-left. To fix this we'll simply store an additional square for each junction that actually describes not whenever or not there's a floor there but whenever or not that node relies on a walkable floor. This way, while building those extended walls, we could simply check these "junction" square instead of the real ones. Paired with a nice fading shader this makes for a believable bottomless pit. Foor patterns Much like the props placement algorithm, this one also comes with room-specific floor patterns. It works much like the prop placement ones, but it renders directly onto the floor type map. Right now, aside from a generic random one, there's only one other arrangement: the Island pattern. Basically, the pattern consists of a central island surrounded by non-walkable floors. There are also ridges along the rooms' entry and exit wall side. Everything is connected by semi-procedurally generated bridges. There will be a lot more different floor patterns... There will also be huge structures here and there too, like lakes or chasms. Of course, some room patterns will override these, but not all of them. Floor types Now that the technical stuff is done then let's talk about the floor types. Normal Floors This is your typical floor. Nothing special here Grass Floors A typical grass-filled ground. It is very noisy and will get instantly noticed by enemies while walking on these. I'm not sure how to make this type of floor more interesting... (A Geometry shader perhaps, or maybe an actual separate mesh of simple billboarding triangles...) Grass Wetness One particular thing to notice is that this type of floor will have different coloration depending on the wetness level of a room. To achieve this I've decided to have another 2D array of the float that describes the wetness of a particular square. Like the floor types 2D array, there are many utility functions to draw on that array. I've also wanted to have some blur going on so I've decided to look into the gaussian blur algorithm, which is quite useful here. With it, I can control the amount of blur applied between different zones. After that, I store the wetness of a particular floor square in an unused UV map. In the shader, I just sample the U coordinate of vertices to get their wetness and that's it. Take a look: Here's the algorithm I've looked at. Sand Floor (WiP) This is a sandy floor. Jumping from it yields a really low jump. Mud Ew, mud! Careful not to get yourself dirty! You can't go really fast while walking in mud. Chasm This is a chasm. Falling into them results in death, so be careful. Lava (WiP) This is your old friend lava. It is a heart-warming friend that is always there for you. But seriously, don't get in there or you'll catch on fire. Ice A nice clear floor, yet it's quite solid. It is quite slippery, so be careful. Water Ah, nothing feels quite like a nice swim, especially when you're on fire. Poisonous Water This isn't like your normal water. Bathing in it will poison you, so be careful not to slip! Liquid Nitrogen (WiP) This is quite a scene: a sea of liquid nitrogen. It's impossible in real life, but this is a video game. But like real life, touching this will freeze you, so be careful! Spikes (WiP) I didn't finish their design yet, but it's your old friend the spikes. You get the gist: stepping on them will hurt you so be careful! Love Potion (WiP) A bit of a stretch, but it's there! Stepping in this will make you frenzied, so be careful! Liquid Floors Another thing to mention is that I've also cooked up a wavy vertex shader that makes models wavy, which is quite useful to simulate big bodies of liquids. Here's a good look of the shader in action: wavyWaves.mp4 I've followed this tutorial to achieve this if you're interested Minor updates I've finally decided to fix most melee weapons hitboxes. Previously I've used the actual weapon's hitbox to basically see if the attack hit something. This was unreliable at best, mainly due to by both animation and code being wanky. I've changed it so that hitboxes are now more reliable and will always hit where the player aims their crosshair. This makes weapons like sword relevant again! This applies to both players and AIs Next week Last week was insane! That floor algorithm really took a lot of my time and I think it can really pay. With things like chasms, jumping now gets the importance it should have. Lately, I'm trying to somehow fit AI in this. I want to give the player the ability to "push" enemies in chasms. Right now AIs are restricted to their navmeshes, which is neat but it makes them immune to chasms, so there's a lot of thinking ahead. There's also some polishing to do with, especially with floor formations and stuff. I also need to change the visual of some floors, like for example the spikes or the grass. Afterwards, I really want to diversify enemies. This would be an important step towards having a public demo of some sort.
  2. Why hello there, and happy new year! I feel like 2019 is gonna one of those years where change is imminent, and let's just hope it's not a bad change but rather a pleasant one. With the new year comes a new schedule. I've decided to write the Weekly Updates (and consequently ends sprints) on Saturday from now on. This way I can synchronize all of my updates. But anyways, I've also decided to take a 2-week hiatus, hence the radio silence for the last weeks. It was a nice well-needed break and I feel overall revigorated and well rested from it all. With that said, I have a whole lot to talk about, so without further ados, let's get right to it! Minimaps Markers First, there's been a significant upgrade to minimaps. Now the minimap can display the position of collectables items, interactable props and other notable landmarks. Each point has their own type of minimap markers so players can easily locate any collectable items they missed. Each marker is also kept straight no matter the map's orientation, giving them the appearance of some kind of GTA-like map markers. Mainly an aesthetic choice but I like it like that anyways. Quite handy if I say so myself. Stores, Stores, STORES! Another upgrade worth mentioning is that I've revamped the level generation code so that the appearance of malls won't depend on the player's luck anymore. This means that it's the seed that decides malls position. This effectively means that during normal gameplay players can still encounter shops no matter if they're lucky or not. Aside from that there's also been a significant upgrade in special rooms constraints. Now special rooms are more likely to spawn due to less strict constraints. Overall this means a more seasoned level, of which the game is in dire need of. Rests areas Second, I've decided to add a new type of interactable props: the rest area. These are actually modelled after rest area found in most shopping centers and malls. (because of aesthetics) The player can actually use these to rest and restore some of their health. Each rest areas can only be used once, as the player actually "trashes" it when they use it. However, there's a catch: every enemy also gains their health back. This means that players have to be careful when using these, especially if they're facing a boss. Rest areas only spawn in regular rooms if the player is lucky, and there's only one rest area per rooms. There are two types of rest area: a common one and a rare one. Common rest areas This common rest area only heals 50% of health to any active entities Rare rest areas This is the rarest variety of rest areas. It fully heals any active entities Bosses Range Attacks Previously I've talked about how bosses were in, and now I've enabled that boss the ability to do range attacks. The way it works as of right now is similar to a melee attack, but it also produces some kind of "shockwave" that moves towards the enemy. A skilled player can actually try to either jump over it or simply avoid it altogether. Bosses choose to do range attacks whenever their target is far enough, otherwise, they'll either try to get closer or do a melee attack depending on its distance with its target. Item agglomeration Third, let's talk about items in general. I've previously said that I've started to do playtesting among my closest friends and family, and have been taking notes on some matters here and there. One of the most noticeable things was the fact that most players disliked walking around the room to try to collect most items that were either drop as loot or from a treasure box, especially if it was money. So, after thinking about it I've decided to implement an item agglomeration mechanics where collectable items can "fuse" together, much like how it's made in Minecraft. Each item agglomeration has some kind of "notification pill" on the top right corner telling how many items it has inside. If two items that can agglomerate together are near enough from each other, then a magnetic force will pull each item towards each other, creating some kind of magnetic/gravitational forcefield. Most aglomerated items will also have different sizes based on the amount of agglomerated items. Larger agglomerations mean larger sizes and vice versa. The item's mass also gets bigger and bigger the more items it has. There's also a limit on how big an item agglomeration can be. If the limit is reached then another agglomerated item is created. Item agglomerations that are full won't agglomerate anymore, and there won't be any pull forces applied to them. When the player grabs an item agglomeration, then they get the specified amount of items. With this, it was significantly easier and less time to consume to collect every item, as they now group themselves together. It's also quite mesmerizing to see items get pull towards each other. Right now only money, keys and bombs can agglomerate, but I'm sure there's gonna be a whole lot more different type of agglomerate items in the future. Minor updates I've decided to nerf the bow by removing the ability to the bow to induce knockback. Fixed bugs with items orientation when placed on their pedestal There are now many more different distinct types of notification, each with their own designs and colours Added a "box breaking" effect that shows the "health" of breakable boxes I'm still working on it though. It seems that I'm not really satisfied with it, to begin with... Consequently, I've also fixed some bad geometries on the breakable box model here and there too. Added a velvet-ish shader for some types of props that are made of cloth or similar substances I've decided to balance movement speed a bit. After a series of playtesting that shows that the player moved too fast. It was a wonderful thing to do. Now the speed seems more reasonable and manageable. Changed how much damages bombs do (slight buff). I've also changed the actual damage distribution. It is now a linear one (might change it in the future though). This means the closest an entity is to the bomb the more damage it gets Same thing with the explosive force Next Week Next week will be a really hard one. With all that free time of mine during countless car trips and what not I decided that some brainstorming was in order (especially with all that playtesting. It's really eye-opening and all) One crucial idea I had was to diversify the room's landscape a bit. I hope that with that it's gonna make the game a wee bit more exciting and captivating. Technically this is currently in WiP and that's why some of the pictures taken may have holes here and there. I'm currently working on an algorithm that will enable me to have varied types of grounds (like grassed, iced or even chasms). I'm currently working on it and it would probably be the main theme of next weeks' sprint. Aside from that, there's also the idea of adding many more enemy types and perhaps more weapons and even more balancing. There are also other relics, activated items and perhaps pieces of equipment to add. In other words, there's no shortage of work to be done!
  3. jb-dev

    A boss telegraphing its attack

    From the album: Vaporwave Roguelite

    This shows a boss telegraphing its attack to the player
  4. jb-dev

    Vaporwave Roguelite

  5. jb-dev

    A boss seen from afar

    From the album: Vaporwave Roguelite

    This is a boss currently spotting the player
  6. Why hello there! What a nice thing to see you again! This is another entry of your favourite Weekly Update! This time it's all about (artificial) intelligence. Most new features are linked to AI in one way or another, so let's get right to it! Step It Up! First, let's talk about sound! Previously, the game was almost devoided of sounds. It was pretty miserable, but lately, I've tried to remedy the situation by adding many different sounds. It gave a whole lot of life and overall made the game much more enjoyable. Now I've also made another big step (sorry for the pun): I've added stepping sounds. This means that walking around now makes noise. There are also various types of sound for each type of surface. This applies to both player and AI steps. Those sounds are also played when the player is either going to jump or is landing from one. It's quite nice to hear and it's a pleasant way to give audio feedback for jumping. Coming up to our senses Second, AIs are generally smarter than before with the help of senses. Right now there are only two types of senses: hearing and communicating. I'm All Ears First, let's talk about hearing things. Previously, AIs were lacking any type of ears, meaning that they would only react to a direct line of sight or just by being in their "bubble". This meant that as long as the player avoided any of these situations no ones would be able to spot said player. But now this all changes: AIs can "hear" sounds like footsteps and gunshots. This system works in an elegant way... First of all, everyone sounds in the game are fully 3D. This means that a sound has a given position, and because of this there's also a spatial volume roll-off. By using the sounds' 3D position and applying the volume roll-off we can calculate a perceived volume for each listener. We then compare that to the listeners' hearing threshold to tell whenever or not the sound is heard. If so, then there's an appropriate reaction from the listener. Communicative Next, there's also the communication sense. Although broad, the idea is that an AI can broadcast a message to any other ones close enough to hear it. In that sense, it kinda works like the hearing one, except it's completely silent, is exclusively for AIs and also have a meaning. Like hearing, each message has a perceived volume (or urgency, as I like to call it) which is defined by the emitters 3D position and a spatial roll-off curve. Right now, each AI can choose to respond or not to a broadcasted message depending on their willingness. For example, a healthy AIs would be more akin to respond to any messages, while injured ones might be more hesitant to make a move. Urgencies also depend on the emitter's current condition: if an enemy attacks an AI and the latter is getting dangerously close to death then the broadcasted message base urgency would be high. It's quite a complex thing to decide which is the appropriate urgency level for each message, and it also figures that it would change based on which type of AI are involved. There are, as of now, only two types of messages: Help This message is sent mainly when the AI needs assistance. Right now this is mainly used when an AI is injured. The more injured the AI gets the bigger the urgency is. Look This message is sent when an AI wants other AI to take their attention to in a specific direction. Right now this message is sent when AIs spots an enemy. That's about it for messages. Enemies reactions Next, there's another AI upgrade. Enemies are now properly reacting to attacks and injuries. If the injured AI didn't spot the attacker they would try to investigate the supposed attacks. This means that the player could technically set up an elaborate trap to lure the AI near and give a lethal blow away from its friends. Pretty insignificant on its own, but paired with the other AI upgrade this makes gameplay a whole lot better in my opinion. Bosses Yes, you read that right. Bosses are now technically in! (although there's a lot of bugs with their AI and whatnot) Bosses are usually encountered at the end of a level. They guard the exit and in order for the player to advance they need to take them out. Type of Bosses In the finished game there would be two different types of bosses: Sedentary Bosses As the name suggests, this type of boss doesn't move at all. Instead of depending on movements to attack and escape players they would use environmental way to distance themselves from the player. These would generally have a lot more HP than the other type of boss to try to balance things out. Nomadic Bosses This type of boss will, unlike the sedentary ones, be mobile and move around the room. They're also using that mobility of theirs to control the distance between their enemies and themselves. Boss Behaviours All bosses will use behaviour trees to decide their behaviour and attack patterns. In general bosses attacks are split in two: their announcement and the actual attack. Before attacking the boss need to "announce" (or telegraph) it first. The player can then easily predict attacks and plan accordingly. There are also two types of attacks: melee or range. If the target is close enough, a melee attack is used. Otherwise, we use a range one. Some bosses are restricted to melee attacks while others can do both. In the final game, there might be multiple cyclic types of attacks per bosses. Boss death Once the player kills the boss a reward is given and the passage to the next level is opened. The reward got from the encounter is currently randomly chosen, but will most of the time either be pieces of equipment or relics. The player can either dismiss or collect them. That's where the strategy part comes in! First AESTHETIC boss Right now there's only one particular boss that is fully modelled, textured and even animated (thanks Mixamo). It's supposed to represent a Greek statue. (Verry AESTHETIC if you ask me.) Here you can see it telegraphing a melee attack: There will be more that one boss but this is a start. Next Week Now that bosses are in there's still a whole lot of work ahead to really polish and fix their behaviour tree, as I'm not much familiar enough to behaviour tree and have still a lot to learn. I also need to finish attacks so that they do damage. So next week will be boss-themed I guess. Other than that the work ahead of me is mostly modelling. I need to really polish each level so they feel different enough from each other to keep the interest and curiosity level up throughout the game.
  7. Hey, nice seeing you again! I can safely say that this update is packing quite a punch, so let's get right to it! Patching up holes First, I want to talk about navigation meshes. Previously, only the procedurally generated floors were included in the navmesh baking process. This meant that all special rooms (aside for landfills and gyms) were completely inaccessible for any NPCs. This was due to two issues. The first one was simply that the navmesh baker only looked for the generated floor rather than any walkable surface. In Unity, it was just a matter of changing things a bit to use a bound box rather than checking in the object's hierarchy. The other issue was the way the floor was generated... Previously, most special rooms using static assets had floors that only covers the room itself, without counting the actual connective gap between it and the rest of the rooms. Because the floors were generated using marching squares, that connection's floor turns into an awkwardly shaped triangle, and thus created two small triangular holes. The problem was fixed by simply adding another square of the floor after that connective square. With these two solutions, NPCs are now able to enter and navigate special rooms, so there's no escape now! New Relics and capacities Next, there's now a lot of newly implemented capacities (and thus relics). Backup Floppy Capacities This relic comes with the Second Chance capacity Second Chance When the player is about to die, then they instantaneously regain 25% of their health. This capacity can only be used once. You can, however, have that capacity many times and thus have multiple chances. Stats Bonuses DEF -35% HP -25% Beach Ball Capacities This relics only has one capacity: Double Jump. Double Jump This capacity is self-explanatory: You can now jump again in mid-air. Stats Bonuses AGL -12% Concentrated ATK Juice Capacities This relics comes with two capacities: Slow Attack and Charge Up Slow Attack This capacity simply slows down the attack speed. It also influences the charging times of chargeable weapons (like bows). This capacity can also be applied multiple times, meaning that attacks get slower and slower the more Slow Attack capacities you have. Charge Up This capacity lends to the wearer the capacity to charge attacks with swingable weapons like swords. A charged attack will have a somewhat substantial damage bonus depending on how long the player held the attack button. Quite useful to deal with stronger enemies! Stats Bonuses ATK +25% AGL -10% Echo Drop Capacities This relic only got one capacity: Shockwave. Shockwave With this capacity, the entity can generate a shockwave when they attack if they're lucky. This makes any enemies in a small radius take damage no matter if they're hidden or not Stats Bonuses DEF -29% Electronic Mask Capacities This relic comes with two capacities: See Enemy Health and Clairvoyance. See Enemy Health This capacity is quite self-explanatory. It gives the player the ability to see any targeted enemy's current health. Quite handy for planning attacks! Clairvoyance This capacity helps the player find their way by rendering a nice glowing path to the exit. The path actually gets refreshed every 5 seconds, and there's even a nice fade-out. Here's a picture of that path As you can see it's really AESTHETIC. The colours of that path are picked from our palette, meaning that it changes colours depending on the current level. Stats Bonuses DEF + 5% HP -20% Fan Of Violence Capacities This relic lends two capacities: Corrosive Spead and Enflamer Corrosive Spead This capacity makes any killed enemies drop a puddle of poisonous blood. If another enemy walks on it they instantaneously become poisoned (if they don't have any other status effect that is). The puddle dries up after a while. As of now, there's no actual damaged dealt directly to enemies when they stand on a puddle. This might an idea for later, though. Enflamer This capacity is quite easy to understand: you now deal fire damages and have a chance to give the burning status to any attacked entities. Stats Bonuses ATK +5% HP -5% Flying Shoe Capacities This relic only got one capacity: Hover. Hover This capacity makes the entity able to glide for a short period of time after a jump. Simply press and hold the jump button to glide. After a bit, the glide will stop. You can also release the jump button during a glide to stop it. One would think that the Double Jump capacity would counteract with this one but one would be wrong: just hold the button down after the double jump. This paired with a ranged weapon will make a deadly combo. Stats Bonuses HP -5% New Activatable Item Next, I want to talk about a new activated Item: French Fried French Fried Alignment: Future Funk Description This is a rather funny looking moustached french fry wearing a beret and smoking a cigarette (Don't smoke, kids). This item can summon a seagull familiar that attacks any nearby enemies for a limited amount of time. Once the time runs out the seagull disappears. The player can have up to 3 seagulls at a time. there's also a cooldown before the item can be used again. Capacities Aside for its activatable ability, the Hover capacity is also given to the player as long as they hold the item. Stats Bonuses DEF -11% Headshots! I've previously thrown the idea around of having different damage bonuses if the player targets a specific body part with a projectile. I'm proud to say that the feature is now fully implemented. Now there's a 5x damage multiplier to projectile if they hit the head (for example). Although these bonuses exist, there's still a lot of balancing to do and whatnot. But I got to say that it's quite fun headshooting enemies with arrows (mainly because enemies aren't balanced yet). This works (of course) for any projectiles. Mouse Refactored There's also have been a big mouse control refactor. Previously, the mouse script I used wasn't as flexible as I originally thought. Rather than coding everything from the ground up, I've decided to cherry-pick code from Unity's standard Assets FirstPersonController script. I Initially wanted to fully use the controller, but there were some input delays with the Update and FixedUpdate functions. I decided to pick its MouseLook script and integrate it into my custom PlayerController. The results were night and day. Not only I could easily change the sensitivity, but there's even a "Smooth Mouse" function which interpolates mouse movements. Mouse Sensitivity Speaking of mouses, I've also added the ability to change the mouse sensitivity. This was made after many feedbacks of my playtesters, who were either unable to use the mouse properly or complained about an excessively sensitive mouse. The Mouse Sensitivity setting takes the form of two components: a slider and an input field. In essence, the input field is used to save the actual sensitivity, while the slider is just a more tactile way to set the sensitivity. Right now, changing the slider will update the input field, which in turns updates the mouse sensitivity. If the player wants an absurd sensitivity (like 100 or something), they can't use the slider for that (which only goes up to 20 right now) and instead have to manually input this in the input field. There's also another checkbox component controlling that previously mentioned "Smooth Mouse" mode. Pause Screen Option Tab Now there's an options tab in the pause menu: This is a quick way to change common settings such as volume slides and mouse sensitivity among other things. These work just like their Main Menu counterparts. Once the player closes the pause menu, options are automatically saved. Quite handy if you want to adjust your mouse sensitivity mid-game, or lowering volumes while streaming. Closed Rooms Previously, all rooms were open form the getgo. The player could technically speedrun their way through the game without breaking a sweat. This kinda made the game quite boring, as there weren't any valid reason to destroy every enemy in each room. This was in a dire need of change. So I've now implemented a linear progression system, in which the player needs to clear the room of any enemy before passing on. Of course, the player can break walls or enter special rooms anytime (mainly because these rooms are optional and won't provide any shortcuts at all), but in order to go to the next room, they need to clean the room first. The way this works is by having closed/opened doors (much like locked doors but without any type of locks). This makes the game feel more like a game, although there's still place for improvement. Minor Upgrades Fixed the MSAA artifact bugs It was quite simple: just use FXAA Technically I can also do TAA (Temporal Anti Aliasing), but this could be put in the options. Of course, there's a lot of other options, but right now FXAA does the job just fine There might be better options, or maybe an MSAA fix but this will wait. Added a looping testing sound effect when fiddling around with the Sound Effect volume slider This is for both the Main Menu's options screen and the Pause Menu Options tab. Fixed a lot of bugs, especially with destruction/creation Charging an attack now slow down the player Once the player unleashes its attack it resets Previously both the Quick and Slow Attack capacities only affected swing speeds. Now they also affect the charging rate. Added a touch of Ambient Occlusion I will probably put this in the options later on... Next Week Even with a cold doing its thing I'm still trying to be proactive and work on the game. In fact, yesterday I started working on a draft of a boss behaviour tree. Although still really rough and full of bugs I think I can have a working boss ready for next week. Afterwards, It'll be modelling time again, but this time it'll be level specific stuff. And after that, there's other relics, items, food, capacities and abilities that are left in the design document that needs to be implemented in the game, which means modelling, coding, designing and whatnot. But right now let's focus on bosses...
  8. Last week wasn't as productive as the last, but it's still substantial nevertheless. So without further ados, let's get to it! GUIs Previously, some GUI elements didn't scale to the screen's density. This meant that no matter the resolution those items always remained at a set size. This was fine and dandy, but now that menus are implemented it's primordial to have some kind of cohesion. The main reason why such constraint existed was mainly due to those wacky title bars of those funky windows. Before these were all textures, and in essence, I wanted to make sure that these won't get blurred or offset, so keeping the same scale was the only choice back then. I, however, tried a different approach: because these funky lines were relatively simple and didn't require any type of special texture I thought that we could easily replace them with custom geometries. This way I can control where each vertex goes and how they adapt to the GUI element's rectangle. After a bit of tinkering, I finally managed to change this, meaning that I could now get rid of the unscaled canvas. As you can see the results are a whole lot better : And here's how it looked previously: And just for comparison, let's take a look at the GUI at my screen's native resolution: It was a long-awaited change, to be honest. Especially if I want to try to have dynamic resolutions in the future. Wonderful Sounds One of the most striking updates has to be the sounds. Previously, there weren't any sounds yet, but now there are progressively more and more varied sounds, making the game a bit more complete. On most items (collectables and whatnot) there's now a physic sound that plays when the item's associated rigid body get hit. The sound changes its volume based on the impact velocity's magnitude. This makes locating those items so much easier. Similarly, there's now another sound that plays when said item gets picked up. Let's take a look: As you can see (or heard in that case), most sounds are also given a random pitch just to spice things up. Weapon Balances Another big upgrade would be weapons. After a bit of closed testing, I've realized that the weapons could need a bit of balancing. The Gun Got Nerfed The Gun itself got a slight nerf. Before each bullet shot could be recycled. This, in effect, makes it behave more like Heavy Bullets. However, it was clear that picking up each of these bullets were kind of a pain for most people. So I've decided to reduce the amount of time a bullet can be recycled by linking that recycling to the player's current luck stats. In the future, there might be even actual bullet magazines and an automatic reload process (or manual). This way we could counteract the fact that bullets would be scarce if the player has poor luck. The bow got buffed The bow, however, got a big buff. Now, arrows are infinite. This effectively means that there are no more melee attacks and every time the player wants to attack a pre-charge is needed. The Mini Map Next, there's a new Minimap. This Minimap shows a simplified layout of the level. The room the player is currently in is also highlighted, and it changes when the player moves to another room. Each type of rooms has their own colours, which is dictated by the colour palette. This means that each level has their own room colours. If this might be a hindrance then this could be easily changed, but so far I simply lack the data to know. So far all rooms are shown (even the hidden ones), but eventually, only the discovered rooms would be shown. There's also no other things as of yet. There might be enemies, items and whatnot. These would be pretty easy to implement though. The map also rotates to match the player's view. It also follows the player around so that the player's position will always at the middle of the map. Take a look: Minor updates Fixed a bug with enemies' animations not working properly; Undid (partially) the UnityEvent's to also use C# native events: As seen here, there's basically no reasons to use UnityEvents rather than native C# events. One of the reasons one might use UnityEvents is of they use a serialized and strongly linked. But overall it's significantly slower; Another reason for the undoing is simply because my capacities are technically not serialized. This means that those capacities listeners are never invoked when the event is called. Added an empty Option tab in the pause menu. Next week So next I'll probably work a bit on the minimap, and perhaps fix a few graphical bugs linked with the MSAA applied to the game. Some models get unwanted gaps between shared vertices: So I might have to implement FXAA or TAA to fix this. Afterwards, it's boss time!
  9. jb-dev

    The Almighty Mini Map

    From the album: Vaporwave Roguelite

    I've recently added a mini map on the right upper corner of the screen. With this the player can now see in which room it's currently in. That mini map get updated when the player moves to another room. In the future most rooms will be hidden until the player discovers it by either moving to a new room or, in the case of hidden rooms break a breakable wall or open the locked door.
  10. Hi there, and welcome to this very special weekly update! Yes indeed, this one can be special. Everything about this update is related in one form or another to death. As you may or may not know death (or the capacity for a player to lose) can be an important part of any game. It can take many forms but in our case, it's a typical death. So without any further ados, let's dive right into it! Weapons and View models One of the most striking updates I've made was to weapons, or more precisely how the player uses weapons. Previously attacks, in general, were mainly governed by actual skeletal animations (i.e. the actual world model of the player) This meant that when a player swings a weapon the attack would be oriented not to the head of the player but to its body. One adverse effect of this is that the player couldn't aim up or down. Now, I've introduced view models to the game. For those who didn't know, view models are 3D models that only appear on the player view. (Think of it like gun models in Frist Person Shooters) These make it really easy to align attack not to the actual world model but to the view. This is especially useful to fix our up/down aiming problems. swings.mp4 Of course, this meant that a big refactor was in order but I think it makes the game much more enjoyable. Another effect of this change is that guns and other aiming weapons now have their own animations, meaning that they are now actually aiming at the crosshair in the middle of the screen. There's also a unique melee attack animation for these too. swingAim.mp4 Charging Weapons Previously, changing weapons such as the Bow didn't have any visual indicator of how much tense the bow was. Although this could have been fixed with animations, I didn't rig any weapons as of now. Paired this with the view models refactor and it wasn't really wise to immediately embark on such adventure. To fix this I've decided to add a nice charging bar that shows how much power a charged attack will have. There's even a nice gradient and everything. chargeBar.mp4 Projectiles and compound colliders Previously there was no actual difference between melee and ranged attacks. Both used the same colliders and did the same damage. However, now this has changed. Projectiles are now testing their hits based on a completely different set of hitboxes that are spread all over the model, one for each body part. This makes hit detection react realistically. It also means that, in case of arrows, we can stick the arrow to a particular body part and make the former follow the latter in a realistic manner. gettingShot.mp4 There could be a damage bonus in the future but at the moment it's not a priority. Aside from that, there's another benefit of using compound colliders: rigid bodies. When the player attacks using a projectile and make a lethal strike, the game can then apply a given force to the rigid body that was hit, making ragdolls behave more realistically than ever before. Death And finally, here's the best part: our own mortality. Yes, now players can experience the full thing. When their health drops down to zero, players simply die in a flamboyant way by using ragdolls. When they die, the camera is transferred to a ragdoll and a sad jingle is played. death.mp4 Death Popup After the jingle ends a nice death popup shows up and the player has three different options. Retry This options simply reuses the same run configs (aside from the seed which is regenerated) and start a new one. Main Menu This options boots back the player to the main menu. From there the player can load a new save file and start a new run with a different character and seed. Exit This is quite simple: it ends the game and closes the app. Popup Text The popup itself has dynamic texts that changes based on how powerful the last blow was. In the future, there might be different types of damages leading to different types of texts. We might even change the text based on what killed the player, to begin with. That's about it for death. Minor Updates Fixed many bugs related to enemies. Refactored almost everything. Every C# events were replaced by UnityEvents. Although their implementation isn't actually any better than the native one this gives us the ability to edit events directly in the Unity Editor. It can also give us the ability to change which type of collections are used to store every observer. More optimization opportunities, yay! Added a bunch of extension methods (That thing is OP, to be honest) Removed a bunch of unused codes and whatnot. Reduced muzzle flashes. This could have been hazardous for epileptic people. Added a nice keyboard (?) model. Fixed bugs whit the analog blur effect dishing out unclamped colour values, resulting in strange dark lines artifacts. Added a death plane at the bottom of levels. This means that pesky player that found their way out will suffer the consequences. 😈 fallDeath.mp4 Fixed bugs with the character selector highlighting the wrong character when switching screens. Changed some sounds and added a bunch of new ones. Next week Next week will probably a continuation of the cleaning process. Afterwards, it's boss time! I've also started to read this book on game design, so there might be some unplanned edits here and there, too.
  11. Last week was intense! There's a lot of new stuff! So without further ados, let's cut the cheese. 🧀 Loading Screens A-Plenty So last week I said I was able to load a level from the main menu. However, there were some problems when it came to the reactivity of the app during that loading phase... The game froze and gave no signs of activity, promoting Windows to administer the "Not Responding" treatment. To fix this I've broken up the loading process onto three separate loading processes. I've also optimized the music playing feature: it now initializes before the menu screen, so now everything can be offset to a secondary thread. It's just a matter of waiting for the end of that process with a Coroutine and load the next scene when it's done. This significantly speeds up the loading process to the point where some loading screen only shows up to immediately disappear after. Getting In and Out of Levels Secondly, I've finally linked all levels together. Now, when the player jumps down the Ethernet port a loading screen is shown and the next level is then loaded. This means that the player can theoretically complete the game for the very first time. (Yay!) Levels Thirdly, there is now more than one level. Each level has their own localized name. In the future, an AESTHETIC Sonic-like splash screen will be shown to introduce the level. Right now it's only a small notification, but it's getting there. Because the game uses a palette, it was really easy to add other levels. I did, however, need to make each level look distinct from one to another, so I had to work on their palettes a bit. In order to get the right feel, I've tried to get Vaporwave images that inspired me and extrapolate on their palettes to create new ones. Here's a bunch level and their respective name: Keep in mind that there'll be some level-specific props for each level in the future. (Just changing colours won't be enough to make each level unique) I also want to mention that two of these levels, mainly Current Cave and Hot Hell, have inverted palettes. Usually, each colour changes their values from light at the top to dark at the bottom. These levels have these value flipped. This creates an uneasy feeling, not unlike photo negatives. This effect was used in Current Cave to indicate that it's dark, while at Hot Hell it's hot. Development Builds While working on the game, it occurred to me that I've never built my game at all. This was kinda troubling, as I had a skewed view of the game's performance: the Unity Editor creates a lot of overhead, meaning that the game genuinely runs slower in the Editor than as a standalone. So I've decided to finally build one small developer build to evaluate the game's performance. While doing this I've also decided to tweak some the standalone's settings. For example, I've added a nice logo at the game's main splash screen. (Just a placeholder one don't worry) I've also added a bunch of program icons and cursors. While doing the cursor, it occurred to me that I could generate different cursors for each level, so I tried it. First, I've created a base cursor image. Secondly, I map each colour channel of our base cursor to a colour given by the palette and store the result for later use. Then, when the level loads, we simply replace the cursor with the level's one and voilà. But anyways, I was able to compile a development build and give the link to some of my friends and relatives... I won't put it online right now: there're some easter eggs in it that aren't hidden yet 😉. Counting .mp3 files, the game's size is about 80 MB. While this can be quite big it is but a development build, so not everything has to be perfect. New Characters There's also three new "character" classes: gunner, marksmen and swordsmen. Each of these characters starts with their own equipment, base stats and even their own focus alignment. When the player starts a game with a specific character, its choice is saved in the save file. When the player plays again, the last used character will be already highlighted. But enough talk, let's get right into each of these classes. The Gunner Nicknamed "True American", this character starts with, well, a gun. His weapon: The Gun The gun is a new hit-scan weapon that can also be obtained in-game. It uses ammo and doesn't need to be charged like the bow. This is quite handy, but this weapon is also especially loud: It's not the most subtle weapon out there. Also, unlike the bow, it can only hold a set amount of bullets. (no reload sorry guys) When the gun runs out of ammo, the player can use a secondary melee attack. This attack, however, is considerably weaker than using a bullet. Once the player has a gun, ammo will spawn where common consumable items would also spawn. It can even be found in Malls if the player holds a gun when the level was generated. The ammo is game persistent. This means that if the player had a gun, collected and used ammo, switched to another weapon and switch back to another gun then the ammo amount will stay the same. His Item: The Cellphone The True American also comes whit a cellphone. This gives him the ability to create one-way teleportation points. His Stats For stats, he's really kinda weak compared to The Standard, but what he loses in raw defence he gains back in HP, making him a powerhouse if you can avoid direct contacts with enemies. The Marksmen Nicknamed "Robin Hood", this character uses a bow to dish out damages. His Weapon: The Bow This new weapon can also be obtained in the game. The Bow is used in conjunction with arrows to create a formidable combo. Unlike the gun, the bow isn't a hit-scan weapon: it instead throws arrows. In order to be effective, this weapon needs to be charged up. The player presses and hold the attack button, and release it to unleash a deadly arrow. The longer the player holds the button the faster and deadlier the arrow is. The player can also use a secondary melee attack by quickly tapping the attack button rather than holding it down. This is useful to break breakable boxes or quickly dispatch weaker enemies without wasting any arrows. Like the gun, when the player runs out of arrows, then the weaker melee attack is used. Arrows behave just like gun ammo: they will be lootable when the player holds a bow and their amount is game persistent. Oh, and it's a really expressive way to do art too: His Item: The Survival Gear Robin Hood also holds a survival backpack. This makes him able to consume some of his health and produce food items. His Stats Robin Hood's stats are somehow similar to the True American's, but where the latter gains more in HP the first has a significant advantage in Agility. The Swordsmen Nicknamed "The Standard", this is the default character and probably the only character that isn't an unlock. His Weapon: The Sword The Standard uses a basic sword. It only has a melee attack with a set range. It's quick enough to repeatedly attack in quick succession, but that's about it. His Item: None The Standard doesn't hold any items nor any other equipment whatsoever. I'm not sure whenever or not there should be an unlockable item for this character much like The Binding of Isaac or not... His Stats This is a placeholder stats, but the idea is that this character is an all ground one. Minor Tweaks Upgraded particle physics. Now each rock crumbles made by breaking either a breakable wall or a rock will react according to their position and the explosive force of the bomb. Fixed a bunch of bugs with collision layers. Added locked folder items. This means that in order to open these you'll need a key. Optimized the VaporMaker album image system. Now the colour mapping takes place in the GPU rather than the CPU, saving memory and quickening the whole VaporMaker process. Optimized shaders so that the building of the game doesn't take ages. Added colour palette support for many GUI components. Made GUI component's colour listen to any palette changes so that their colour would always follow the palette. A lot of refactors and fixes. Made some GUI layout more responsive. Fixed bugs. a lot. Made State loading more dynamic. Next week What is planned next week is to polish and balance those new classes. I also want to polish some stuff that I've noted down. After that, It's up to bosses. Afterwards, it's the usual suspect... I got to say: the more and more new features get implemented the more and more this thing I have starts to resemble an actual game.
  12. jb-dev

    A loading screen

    From the album: Vaporwave Roguelite

    This is how loading screens will look like. I still have no idea whenever or not I could show things like tips or anything alike...
  13. Last week wasn't concretely visual or anything... It was mainly an integration one. There was also some graphical updates plus I've also made part of the options menu. Graphics First, let's talk about those graphics. Previously, the skybox was of a solid colour. This was a placeholder skybox. However, I thought about it and came to the conclusion that it was about time to have a better one. I've searched on the internet and found this lovely gradient skybox, so I've added it to the game but with a bit of pizzazz. Basically, I've added a screen-positioned grid pattern and make a big dot in it representing the sun. I've loved it so much that I've decided to add it to my levels too! Here's how it looked previously: And here's how it looks now: I personally like how this looks. Also, previously the directional light that lights the scenes weren't following the colour palette, so I've added a bit of script to help with that, hence the different lighting... Integrations I've mainly had to link up the menus and the actual first level of the game. To do this I've used the Scene loading functions of Unity. I've added a nice loading screen with a working loading bar that fills up to the loading process' actual progression. There is, however, a bit of a hiccup while loading the level. The game window actually freezes and seems like it stopped working... This might be related to the loading process of the Music Player I've previously made: while the process loads in a different thread, the first load is done on the main process. This makes the game hang up until the first song actually loading... This is something I'm currently working on. Options Secondly, I've also added a bunch of drivers to the options screen. Let's take a look at each tab... General This is where general options will be. Right now, there's only a dropdown to switch languages, but eventually, there might be more options if it's needed. Graphics This is where the meat is. Here, the player can set many types of graphical settings, like resolution and quality settings. There are six quality presets: Very Low, Low, Medium, High, Very High and AESTHETIC (Ultra). There's also a seventh one, called Custom, where the player can set each graphical settings separately. As of now, this setting doesn't do anything, as it is only a driver. Audio This is where the player can set all its audio configs. Mainly this is where the player can adjust any volume sliders. There's also another section called "Others" where other audio settings can be set. As of right now, there's only a toggle indicating whenever or not the VaporMaker is active. There might be more options in the future. That's about it for options: the other tabs are still in development. Minor Updates Reflection Probes! Now there's a bunch of reflection probes in special rooms. This means that lights will feel more natural and specular materials will look better. Shader optimizations. I've optimized some shaders and the game builds quicker. (Speaking of build...) I've created a really dirty private build of the game. While still building, there was a lot of bugs and isn't really presentable. The important thing is that it builds properly and without any hiccups. I've fixed some bugs with state loading and overall scene progression. Previously the level scene was completely separate from the menu screen, meaning that a lot of states appeared twice between the scenes. Because these are supposed to be singletons, many of the level's controller were removed, breaking everything. Next week Next week is going to be the continuation of the integration. I mainly need to fix my loading screen hiccup problems and many other things. Afterwards, I might need to make an actual progression between each level. As of right now, there's only one level with no exits. Afterwards, it's gonna be boss time! And then after it's the usual suspects... I gotta say, with all that integration, I'll be soon ready to actually publish some kind of demo or test build by the end of December.
  14. jb-dev

    Menu V2

    From the album: Vaporwave Roguelite

    Another version of the main menu. This one has a more complete skybox. I'm not sure if it'll be a good idea to use the same shade on the actual Levels skyboxes...
  15. jb-dev

    Diablo:Immortal

    If that would be the case then I think that Blizzard should have not have announced it at Blizzcon (IDK if Blizzcon-like event exists in Asia, though) Banjo-Kazooie Nuts and Bolts, anyone? 🙃 I've just looked at the Google Play Store top popular games list, and most of them were either strategy or puzzle games (there might have been one or two arcade games at best). While it's true that the market IS bigger on mobile it's only bigger within certain genera. Right now Blizzard is literally trying to port Diablo's genera and overall gameplay to the mobile which is statistically not really viable. As a rule of thumb, if you use virtual buttons or joysticks in mobile then you should really go back to the drawing board and really think about the UX... For example, let's take arguably one of the most popular mobile game ever : Angry Birds. The game uses intuitive controls that are simple to understand, which makes the game easy to play in short bursts. But most importantly, there's no virtual buttons nor virtual joysticks (aside for really simple things like pausing and such) So If the controls are too complex to understand in a fraction of a second then your mobile game is doomed to fail, and that even if the possible revenue is 15x bigger on phones than on PCs. (And so far, Immortal's screenshots aren't promising...)
  16. jb-dev

    Diablo:Immortal

    I kinda think that this wasn't the time nor the place to announce this. For what I've heard many of these people attending the event were die-hard PC gamer, so this was just distasteful of Blizzard to do that. It's a bit like talking about Xbox to a Sony crowd. (Personally I think that making a mobile game need a whole lot of consideration and UX knowledge. You can't just plop a virtual joystick and call it a day)
  17. Last week started with some kind of epiphany: I've kinda forgotten the idea of the iterative top-down development of Agile development, which is sad. So after a bit of reflexion, I've decided that it was time to start building stuff like menus, save files and playable characters. This way I could ship a playable alpha quicker, meaning that I could start getting monetary funds sooner. But anyway, let's get right to it! New Shader Beforehand, let me show you my newest shader. This one is supposed to mimic Memphis-like designs. The name "Memphis" comes from the "Memphis Group", an Italian designer group that tried to design THE design of the decade (which coincidently was the 80's). This design was mainly expressed through furniture, although it was still used in many other media. Here are some examples: (Fun fact: most furniture made by the group was actually bought by David Bowe for some reason. By far he had the most exhaustive collection.) But anyway, here's the shader: The shader is supposed to represent a rough texture typically found in many Memphis designs like so: As for the actual shader, I've first experimented with that kind of noise while making splash screens mockups in Blender. Here's the original mockup: (Notice the green bar on the left) This was achieved by using the Musgrave cycles node. The main gist is to use a Perlin noise to which we apply different types of filter to change their appearance to match the desired texture. So I've figured that if I wanted to translate this shader in Unity I needed to take a look at blender's source code, which is coincidently open. Here's the final shader code: float4 mod(float4 x, float4 y) { return x - y * floor(x / y); } float4 mod289(float4 x) { return x - floor(x / 289.0) * 289.0; } float4 permute(float4 x) { return mod289(((x*34.0)+1.0)*x); } float2 fade(float2 t) { return t*t*t*(t*(t*6.0-15.0)+10.0); } float4 taylorInvSqrt(float4 r) { return (float4)1.79284291400159 - r * 0.85373472095314; } // Classic Perlin noise float cnoise(float2 P) { float4 Pi = floor(P.xyxy) + float4(0.0, 0.0, 1.0, 1.0); float4 Pf = frac (P.xyxy) - float4(0.0, 0.0, 1.0, 1.0); Pi = mod289(Pi); // To avoid truncation effects in permutation float4 ix = Pi.xzxz; float4 iy = Pi.yyww; float4 fx = Pf.xzxz; float4 fy = Pf.yyww; float4 i = permute(permute(ix) + iy); float4 gx = frac(i / 41.0) * 2.0 - 1.0 ; float4 gy = abs(gx) - 0.5 ; float4 tx = floor(gx + 0.5); gx = gx - tx; float2 g00 = float2(gx.x,gy.x); float2 g10 = float2(gx.y,gy.y); float2 g01 = float2(gx.z,gy.z); float2 g11 = float2(gx.w,gy.w); float4 norm = taylorInvSqrt(float4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); g00 *= norm.x; g01 *= norm.y; g10 *= norm.z; g11 *= norm.w; float n00 = dot(g00, float2(fx.x, fy.x)); float n10 = dot(g10, float2(fx.y, fy.y)); float n01 = dot(g01, float2(fx.z, fy.z)); float n11 = dot(g11, float2(fx.w, fy.w)); float2 fade_xy = fade(Pf.xy); float2 n_x = lerp(float2(n00, n01), float2(n10, n11), fade_xy.x); float n_xy = lerp(n_x.x, n_x.y, fade_xy.y); return 2.3 * n_xy; } /* Noise Bases */ float safeNoise(fixed4 p) { return cnoise(p); } float noiseMusgraveHeteroTerrain(fixed4 p, float H, float lacunarity, float octaves, float offset) { float value, increment, rmd; float pwHL = pow(lacunarity, -H); float pwr = pwHL; int i; /* first unscaled octave of function; later octaves are scaled */ value = safeNoise(p) - offset; p *= lacunarity; for (i = 1; i < (int)octaves; ++i) { increment = (safeNoise(p) + offset) * pwr * value; value += increment; pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); if (rmd != 0.0) { increment = (safeNoise(p) + offset) * pwr * value; value += rmd * increment; } return value; } fixed4 frag(v2f IN, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target { half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; fixed2 g_Resolution = _ScreenParams.xy; float factor = -IN.texcoord.y + 1; float dimension = max(_NoiseDimensions, 1e-5); float octaves = clamp(_NoiseDetails, 0.0, 16.0); float lacunarity = max(_NoiseLacunarty, 1e-5); fixed4 p = screenPos; p = p / _NoiseScale; float intensity = 1.0; float offset = smoothstep(1, 0,factor); color.rgb = lerp(color.rgb, _NoiseColor.rgb, saturate(intensity * noiseMusgraveHeteroTerrain(p, dimension, lacunarity, octaves, offset))); return color; } The Menus Then the next big thing was to create different menus in the game. In order to achieve a somewhat proper menu navigation, I've first created a simple navigation flow chart that tells what is the flow between two screens. For example, the player firstly goes through the Title screen, then goes to the main menu and so on. As for the actual implementation, I've decided to use the State design pattern. This way I can easily create simple flows between two screen. First, I've got an AbstractMenuState class: using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public abstract class AbstractMenuState : MonoBehaviour { public AbstractMenuState m_nextMenu; public AbstractMenuState m_previousMenu; public Animator m_menuAnimator; protected GameObject m_menu; public GameObject menu { get { if (!m_menu) { m_menu = transform.GetChild(0).gameObject; if (!m_menuAnimator) { m_menu.GetComponent<Animator>(); } } return m_menu; } } // Show the menu public virtual bool ShowMenu() { menu.gameObject.SetActive(true); m_menuAnimator.SetBool(MenuState.instance.openParameterId, true); selected = firstSelectable; return true; } // Hide the menu public virtual bool HideMenu() { m_menuAnimator.SetBool(MenuState.instance.openParameterId, false); StartCoroutine("DisableMenuDelayed"); return true; } // Things to do when we procede to the next menu public virtual void OnNext() { } // Things to do when we return to the previous menu public virtual void OnPrevious() { } IEnumerator DisableMenuDelayed() { bool closedStateReached = false; bool wantToClose = true; MenuState instance = MenuState.instance; // We're disableing the menu once its animation transition is done while (!closedStateReached && wantToClose) { if (!m_menuAnimator.IsInTransition(0)) { closedStateReached = m_menuAnimator.GetCurrentAnimatorStateInfo(0).IsName(instance.closedStateName); } wantToClose = !m_menuAnimator.GetBool(instance.openParameterId); yield return new WaitForEndOfFrame(); } if (wantToClose) { m_menu.gameObject.SetActive(false); } } public GameObject firstSelectable { get { // We search for the first selectable child Selectable[] selectables = m_menu.gameObject.GetComponentsInChildren<Selectable>(true); for (int i = 0, length = selectables.Length; i < length; ++i) { Selectable selectable = selectables[i]; if (selectable.IsActive() && selectable.IsInteractable()) { return selectable.gameObject; } } return null; } } public GameObject selected { set { //Select the GameObject. EventSystem.current.SetSelectedGameObject(value); //If we are using the keyboard right now, that's all we need to do. var standaloneInputModule = EventSystem.current.currentInputModule as StandaloneInputModule; if (standaloneInputModule == null) { //Since we are using a pointer device, we don't want anything selected. //But if the user switches to the keyboard, we want to start the navigation from the provided game object. //So here we set the current Selected to null, so the provided gameObject becomes the Last Selected in the EventSystem. EventSystem.current.SetSelectedGameObject(null); } } } } Then I've also got a MenuState MonoBehavoir that is composed of an AbstractMenuState instance: using System; using System.Collections; using System.Collections.Generic; using UnityEngine; // This is a Singleton public class MenuState : MonoBehaviour { public static MenuState instance; private bool isReady = false; public AbstractMenuState m_currentMenu; /// <summary> /// Awake is called when the script instance is being loaded. /// </summary> void Awake() { // Setup singletion if (instance == null) { instance = this; } else if (instance != this) { Destroy(gameObject); } DontDestroyOnLoad(gameObject); isReady = true; } const string OPEN_TRANSITION_NAME = "Open"; const string CLOSED_STATE_NAME = "Closed"; private int m_openParameterId; public int openParameterId { get { return m_openParameterId; } } public string closedStateName { get { return CLOSED_STATE_NAME; } } /// <summary> /// This function is called when the object becomes enabled and active. /// </summary> void OnEnable() { //We cache the Hash to the "Open" Parameter, so we can feed to Animator.SetBool. m_openParameterId = Animator.StringToHash(OPEN_TRANSITION_NAME); //If set, open the initial Screen now. if(m_currentMenu) { m_currentMenu.ShowMenu(); } } // Proceding to the next menu public void NextMenu() { AbstractMenuStrategy next = m_currentMenu.m_nextMenu; if (next != null) { m_currentMenu.OnNext(); m_currentMenu.HideMenu(); next.ShowMenu(); m_currentMenu = next; } } // Returning to the previous menu public void PreviousMenu() { AbstractMenuStrategy previous = m_currentMenu.m_previousMenu; if (previous != null) { m_currentMenu.OnPrevious(); m_currentMenu.HideMenu(); previous.ShowMenu(); m_currentMenu = previous; } } } When the player clicks an OK button (for example), then the NextMenu() function of the MenuState is called. This internally calls the Show/Hide function of the needed AbstractMenuState and so on. The same thing is true for any "Cancel" type of button, but using the PreviousMenu() function instead of the NextMenu() ones. Because I'm using Unity, I can then just drag and drop each AbstractMenuState instance the m_previousMenu and m_nextMenu fields to recreate my flowchart. I can even technically set these dynamically based on which button was pressed (like in the main menu screen for example) So let's get right into each menu then! Title Screen This is the title screen. The player just presses any keys to pass right through it and go straight to the main menu. Main Menu This is the main menu. The player can navigate to different screens by pressing one of the menu's buttons. Let's see what each button do. Quick Play This button is quite simple; it quickly prepares a game by reusing previously used parameters. This way the player can quickly get in the game with just one click. This automatically picks the last used savefile and character and puts the player directly at the confirm screen. If it's the first time the game is launched, then the first savefile and the default character are used. This is kinda useful. You only need two clicks and you're ready to go! Play This one is the long version of the Quick Play button. The player then needs to pick a save file from 4 different saves. Right after that, the player chooses a playable character and is then put right at the confirm screen. Options This is self-descriptive. It puts the player at the options screen. Exit This button spawns a quitting prompt. If the player chooses "Yes", then the game quits. Otherwise the prompt closes. Savefile Screen This screen is where the player can choose which save files to use. A savefile holds many different types of pertinent statistics and information (Things like unlocks, run statistics and game completion). It also holds things like the last used character and so on. At this screen, the player will be able to do many different types of savefile manipulation like copy and erase. As of now, these operations aren't implemented, so only the OK button works. Before any operation buttons are enabled, the player must select a save file by clicking (or selecting if you use a controller) a specific save file. A selected savefile will have a green checkmark on its upper-right corner. When the player enters the screen the last used savefile is highlighted. If the game is fresh then the first savefile is used. Each save file also shows things like a progression mark and a last used date. I have yet to precise how the progression percentage is calculated, though I have some ideas on how this can be done (maybe thought unlocks and achievements, but I'm not sure yet). The player can also go back to the main menu using the "Cancel" button. Once the savefile is chosen, the screens translate to the character selection screen. Character Selection Screen This screen is where the player chooses its characters. Each character comes with different stats, focus and equipment. Each of these characteristics can be inspected through the white panel in the lower half of the screen. Like how these components behave in the pause menu, some of these also have tooltips. The characters themselves are laid in a circle formation. The layout system is dynamic enough to have n playable characters, and it's using the game object's children to do all of the layings. The currently selected playable character has a thick outline and it often the one closest to the camera. Also, the currently selected character is determined by the selected savefiles' last used character. If the data is missing then it goes to the default character. In order to change the currently selected character, the player simply uses both left and right arrows at both sides of the screen. This simply turns the contraption by a given angle (calculated from the amount of object present in the root game object). This changes the outline so that it'll follow the currently selected character. Again, the player can either go back to the save file screen or proceed to the confirmation screen. Confirmation Screen This is the last screen before starting the run. In this screen, the player can review its run parameters (like the used save file and the selected character). We can also set the generation seed at this point. As of now if the player chooses to go back then he goes all the way back to the main menu... I'm not sure if it's a better idea if we store from which screen the player came from and use this to send it back to the relevant screen. Options Screen This is where the options will be displayed. I didn't have the time to complete it yet, but it's still accessible. There will be different types of settings typical of any modern games, like graphical settings and whatnot. I've also planned to show statistic here. However, I'm not sure if I should have different tabs/view for each saves file... Technically I could place the save file selection right before the main menu and only show one statistics screen, but I'm not sure yet. That's about it for screens. Minor upgrades Because of the new shader, I've also changed some of the pause menus to use the new shader: There are also some GUI elements that also use these, like the aesthetics lines and health bars... I cant show them just yet because the menu kinda blocks the access to levels right now... I've implemented a playable character class that stores any character specific things like equipment and such; Also, save files are in. There's a simple serialization/deserialization going on with these: I'm not sure when to save though. Right now it's after each savefile changes (like when the player uses a crystal and whatnot). I've also added a GUI shader that uses a special "Hard Light" blend mode when dealing with GUI element textures. Normally Unity uses chromatic multiplication to blend GUI textures with colours. This, however, makes any pure white pixels on the texture take the actual GUI colour; (Hard Light on the left Left, Multiplication on the right) I've added a bunch of textures on buttons and panels. This really looks AESTHETIC now. I've added a normal mapped variant of the AtlasShader. This is quite useful for the menus' statues. Speaking of which these are actually still technically low poly (under 600 tris each!). Their normal maps were baked from high poly models with over 2M verts! Needless to say that Blender crashed a bunch of times while manipulating these... I've finally switched some GUI components to used the Unity's Graphic class rather than coding everything by hand and manually calling the CanvasRenderer. This makes the GUI element's code much cleaner and readable! Next Week If everything goes to plan the game will be in a playable state by beginning 2019 (or so I hope). There's still some work to do with menus... For example, the options screen isn't fully there and so far no runs can be started. I didn't complete the actual level completion, and this might be a good thing to do afterwards... Afterwards, I think I'll be able to code at least one dummy boss, with a somewhat simple attack pattern and whatnot. After it's the usual suspects: Relics, Capacities, Activated items, Equipment... The list goes on.
  18. jb-dev

    Menu transitions

    From the album: Vaporwave Roguelite

    This is how menu translate to one another
  19. jb-dev

    Main menu draft

    From the album: Vaporwave Roguelite

    This is a nice first draft of how the main menu will look like. I've was inspired by Memphis design while making this.
  20. Hello there, welcome the 18th edition of your favourite weekly update! 😃 Last week was really intense. A lot of things were going on at once, so without any further ado, let's cut to the chase! Pieces of equipment First, there's now pieces of equipment in the game. Players can now stumble upon t-shirts, runnings shoes, gloves and baseball caps during their run. Here's a picture of pieces of equipment in malls: In essence, pieces of equipment give the player unitary stat bonuses (things like +1 or +3) when worn. Pieces of equipment can also have a focus alignment: when worn by the player, his focus will be progressively pulled towards its focus alignment. There'll also be additional stats bonuses (and even capacities) when his focus is aligned with a piece of equipment. This means that managing your equipment is critical to have a good run. The player can hold different kinds (or slots if you want) of pieces of equipment. These are: Headware (caps, hats and whatnot); Neckwear(necklaces, neck chains, etc.) Chestwear (T-shirts, chest plates and so on); Handwear (Gloves, rings, etc.;); Footwear (boots, shoes and whatnot). The player can only hold one piece of equipment per slot. He can, however, replace his equipment by simply grabbing another one. GUI refactored Second, I've also done a big GUI overall. Although often forgotten by both gamers and developers, the GUI has an important role in games: they are often the primary way for games to tell their player critical pieces of information like their current health, money or current stats. The GUI was actually a copy-paste from the game's previous iteration with Lemur and JMonkeyEngine. With this refactoring, I've tried to use Unity's GUI components at their fullest. I personally think I've cut the mustard with this one. Status Screen Let's take a look at the status tab of the pause menu: As you can see, everything was kinda bare. There were no ways to tell where everything was, and quite frankly it was all over the place. Here's a look at the newly redesigned one: Now that's prettier! Things are nicely labelled, aligned and positioned. There are even components that were previously hidden, like the Relics section and the Focus section. There's even an Equipment section, along with a new Item section. Also, the status screen is more interactive than ever before! Some components have tooltips, showing useful things like name, description and many more. Relics Let's take a closer look at the relic section: This is where all collected relics go. If no relics were collected yet, a placeholder text is displayed. Each relic is displayed using a nice pictogram from my custom Open Type font. As a bonus, the section is scrollable. This means that if there's a whole lot of relics the view can be truncated and controlled using a scrollbar. (Keep in mind that I've enlarged the icons sizes to show the scroll bar) Equipment The display is quite simple: it's a minimal silhouette of a human body. Each equipment slots are placed according to their type (e.x. the headwear is on the head, etc.) When a slot is empty, a pale "X" is displayed. Otherwise, a glyph representing the grabbed piece of equipment is displayed. Each of these has tooltips attached to them, showing the pieces' name, description and quality. Focus This is a barycentric coordinate component rendered as a triangle representing the player's focus. The only thing new is that it's now properly aligned and labelled... (Now look how happy it is with its proper title!) Item This component shows the currently hold activatable item. Not unlike equipment slots, having no held activatable items yields a pale "X". It also has a tooltip displaying the item's name and description. Foods Previously, foods timers were rather obnoxious: their timers were displayed right in the middle of the screen. If many foods were eaten at once then all their timers would overlap. Now, food timers are properly displayed with tooltips. When the player eats a food item it will place itself to the right of the pause menu in a vertical stack. This is not unlike how Minecraft deals with its potions effects. Once a food timer runs out, the component is removed. Dialogue box Previously, dialogue boxes were of static sizes. They were really big with a whole lot of empty space everywhere. Now that I use Unity's GUI layout at their fullest, dialogue boxes can be resized according to their content. Gone are the static sizes! Here's how it looked before: As you can see, there was a lot of wasted space. It also arbitrarily breaks its text for no other reason than to keep its dimensions. And now look at the new one: Now there's almost no wasted space. Everything fits snuggly now and feels more believable. Restroom I've previously added a restroom room but it wasn't functional yet... With the inclusion of pieces of equipment, the toilet can now fulfil its role as intended. The idea is that the player can discard one of his equipment by flushing it down the drain. The toilet will obviously clog afterwards, as generally speaking toilets aren't made for this kind of stuff, making it a one-time use. Flushed pieces won't appear later on in landfills so this is permanent. Here's a look at its dialogue box: Within the dialogue there are some similar components to those used in the pause menu's Equipment section, but with a twist. Each of these components acts as toggles (or radio toggles if you want). When the player chooses one of his equipment to flush a visual queue is displayed within. Below that, there's a bit of text that indicates which piece is currently selected. After everything is said and done the player can then click the "OK" button at the bottom of the box. This will spawn a confirmation popup: The player can then just confirm everything by pressing "yes", after which the equipment is flushed and the toilet is clogged. Minor Updates Random collectables are now chosen by asserting how much the player needs a particular collectable: We then can do a luck test to see if the player actually gets to have what he needs or not: Yes, this is cruel for some, but also rewarding to others. Fixed some shader stuff; Optimized the GUI (Dhu 🙃😞 Previously I wanted to reuse dialogue boxes. This was however kind of hard and cumbersome, especially for dialogue boxes that were rarely used at all: It was also a pain to deal with this with the Restroom's dialogue (because the whole process uses TWO boxes). Abstracted GUI window controller classes: Horray for abstraction! 🙏 Re-added the Clothes Mall, which was removed due to lack of equipment; Added a bunch of placeholder notification everywhere: These would be polished later on. foreshadowing??? 😶 Added a whole lot of localized text: Now begone "Localized text not found"! 😉 New Music I've also had the time to compose some stuff during last week. Take a look: I'm not quite sure where to use this, even if I titled it as "Tutorial", I'm not even sure if there's gonna be one. Next Week Boy, this was a mouthful! But when it rains it pours, and this was really a necessary evil. I doubt the next one would be as filled to the rim as last one. However, there are still things to do. It ain't over till the fat lady sings. I think I'll work on notifications next: They are in a dire need of polish. I also need to continue the polishing of GUI: I didn't walk the whole nine yards. Afterwards, it's the usual suspects: Rooms, Relics, Capacities, etc. But then again I have bigger fishes to fry. 😉
  21. jb-dev

    Better food timers

    From the album: Vaporwave Roguelite

    This show how food timers are being displayed. This is not unlike how Minecraf does it with its potions.
  22. jb-dev

    Item flushing

    From the album: Vaporwave Roguelite

    This is the confirmation dialog box that is shown when the player is about to flush one of his piece of equipment down the drain.
  23. From the album: Vaporwave Roguelite

    This is the redesinged version of the equipment screen. Now each sections and components are split and aligned properly.
  24. jb-dev

    Equipment screen

    From the album: Vaporwave Roguelite

    This is how the game displays the players' current equipment.
  25. jb-dev

    Pieces of equiments in a clothes mall

    From the album: Vaporwave Roguelite

    This shows some default placeholders pieces of equipment. Because the game doesn't take place in a fantasy settings like most roguelites, I try to keep with the vaporwave theme a lot when it comes to modelings items...
  • 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!