• entries
36
11
• views
3056

An update blog for projects going on that have some degree of interest

## Algorithm Flexible Room Layout algorithm

While making a roguelike game, procedural generation have to be quick and yet intriguing enough for the generated level to be fun to just pick up and play. There are many ways to generate and laying out procedurally generated rooms. In The Binding Of Isaac, for example, you have many different types of regular room presets.  The generator just picks a preset based on things like room placement and size. Because those rooms are always of fixed size, this is a nice compromise. By having handmade presets the generated level is somewhat believable (i.e. there are no gaps or obstacles below a room door or secret room and whatnot).      Another example would be Nuclear Throne.  The game takes a different approach to procedural generation by keeping it relatively simple. Because it's not room-based like The Binding Of Isaac, there are more things like caves and large open area.  The gameplay also plays into this, as the player needs to eliminate every enemy to spawn a portal to the next level.      Because my game is somehow more inspired by The Binding of Isaac, the right way to procedurally generate rooms would be to use presets, and this is how I make special rooms. However, there's a big difference between The Binding Of Isaac and my game: my regular rooms aren't always the same size. This means that rather than having presets of regular rooms as well as special rooms I need something more flexible and, most importantly, dynamic.. The anatomy of a Room In my game, as I've said in a previous post, levels are big two-dimensional arrays from which the level geometry is generated. Every room of a level is made using a BSP tree. I won't go in details much on how rooms are generated, but in essence, we create a grid from which we trace a path between two rooms and sparsely attach bonus rooms along the way. Because I already have rooms sizes and whatnot with that level generation, I could reuse the same idea for room layouts. Within rooms, I've also set special anchor points from which props (or more precisely, prop formations, more on that later...) could be generated. Basic Layouts The idea here is to have room layout presets. Within those, presets are an array of prop formations, and each of these formations is linked to a specific anchor point. A formation has a two-dimensional boolean array that indicates whenever or not there should be a prop here. Let's take, for example, a diamond array: The dimension of the array depends on its rooms' dimensions. Here's how it's done: $$size = \left \lceil \frac{2(max(RoomSize_{x},RoomSize_{y}))) }{ 3 } \right \rceil$$ In order to change the array's content we actually use common image manipulation algorithms... Bresenham's Line Algorithm The first used algorithm is the Bresenham's Line Algorithm.  Its purpose is to simply render a line describe by two bitmap points onto a raster image. To put it simply, we get the deviation (delta, or "d" for short) in both X and Y of each point of the described line and compare both of them. Depending on the biggest, we simply incremate the point on that axis and colour it in. Here's the implementation: public void TraceLine(Vector2Int p0, Vector2Int p1) { int dx = Mathf.Abs(p1.x - p0.x), sx = p0.x < p1.x ? 1 : -1; int dy = Mathf.Abs(p1.y - p0.y), sy = p0.y < p1.y ? 1 : -1; int err = (dx > dy ? dx : -dy) / 2, e2; while (true) { m_propArray[p0.x][p0.y] = true; if (p0.x == p1.x && p0.y == p1.y) { break; } e2 = err; if (e2 > -dx) { err -= dy; p0.x += sx; } if (e2 < dy) { err += dx; p0.y += sy; } } } Midpoint Circle Algorithm The midpoint circle algorithm is an algorithm used to render a circle onto an image. The idea is somehow similar to Bresenham's Line Algorithm, but rather than drawing a line we draw a circle. To do this we also need, for simplicity sakes, to divide the circle into 8 pieces, called octants. We can do this because circles are always symmetric. (It's also a nice way to unroll loops) Here's the implementation: private void TraceCircle(Vector2Int center, int r, AbstractPropFormation formation) { int d = (5 - r * 4) / 4; int x = 0; int y = r; do { // ensure index is in range before setting (depends on your image implementation) // in this case we check if the pixel location is within the bounds of the image before setting the pixel if (IsValidPoint(center + new Vector2Int(x,y)) { formation.m_propArray[center.x + x][center.y + y] = true; } if (IsValidPoint(center + new Vector2Int(x,-y)) { formation.m_propArray[center.x + x][center.y - y] = true; } if (IsValidPoint(center + new Vector2Int(-x,y)) { formation.m_propArray[center.x - x][center.y + y] = true; } if (IsValidPoint(center + new Vector2Int(-x,-y)) { formation.m_propArray[center.x - x][center.y - y] = true; } if (IsValidPoint(center + new Vector2Int(y,x)) { formation.m_propArray[center.x + y][center.y + x] = true; } if (IsValidPoint(center + new Vector2Int(y,-x)) { formation.m_propArray[center.x + y][center.y - x] = true; } if (IsValidPoint(center + new Vector2Int(-y,x)) { formation.m_propArray[center.x - y][center.y + x] = true; } if (IsValidPoint(center + new Vector2Int(-y,-x)) { formation.m_propArray[center.x - y][center.y - x] = true; } if (d < 0) { d += 2 * x + 1; } else { d += 2 * (x - y) + 1; y--; } x++; } while (x <= y); } Flood Fill Algorithm This is quite a classic, but it's still useful nevertheless. The idea is to progressively fill a section of an image with a specific colour while  The implementation is using a coordinate queue rather than recursion for optimization sakes. We also try to fill the image using west-east orientation. Basically, we fill the westmost pixel first, eastmost second and finally go north-south. Here's the implementation: public void Fill(Vector2Int point) { Queue<Vector2Int> q = new Queue<Vector2Int>(); q.Enqueue(point); while (q.Count > 0) { Vector2Int currentPoint = q.Dequeue(); if (!m_propArray[currentPoint.x][currentPoint.y]) { Vector2Int westPoint = currentPoint, eastPoint = new Vector2Int(currentPoint.x + 1, currentPoint.y); while ((westPoint.x >= 0) && !m_propArray[westPoint.x][westPoint.y]) { m_propArray[westPoint.x][westPoint.y] = true; if ((westPoint.y > 0) && !m_propArray[westPoint.x][westPoint.y - 1]) { q.Enqueue(new Vector2Int(westPoint.x, westPoint.y - 1)); } if ((westPoint.y < m_propArray[westPoint.x].Length - 1) && !m_propArray[westPoint.x][westPoint.y + 1]) { q.Enqueue(new Vector2Int(westPoint.x, westPoint.y + 1)); } westPoint.x--; } while ((eastPoint.x <= m_propArray.Length - 1) && !m_propArray[eastPoint.x][eastPoint.y]) { m_propArray[eastPoint.x][eastPoint.y] = true; if ((eastPoint.y > 0) && !m_propArray[eastPoint.x][eastPoint.y - 1]) { q.Enqueue(new Vector2Int(eastPoint.x, eastPoint.y - 1)); } if ((eastPoint.y < m_propArray[eastPoint.x].Length - 1) && !m_propArray[eastPoint.x][eastPoint.y + 1]) { q.Enqueue(new Vector2Int(eastPoint.x, eastPoint.y + 1)); } eastPoint.x++; } } } } Formation Shapes Each formation also has a specific shape. These shapes simply define the content of the formation array. We can build these shapes using the previously mentioned algorithms. There are 9 different types of shapes as of now. Vertical line A simple vertical line of a width of one Horizontal line A simple horizontal line of a width of one Diamond A rather nice diamond shape, especially pretty in corners Circle The circle is rendered using the Midpoint circle algorithm. Especially pretty in the center of rooms Cross A simple cross shape, i.e a vertical and horizontal line align at the center.  X Shape An "X" shaped cross, i.e two perpendicular diagonal lines align at the center. Triangle An Isocele triangle. Square A solid block. Every cell of the formation is essentially true. Checkers A nice variation of the square shape. Every other cell is false. There might be more types of shapes as time goes by, but it's about it for now. Placing props Once the array is set, we simply need to place the actual props in the room. Each formation is of an actual type, i.e. rocks, ferns, etc.  (For simplicity sakes, let's say that every prop is a 1x1x1m cube. This would simplify future steps.) In order to find their position, we simply align the array's center to the formations' specified anchor point. For each prop formation, we then instantiate props for each true cells while checking whenever or not the prop would be outside its room. Afterwards, we do a precise position check to make sure no props are either partially or fully outside a room. Finally, we make sure every room connections aren't obstructed with props. And voilà, we have a nicely decorated room In Game Screenshots Here's a couple of screenshots of what it looks like in-game

## Unity Weekly Update #16 - 【﻿Ｒｅｌａｘａｔｉｏｎ】

Last week, there was a lot of thinking going on... There's still is least one new room plus many different refactoring. The Spa Firstly, there's a new room: the spa. This is a relaxing and zen room filled with classical　Ｖａｐｏｒｗａｖｅ　ａｅｓｔｈｅｔｉｃｓ.     I've based it on really generic Vaporwave images around the internet.      The gist is that the player can cure its status effect by interacting with either massage table in the back. You may or may not have seen the fountain in the middle of the room. Its water is purely refractive with a solid, almost emissive colour when perpendicularly facing its surface (like some kind of Fresnel). This shader is part of Unity's Standard Asset, so it wasn't a hassle to get it up and running. The water is also being used in the restroom's toilet. There might be other places where it might pop up in future rooms. Minor Changes I've modelled and imported a generic spherical light that makes lighting a tad more tangible and credible.
Most lights are now coloured using blackbody colour temperatures, adding a little bit more reality to most rooms. Changed the palette texture. Colours are now more distinct from each other and more contrasting for at least the default palette. This is due to some feedback saying that the palette was too much pink... Changed how most solid colours meshes are being rendered so that they rely more on the palette texture. This means that changing the current sub-pallette or even the texture itself will dynamically change the colour of those meshes as well. Made the palette initializing run within the Unity Editor. Now there's no need to run the game only to look how models are shown. This really speeds up room designs and model previews, mainly because I previously needed to compile the game and regenerate the levels until the wanted room was generated. Refactored the RNG. Now each level has its own isolated RNG state.  This means that actions taken in one level won't influence the next one anymore. This also means that a given seed at a given chance (or luck if you fancy) stat will always produce the same level with the same loot. There's still some tweaking to do, but overall the isolated RNG system is in place. Many bugs were corrected, particularly with shaders. Next Week Most significant rooms are now in the game. There are still some minor rooms left, but these can wait: those might not even make it into the game so my energy could be better used on more critical stuff. Right now, normal rooms are in dire need of polish. Like in The Binding of Isaac, there will be different types of regular rooms. Each room would have different types of decoration in them. For example, some might have loads of rocks while others won't. There are currently only two placeholders kind of regular room... I do not know how many kinds of disposition there'll be: all of this needs research, sketches and design... There's a lot of work ahead. The good news is that heavy modelling is momentarily stopped. The following week will be fundamentally a coding one...

## Unity Weekly Update #14 - Ｈｉｇｈ　Ｓｔａｋｅｓ

Last week was another modelling one, although there were some coding to be made in the last 2 days. Basically, I've continued the implementation of the pawnshop. Also, I had time to add a new room. The Pawnshop Although already functional, the pawnshop still needed some details props here and there. Here's a bunch of pictures showing the (almost) final version: As of now, the pawnshop's stock mainly consist of either prop from previously added rooms or even models of previous blender scene that went nowhere (take it as recycling I guess) I also want to point out that the cash register is modelled after classical mechanical cash registers like these ones:   There are also various guitars hanged on the back wall... Here's the actual reference I've used for the whole room: There's still the lighting to take care of... Also, keep in mind that I want to add more props from other rooms in the shop. So I still need to keep on moving along and get back to it when new props were added in the game. The Casino There's also a whole new room: the casino. This room acts like a giant slot machine for stats. Like traditional slots machines, the player simply pulls its lever to stop the currently active slot. There are 3 slots: one that states which stats the bonus applies, another one stating whenever it's actually positive or negative and finally the actual bonus amount. I won't lie: I kinda wanted to mimic Mario Party's mythical Chance Time. For those who aren't familiar, Chance Time was an event in the Mario Party games in which two players are forced to give/exchange specific items between each other. The player involved and the actual items are given by a slot machine-ish process. Here's a compilation of Chance Time events: As for the casino, I'm not quite sure whenever the player needs to buy in before the slots start spinning. What I'm sure of is that this process is only once per casino and that the bonus/malus is permanent. Also, the room is not fully decorated nor is lighted, but as of right now the main goal is to debug the actual slot mechanic. Next week Like before, next week is going to be room-centric again. There are also bugs with those slots that need to be fixed. They don't always line up correctly and sometimes even decides to give the player a completely different outcome.  Once most rooms are either fully or partially implemented, then maybe the next step would be to either fix animations or complete AIs. Afterwards, we still need capacities and relics... Some code refactoring wouldn't hurt either.

## Music New music track released - ＶＩＲＴＵＡＬ　洞窟

I've recently released on YouTube a new track part of the game's original soundtrack. I have yet to choose how this track is going to be used, but chances are that this track will be used in a cave-like level (mainly due to its title) If you got any type of feedback, don't be shy! I'm always willing to get better and am always open to criticism.

## Unity Weekly Updates #11 - Ｍｓ．　Ｌｉｚａ，　Ｉ　ｄｏｎ＇ｔ　ｆｅｅｌ　ｓｏ　ｇｏｏｄ．．．

Last week I've worked on implementing statuses in the game. To put it simply, statuses negatively affect entities. Things like poisoning or bleeding, for example, will continuously dish out damage for a specific amount of time. Statuses Here's a list of some statuses and their effects. Keep in mind that statuses times aren't final and will eventually change depending on the impact of their effects...  Poisoned This status is self-explanatory. It will damage the entity for about 20 seconds. The damage amount will increase linearly through time.  Burning In essence, the entity is burning. Not dissimilar to being poisoned, the burning status also damages the entity for 20 seconds. The difference here is that the damage will increase using a reciprocal function.  Bleeding The entity is bleeding heavily. Again, that status is like the previous two. The difference here is that the damage will increase logarithmically.   Frozen The enemy is frozen solid. It can still move but at a reduced speed. Can also attack, but at a slower rate than usual. It will go away after 20 seconds.  Damned The enemy is cursed. For 20 seconds, the entity will be extremely unlucky.  Any luck tests will fail regardless of the entity's current luck.  Paralysed The entity is paralyzed. For 20 seconds, the entity can't move.  Frenzy The entity is caught up in a violent frenzy fits. If the entity isn't the player, then they will ignore the player and attack its friends.  If the entity is the player, then the situation is reversed: every entity will attack the player. It lasts for 20 seconds. After then, the fits end. Here's a video of frenzied enemies fighting themselves: InAFrenzy.mp4  Stunned The entity is blinded and incapacitated. A big and blinding flash is produced. The affected entity retrains their mobility, but both vision and earing are temporarily lost.  Knocked out The entity is knocked out. it can't move or see... A mix between paralyzed and stunned, except that everything will black out rather that light up. Statuses visual effects Each of these effects will have their own visuals to help to identify what type of effect is induced in who. If the effect is applied to the player, then a vignette effect is applied to the screen.  This effect actually has a nice wavy effect among other things... Here's a video of it: wavy.mp4 When inflicted by the frozen status, the player will also see ice crystals forming on their screen, just to be fancy.  If otherwise an AI is given a status, then the same pattern will be applied to it. The pattern is also screen aligned, making it really abstract. New Relics and Activated items Because statuses are now fully implemented in the game, there's now even more relics and activated items. These are directly related to statuses and give the player unique capacities like to those as well. Relics There are 4 new relics. These are all related to statuses in one way or another... Hot dreams This is an abstract representation of a sunset. It's actually quite cliché in 80s aesthetics... This relic also does billboarding. There are just some shapes that don't translate well in 3D... With this, the player is able to set entities on fire (thus giving the burning status) to attacked enemies. These attack can be direct (like a hit) or not (like a laser beam).  As long as it originated from the player, it's all right. Here are its modifiers: -5% ATK +5% AGL Ice drop This is an ancient artifact resembling a raindrop. While holding it, any attack received or given will result in the other party to receive the frozen status. Here are its modifiers: +10% DEF -5% ATK Crystal Cola This is a clear cola. It's supposed to represent a Crystal Pepsi. This relic gives the Purifier capacity. In essence, it can make the player resistant to status changes. Here are its modifiers: +10% LCK -5% ATK Crystal Tea A nice tea beverage. It's a reference to Arizona green tea. It has the Purifier capacity and also speeds up attacks. Here are its modifiers: -25% ATK +25% AGL Activated Items There's only one new activated item: the Lipstick. Lipstick Alignment: Future Funk This is a lipstick. A red one in fact. While holding it, the player will experience a small growth...  When activated, the item will make any hostile entities in a 25m radius receive the frenzy status. Here are its modifiers: -20% LCK Minor changes There weren't a whole lot of other changes. But the AI was considerably changed to include status effect in their behaviour (ex: stunned enemies can't spot the player or frenzied enemies will attack other enemies)... Next week There's still a lot of work on status effects. For example, not all statuses have patterns, and there's also more effects to be added and tweaked here an there. If there's anything new, it could be better props or even more specials rooms... After all, now that statuses are in, there's a lot of things that can be implemented.

Last week I've worked on two things: Foods and Activated Items. I can safely say that my goal was achieved, and even surpassed. I've managed to add three working Activated Items and a whopping 9 foods in total. So let's dive right into it. Focus system crash course Before we dive right into activated items, we first have to know about the focus system. The focus system is like the classes or specializations system in most RPGs. Except that the focus system is actually quicker and is overall much more simpler than traditional RPG class system. (Because it's in a roguelike game and permadeath exists) In essence, each time the player uses those items, then its focus will shift through three poles: Vaporwave (Rogue/Assasins), Future Funk (Marksmen) and Hardvapor (Brawler). Having a certain focus can results in additional bonuses in certain stats, and can even give weapons and other items different type of bonuses and capacities. As of right now, no actual bonuses are implemented. This is because the focus system is primarily linked to the player's equipment... These aren't in the game just yet... Activated items If you played The Binding of Isaac, then you may be familiar with this concept. The idea is to have an item that can have an effect when manually triggered. Activated items work just like this: they are items that the player can activate. Most of the time, these give additional abilities to the player, like becoming temporarily invisible. Activated items can also have relic-like capacities that apply as long as the item is held, and can also have modifiers. Items can also have a focus alignment. Right now, only three of these are functional in the game. The Cellphone Alignment: Vaporwave This is an old piece of junk. It's supposed to represent an old Motorola brick phone. With this phone, the player is able to set up a one-way teleportation trip. First, the player needs to set up an exit point by activating it. This will create a weird sphere of spatial distortion Afterwards, when the player activates the item once more, they will be instantly teleported to it. Useful when you're in a huge level and want to get back to a specific room like a mall after getting more dosh. Here are it's modifiers: -5% ATK -10% HP Survival Gear Alignment:  Hardvapor This activated item is supposed to represent a survival backpack. With this item, the player can sacrifice its health for foods. Here are its modifiers: -20% AGL -10% HP This Alignment: None This is this or at least my interpretation of it. In my head, an object always was a big red specular sphere. Maybe it's because I started making games with Game Maker? Perhaps... With This, the player can reroll all items in a 25 meters radius for 10$. Here are the modifiers: +25% LCK -10% HP Foods Foods are like temporary relics. They sometimes have capacities like relics and also have modifiers that are usually out of this world. When the player eats foods then a countdown is initiated. When the countdown is finished, all modifier and capacities given to the player are removed. Right now every food lasts for about 5 seconds. This will be individually tweaked based on things like modifiers and capacities... Here's a list of foods in the game: Pineapple This is a simple pineapple. Nothing special here Here are the modifiers: -10% LCK +25% ATK +50% DEF -10 AGL Banana A normal banana. Here are the modifiers: +75% LCK +68% DEF +50% AGL Lime A normal lime, cut in half. Here are the modifiers: +10% LCK +25% ATK +75% AGL -10% HP Pineaburger A burger made of a slice of pineapple. There's also a lettuce leave thrown in there for good measure. Here are the modifiers: -10% LCK +25% ATK +50 % DEF -10% AGL Double Deluxe A plain waffle topped with whipped cream and glazed with some kind of syrup (claimed to be raspberry, but sure doesn't taste like it) Here are the modifiers: +75% LCK +10% ATK -25% DEF +10% AGL +5% HP Instant Ramen A normal instant ramen bowl. chopstick included. Here are the modifiers: +50% ATK +50% AGL -25% HP Bento box A somehow 80s bento box, with crazy shapes, lines and colours. Comes with chopsticks. Here are the modifiers: +25% LCK +10% DEF -10% AGL +75% HP Toast Sandwich A somehow plain looking sandwich. It appears to have a heavily buttered toast in the middle. This is one of the food that can give you a capacity. When eaten, it gives the capacity to do a double jump. Here are the modifiers: -10% LCK +25% DEF -50% AGL -5% HP Minor updates There are now proper debug tools, such as spawning folders and so, making the testing phase so much quicker Resolved some bugs with mall inventory not being properly chosen Finally added relic/foods/equipment/weapon spawning to folders items. This means that the player can finally get good loot from folders. Fixed an infrequent bug that gives wrong orientation to some rooms (i.e. some breakable wall used to spawn perpendicular to the rooms) Added a bunch of things to add effects like 2d drop shadows and outline rendering Next week Next week I planned to add statuses to the game. Statuses like poisoned of stunned. There's already a list of statues that was previously prepared. Now it's just a matter of implementing those. Otherwise, if I have the time I'm probably going to continue the implementations of items/capacities... I also realized that while testing things out I just forget I'm testing and I just play the game (even though there's only one unfinishable level) I genuinely had fun... I wish this feeling will get bigger as this is developed. ## Unity Weekly Updates #9 - Ｒｅｌｉｃ Ｍａｎｉａ In my previous update, I've said that the next step would be to integrate relics in the game. I'm proud to say that I've managed to implements some of the planned relics. What are Relics? If you played The Binding of Isaac, you may recall it's Passive Collectibles. Relics are the equivalent in this game. In other words, Relics are run-scoped upgrade the player either find or (if they're lucky) buys in malls. These give stats percentage bonus (i.e. +25% bonus in attack) and also give the player special capacities. What are Capacities? Capacities are passive (i.e. not explicit, or don't need special inputs) abilities the player gain. For example, one capacity could be the capacity to shoot laser beams at each attack. There's a science to it, though. They need considerable balance tweaks here and there just to make sure the game won't break with these capacities. Some capacities are linked to relics, and others not. For example, a capacity can be linked to a specific Item or even Foods. Right now, there are no items or Food in the game, so we'll talk about those in due time... Stats crash course Before we continue with the relics, we first need to understand stats. Stats are exactly what you think they are: just like in most RPG, they quantify the skills of a given entity. In the game, there are 5 base stats : Chance (or Luck if you're fancy): This stats dictates the probability of a player to have good things happen to them (e.x. good loots spawns after an enemy is killed or a lot of special rooms and tunnels are spawned). It also dictates your chance of doing a critical hit (when so, the total damage output are 50% stronger) Attack: it's self-explanatory. This simply gives how much damage is given at each hit Defence: Also self-explanatory. This simply says how much damage is subtracted from an attack Agility: This stats dictates how fast your character goes. there might be more in the future, but for now, it only affects this Vitality (or Health if you're fancy): This stat simply represents your maximal health. These make CADAV. I don't know if it's clever enough, but it's catchy. (Not as good as SPECIAL, but good enough) For each stat, there is two different type of bonus/malus. These are a unitary bonus (or simply bonuses) and a percentage bonus (or modifiers). Bonuses usually come with pieces of equipment (things like armour and/or weapons), while modifiers are usually applied with capacities as a counterweight. Relics List Here's a small list of relics that are fully functional as of today: Laser Gem The laser gem is a relic resembling an abstract transparent cube with an opaque core. When the player picks up that relic, it gives them the ability to fire penetrating laser beams that deal damage to enemies when the player attacks. When the laser collides with anything but entities (like enemies) it will be reflected. This can be a quite powerful tool to quickly dispatch large amounts of enemies. The beam itself last for about 10 seconds, and only 3 beams can be fired at a time. Here are the modifiers: -10% of Attack +5% of Luck Modern Computing This relic is also abstract, but it's nevertheless more meaningful than the previous relic. Both its name and its model references something really vaporwave. But I'll let you figure it out. When the player grabs this relic, a combo system is activated: for every enemy killed, drops that cames from defeated enemies will linearly increase in number. Of course, being a combo system, if the player is hit then the combo is reset. Here are the modifiers: -5% of Luck -4% of Attack Credit Card The credit card is a credit card. (I didn't know what you expected) With this cool relic, the player can actually purchase anything they want anywhere even if they lack the money for it. Buying an item without the needed money creates a debt in the player's funds. After each 10$ of debt, a random amount of negative modifiers are applied to the player's stats. When the player pays off their debts then these nerfs are progressively removed. Because of this special capacity, no base modifiers are applied when this relic is grabbed. DOUBLE-VISION This relic is rather abstract. It's actually a pair of eyes. When the player grabs this relic, every loot that are consumables (i.e bombs, keys or money) are doubled. Here are the modifiers: -5% of Attack -10% of Luck +5% of Agility Extension Cord This relic is simply a North American electric extension cord. There are two capacities attached to this relic. The first one simply makes the range of your attacks bigger. Its just actually the game resizing your weapons... Nothing special here. The second one is more a nerf than anything else: It slows down your attack speed by half. Here are the modifiers: -25% of Attack -25% of Agility Boxed Copy This relic is a Software box. It's supposed to mimic the Windows 9x boxes. With this relic, on the first successful hit by the player to an enemy, the latter has a chance to get "Boxed". When being "boxed", enemies are transformed into a similar box like the relic itself. However, that box is able to be opened by the player. It then spawns a random amount of consumables. It essentially one hit enemies if your lucky and gives you loot too. This only works on the first hit: subsequential hits won't work. Here are the modifiers: -25% of Attack Atk-booster 2000 This relic is a computer chip, presumably a CPU. It simply increases your attack speed by half. Here are the modifiers: -25% of Attack +10% of Agility Watch Out! This relic is a simple watch. With this one, you gain the ability to backstab other enemies. (not unlike the TF2 backstab) This means that if you hit their back they get one hit. In essence, this works by using the same algorithm that my vision field Here are the modifiers: -40% of Attack -25% of Health +5 of Agility Minor Updates Items that are in malls, along with relics and pieces of equipment, now rests on pedestals. These get removed when the item is picked up or otherwise get removed
There's now a key collectible that can spawn with any type of loot. Picking these up simply increments the player's total amount of keys
The Big Mall (the generic one) now has a chance to spawn a buyable relic in its inventory Fixed many bugs with a whole lot of things Thrown items now properly trigger AIs: they will look at the player that has thrown said projectiles rather than the projectile itself What's next? This week I'm planning to add more capacities and maybe add either Foods or Items in the game. Same goal as before: at least one Food or Item. Just to be clear: Items are like The Binding Of Isaac's Activated Collectibles except that they also change the player's stat and may also add passive capacities while the item is being held. As for food, think of relics, but temporary (a bit like Minecraft's potions). Here comes another big week I guess...

## Unity Weekly Update #8 - Ｌｏｃｋｅｄ　ｄｏｗｎ

I've decided to change the frequency of these updates: most of the times, I just do some minor updates and graphical tweaks here and there. Therefore, if I do these updates weekly, then I'll have a lot more content to write about. So, yeah... Last week, I've been working on adding many different types of rooms in the level. You may or may not know that I use BPS trees to generate a level, and previously, only 5 types of rooms spawned in a level: starting rooms, ending rooms, normal rooms, tunnel rooms and Malls. It was very static and not flexible, so I've changed it to make it more dynamic. Malls Variations First, I've added two different variations for Malls: Blood Malls and Clothes Malls. These were originally planned and already built. Big Malls These are your typical type of Malls. You can find everything here. This is where, for example, you'll find hearts, keys and/or bombs. They were already in the game, but now they're more specialized (or generalized in this case) Blood Malls The Blood Malls specialized in bloody activities. (meaning that you'll mostly find a selection of weapons here) Clothes Malls The Clothes Malls are specialized in clothes, which in our case are actually pieces of equipment the player can have New Rooms Aside from these new type of malls, I've also added 3 new types of rooms. These rooms, however, are guarded by a locked door: the player must use a key to enter. In order to unlock a locked door, the player just needs to touch it. If the player has enough keys, then a key is used and the locked door disappears. There's also an event that triggers that can do things when the player unlocks the door (like revealing hidden models and what not) The Gym The gym is a room resembling some of these outside gyms you can see in some places.  The player can use up to tree gym equipment to get a permanent stats bonus to a randomly selected stat.  The prices of usages of these gym equipment doubles after each use. (i.e. if using one piece is 10$, then after buying it the others will cost 20$ and so on) I've planned that NPC would use non-interactive gym workstations for decoration, but it's not really important as of right now... The Bank The bank is not fully functional at the moment, but it still spawns. The idea is to give the player a way to store money persistently throughout runs. The player can then withdraw money (with a certain transaction fee) from that bank. That means that you can effectively get previously deposited money back when you'll need it the most. The Landfill The landfill gives you the opportunity to gain back previously thrown away pieces of equipment. Basically, the game stores the last three thrown away pieces of equipment. When the rooms spawn, it simply displays you those pieces of equipment. you can then pick them up for free. This, however, comes with a caveat: pieces of equipment that will be switched from a previously thrown away pieces of equipment won't reappear in another landfill. Also, once the landfill despawns, the items in that landfill will be discarded. (Think of it as a last chance opportunity) There aren't any props at the moment, but it's fully functional. Minor Tweaks Aside from that, there are also some minor tweaks: Bombs now damage the player if the latter is within its blast radius; Player jumps are now more precise: letting go of the jump button early makes a smaller jump than if it was held down longer; Ground detection (that was previously done with raycasting) now uses Unity's CharacterController.isGrounded property; When the player is hurt, a knockback is applied to him; The strength of said knockback is actually the total amount of damage the player took. Coins and money items now emit particles to help the player localize those important items;
They're now keys (left) and bombs (right) counters in the HUD;
The key one still needs a specific icon, but it's fully functional; There were many shader optimizations and adjustments: Many shaders were merged together and are now sharing most code; I've also changed the shaders so that we can use GPU instancing for most props, I also now use MaterialPropertyBlock for things like wetness; Also, now the palette texture and its palette index are now global variables, this effectively means that I only need to set these values once and everything else follows; A small "Sales" sign is placed in front of most types of malls. This sign has a random orientation and position each time it's spawned. ;
Props that obstruct a passage are removed from the room; This way no prop can obstruct the room so that the player cannot exit it. Some rooms now spawn ferns instead of palm trees;
Lianas also have different configurations based on which prop spawns. Next week Over the next week, I've planned to integrate the first relic. Relics are items that give the player capacities and stats boosts. It's common to have something similar in most roguelite and roguelike games. That type of thing needs to have a good abstraction in order to work: there are many different types of capacities that affect the player in radically different ways. There's a lot of work ahead. But I'm confident it'll be easy. Just need to get in the groove.

## Unity Daily Update #7 - Ａｎｏｔｈｅｒ　ｐｌａｎｅ　ｏｆ　ｂｅｉｎｇ

During the past days, lots of shaders were updated and other visual things did too. Firstly, I've added lights effects when the crystals get shattered. There's also a burst of particle emanating from the broken crystal on impact. Also, enemies now leave a ragdoll corpse behind when they die. I love some of the poses those ragdolls make. On another note, I've toyed around with corpse removal and got captivated by the shrinking effect it created. It can sometimes be off-putting, but I'm still captivated. I've also added a nice VHS-like effect from layering two VHS shader together; namely "more AVdistortion" and "VHS pause effect". I've already ported the former and it's already active and the latter was just a matter of porting GLSL shaders to HLSL. No biggie. I did change the code a bit to make the white noises move through time. And there's nothing like trigonometry to help us with that fixed4 frag (v2f i) : SV_Target { fixed4 col = fixed4(0, 0, 0, 0); // get position to sample fixed2 samplePosition = i.vertex.xy / _ScreenParams.xy; float whiteNoise = 9999.0; // Jitter each line left and right samplePosition.x = samplePosition.x + (((rand(float2(_UnscaledTime, i.vertex.y))-0.5)/64.0) * _EffectStrength ); // Jitter the whole picture up and down samplePosition.y = samplePosition.y + (((rand(float2(_UnscaledTime, _UnscaledTime))-0.5)/32.0) * _EffectStrength ); // Slightly add color noise to each line col += (fixed4(-0.5, -0.5, -0.5 , -0.5)+fixed4(rand(float2(i.vertex.y,_UnscaledTime)),rand(float2(i.vertex.y,_UnscaledTime+1.0)),rand(float2(i.vertex.y,_UnscaledTime+2.0)),0))*0.1; // Either sample the texture, or just make the pixel white (to get the staticy-bit at the bottom) whiteNoise = rand(float2(floor(samplePosition.y*80.0),floor(samplePosition.x*50.0))+float2(_UnscaledTime,0)); float t = sin(_UnscaledTime / 2); if (whiteNoise > 11.5-30.0*(samplePosition.y + t) || whiteNoise < 1.5-5.0*(samplePosition.y + t) ) { // Sample the texture. col = lerp(tex2D(_MainTex ,samplePosition) , col + tex2D(_MainTex ,samplePosition), _EffectStrength); } else { // Use white. (I'm adding here so the color noise still applies) col = lerp(tex2D(_MainTex ,samplePosition), fixed4(1, 1, 1,1), _EffectStrength); } return col; } It's nice to have HLSL code, but a video is better:

## Unity Daily Update #5 - Ｅｔｅｒｎａｌ　Ｅｔｈｅｒｎｅｔ

Today, I've worked on level exits. When the player arrived at the last room before, nothing awaited him. He was stuck for eternity on the same level. Kinda boring, actually... But today this is no more! Now a big Ethernet port awaits the player at the end of the level. He just needs to jump in it to clear the level.  I've had to create two new shaders: one that can fade the screen to black according to the player's y coordinates. I've also needed to modify my main shader to add a new parameter that can create a gradient from the usual colours to pitch black. This way, I can simulate a bottomless pit.

## Unity Daily Update #4 - Crystal updates

Today, I've fixed some bugs with the crystal throwing algorithm. Basically, crystals will be used by the player to get to those alternative paths I've mentioned in my BPS tree entry. There'll be at least 3 type of crystals : Fire, Water and Life. Each will be thrown to eliminate obstacles at the entry point of each alternatives paths. I've also planned them to be persistent throughout runs. This means that the amount of crystals are linked to a save file rather than a run. So if the player didn't used their crystal during the run, then they'll have the opportunity to use them in another one. As you can see, each type of crystal has a particular particle effect attached to them. I've tried to simulate how each type of elements would react. So the fire crystal particles behaves like flames, life one like fireflies and water one like drops of water. I still have to give them a distinctive shape... For now, I've used the default particle sprite provided with Unity. Also, after a crystal hit something, it'll generate other type of particles. These particle will move accordingly to the impact force. So, to recap, I've been working on particles for the past days... Kinda slow, but I think it's worth it...

## Algorithm The power of the vector cross product, or how to make a realistic vision field

In the previous iteration of our game, we decided to use an actual cone as a way to make an AI "see". This implementation was hazardous, and it quickly became one of the hardest things to implement. We eventually were able to code it all, but the results were really static and not really realistic. Because of the reboot, I took the time to actually identify what constraint one's vision has. The visual field First of all, a cone isn't really the best in therm of collision checking. It required a special collider and could have potentially been a bottleneck in the future when multiple AI would roam the level. In actuality, the visual field can be represented as a 3D piece of a sphere (or more like a sector of a sphere). So we're gonna need to use a sphere in the new version. It's cleaner and more efficient that way. Here's how I've done it: foreach (Collider otherCollider in Physics.OverlapSphere(m_head.transform.position, m_visionDistance / 2, ~LayerMask.GetMask("Entity", "Ignore Raycast"), QueryTriggerInteraction.Ignore)) { // Do your things here } Pretty simple, really... Afterwards (not unlike our previous endeavour), we can just do a simple ray cast to see if the AI's vision is obstructed: // Do a raycast RaycastHit hit; if (Physics.Raycast(m_head.position, (otherPosition - m_head.position).normalized, out hit, m_visionDistance, ~LayerMask.GetMask("Entity", "Ignore Raycast"), QueryTriggerInteraction.Ignore) && hit.collider == otherCollider) { // We can see the other without any obstacles } But with that came another problem: if we use a sphere as a visual field, then the AI can surely see behind his back. Enters the cross product. Vectorial cross product The cross product is a vectorial operation that is quite useful. Here's the actual operation that takes place: $$\mathbf{c} = \mathbf{a} \times \mathbf{b} = ( \mathbf{a}_{y}\mathbf{b}_{z} -\mathbf{a}_{z}\mathbf{b}_{y}, \mathbf{a}_{z}\mathbf{b}_{x} -\mathbf{a}_{x}\mathbf{b}_{z}, \mathbf{a}_{x}\mathbf{b}_{y} -\mathbf{a}_{y}\mathbf{b}_{x} )$$ This actually makes a third vector. This third vector is said to be "orthogonal" to the two others. This is a visual representation of that vector: As you can see, this is pretty cool. It looks like the translation gizmo of many 3D editors. But this operation is more useful than creating 3D gizmos. It can actually help us in our objective. Interesting Properties One of the most interesting properties of the cross product is actually its magnitude. Depending on the angle between our two a and b vectors, the magnitude of the resulting vector changes. Here's a nice visualization of it: As you can see, this property can be useful for many things... Including determining the position of a third vector compared to two other vectors. But, however, there's a catch: the order of our a and b vector matters. We need to make sure that we don't make a mistake, as this can easily induce many bugs in our code. The funnel algorithm In one of my articles, I've actually explained how pathfinding kinda works. I've said that the navigational mesh algorithm is actually an amalgamation of different algorithms.  One of these algorithms is the Funnel algorithm, with which we actually do the string pulling. When the Funnel algorithm is launched, we basically do a variation of the cross product operation in order to find if a certain point lay inside a given triangle described by a left and right apexes. This is particularly useful, as we can actually apply a nice string pulling on the identified path. Here's the actual code: public static float FunnelCross2D(Vector3 tip, Vector3 vertexA, Vector3 vertexB) { return (vertexB.x - tip.x) * (vertexA.z - tip.z) - (vertexA.x - tip.x) * (vertexB.z - tip.z); } With this function, we get a float. The float in question (or more particularly its sign) can indicate whether the tip is to the left or to the right of the line described by vertexA and vertexB. (As long as the order of those vectors are counterclockwise, otherwise, the sign is inverted) Application Now, with that FunelCross2D function, we can actually attack our problem head-on. With the function, we can essentially tell whether or not a given point is behind or in front of an AI. Here's how I've managed to do it: if ( FunnelCross2D((otherTransform.position - m_head.position).normalized, m_head.right, -m_head.right) > 0 ) { // otherTransform is in front of us } Because this is Unity, we have access to directional vectors for each Transform objects. This is useful because we can then plug these vectors into our FunnelCross2D function and voilà: we now have a way to tell if another entity is behind or in front of our AI. But wait, there's more! Limit the visual angle Most people are aware that our visual field has a limited viewing angle. It happens that, for humans, the viewing angle is about 114°. The problem is that, right now, our AI viewing angle is actually 180°. Not really realistic if you ask me. Thankfully, we have our trusty FunnelCross2D function to help with that. Let's take another look at the nice cross product animation from before: If you noticed, the magnitude is actually cyclic in its property: when the angle between a and b is 90°, then the magnitude of the resulting vector of the cross product is literally 1. The closet the angle gets to 180° or 0°, the closest our magnitude get to 0. This means that for a given magnitude (except for 1), there are actually 2 possible a and b vector configurations. So, we can then try to find the actual magnitude of the cross given a certain angle. Afterwards, we can store the result in memory. m_visionCrossLimit = FunnelCross2D(new Vector3(Mathf.Cos((Mathf.PI / 2) - (m_visionAngle / 2)), 0, Mathf.Sin((Mathf.PI / 2) - (m_visionAngle / 2))).normalized, m_head.right, -m_head.right); Now we can just go back to our if and change some things: if ( FunnelCross2D((otherTransform.position - m_head.position).normalized, m_head.right, -m_head.right) > m_visionCrossLimit ) { // otherTransform is in our visual field } Then we did it! the AI only reacts to enemies in their visual field. Conclusion In conclusion, you can see how I've managed to simulate a 3D visual field using the trustworthy cross product. But the fun doesn't end there! We can apply this to many different situations. For example, I've implemented the same thing but in order to limit neck rotations. it's just like previously, but with another variable and some other fancy codes and what not... The cross product is indeed a valuable tool in the game developer's toolset. No doubt about it.

## Unity Daily Update #3 - ＡＥＳＴＨＥＴＩＣ＋＋

Today was kind of a slow day: I had many things to do, so development was kind of light... Nevertheless, I've still managed to do something... I've added a way to highlight items through emission (not unlike how we did it previously) and make enemies blink when they get hurt. It wasn't really hard: because this is Unity, the surface shader got us covered. It was just one simple line of code.  #ifdef IS_EMISSIVE o.Emission = lerp(fixed3(0, 0, 0), _EmissionColor.rgb, _EmissionRatio); #endif

## 3D Vaporwave treasure models

Roguelites are synonymous with loot and treasure chests. However, my game is vaporwave, so traditional treasure chests are out of the question. This is what I came up with: You may get the references if you know your Windows well enough... 😉

## Unity Daily update #1 - wet-dry shader variations

I've decided to make a daily update blog to have a development metric. So here goes... Today, I've modified the shader I've previously made so that it can take a "wetness" parameter. Basically, in my palette, the first 4 columns represents a pair of colors, where as the first ones are dry colors and every other ones are wet colors. I just do a clever lerp between those two consecutive colors according to the given wetness parameter. Here's an example:     Here, you can see that the leaves of that palm tree is significantly more yellow that usual Here it's way more green. The way I did it was quite simple: I've just added a _Wetness parameter to my Unity shader. I then just do a simple lerp like so: /* In the shader's property block */ _Wetness ("Wetness", Range(0,1)) = 0 [Toggle(IS_VEGETATION)] _isVegetation ("Is Vegetation?", Float) = 0 /* In the SubShader body */ void surf (Input IN, inout SurfaceOutputStandard o) { #ifdef IS_VEGETATION fixed4 wetColor; float uv_x = IN.uv_MainTex.x; // A pixel is deemed to represent something alive if its U coordinate is included in specific ranges (128 is the width of my texture) bool isVegetationUV = ((uv_x >= 0.0 && uv_x <= (1.0 / float(128)) ) || (uv_x >= (2.0 / float(128)) && uv_x <= (3.0 / float(128)) )); if (isVegetationUV) { fixed2 wetUV = IN.uv_MainTex; // To get the other color, we just shift by one pixel. that's all // The _PaletteIndex parameter represents the current levels' palette index. (In other words, it changes level by levels) // There are 8 colors per palette. that's where that "8" comes from... wetUV.x = ((wetUV.x + (1.0/float(128))) + 8.0 * float(_PaletteIndex) / float(128)); wetColor = tex2D(_MainTex, wetUV); } #endif // This is part of my original palette shader IN.uv_MainTex.x = IN.uv_MainTex.x + 8.0 * float(_PaletteIndex) / float(128); fixed4 c = tex2D(_MainTex, IN.uv_MainTex); #ifdef IS_VEGETATION if (isVegetationUV){ c = lerp(c, wetColor, _Wetness); } #endif o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = _Alpha; } Then it's just a matter of changing that parameter in a script like so: GameObject palm = PropFactory.instance.CreatePalmTree(Vector3.zero, Quaternion.Euler(0, Random.Range(0, 360), 0), transform).gameObject; MeshRenderer renderer = palm.GetComponentInChildren<MeshRenderer>(); for (int i = 0, length = renderer.materials.Length; i < length; ++i) { renderer.materials[i].SetFloat("_Wetness", m_wetness); } I've also changed the lianas's colors, but because I was too lazy to generate the UV maps of these geometries, I've just gave them a standard material and just change the main color... And I made a Unity script that takes care of that for me... // AtlasPaletteTints is an Enum, and atlasPaletteTint is a value of that enum // m_wetness is a float that represent the _Wetness parameter // m_isVegetation is a bool that indicates whether or not the mesh is considered a vegetation (this script is generic after all) Color col = AtlasPaletteController.instance.GetColorByPalette(atlasPaletteTint); if (m_isVegetation) { // Basically, we check whether or not a color can qualify for a lerp if ((atlasPaletteTint >= AtlasPaletteTints.DRY_DETAIL_PLUS_TWO && atlasPaletteTint <= AtlasPaletteTints.DRY_DETAIL_MINUS_TWO) || (atlasPaletteTint >= AtlasPaletteTints.DRY_VEGETATION_PLUS_TWO && atlasPaletteTint <= AtlasPaletteTints.DRY_VEGETATION_MINUS_TWO)) { // Each colors have 5 tints; that where the "+ 5" is coming from col = Color.Lerp(col, AtlasPaletteController.instance.GetColorByPalette(atlasPaletteTint + 5), m_wetness); } } GetComponent<Renderer>().material.color = col;

## Unity ｌｅｔｓ　ｇｏ　ｔｏ　ｔｈｅ　ｍａｌｌ (Video)

After really thinking about it, the method I've used to play MP3 wasn't the most flexible, so after re-working it out, I've decided to stream the music directly in a Unity AudioClip. This way, the audio goes through an audio mixer form which I can easily apply filter to... I was also able to cross-fade between two music track. I've also put the sound loading onto another thread, making the audio loading run in the background rather than clogging up the main thread. Also, it's easier to use the 【 ＶａｐｏｒＭａｋｅｒ】with the Unity Audio system... I can even add more wacky filters over it to make those songs more ＶＡＰＯＲＷＡＶＥ than ever.

## Algorithm BSP trees, or creating a randomly generated level

Hi guys, I have a bad news and a good news. The bad news is that the game i was currently working on is kinda canceled. But, however, this is not the end of this endeavor. I've chosen to continue the development on my own and with Unity.  Turns out that the previous engine we tried was missing a lot of key components that was needed for our project.  Paired this with other intrapersonal problems and our team was dissolved. I, however, still believe in the idea. The feedback was somewhat positive, and I'm sure that if I give my 100% on this that i might get a chance to make you believe in it too.   So hang on tight, because the ride is far from being over.