Jump to content
  • Advertisement
  • entries
    9
  • comments
    18
  • views
    17167

About this blog

The Mechanical Heart

Entries in this blog

 

Unity Editor Data Entry 2.0

Unity Data Entry
So, unity has a problem. Well, ok lots of problems, but I want to talk about a specific one. Data entry and how things can quickly get out of hand. For those who are unaware, unity allows you to edit serialize data through the editor using an 'inspector window'. My script has 3 variables that can be edited with types enum, int and float. (unity offers many other data types which can be edited through the inspector). Entering data through the inspector is fine for simple objects/scripts. However, once a object/scripts becomes more complicated the default data entry becomes a burden. Specifically when you have a variable which will determine if another variable is used or not. A good example of this is you may have a projectile, this projectile could behave in different ways. It could be a homing projectile, it could be a bullet, it could be anything. If the projectile is homing, it will use additional parameters to a standard projectile, if it is a bullet it would use different parameters again. The solution to this problem, as stated a lot of places on the internet is to create a custom drawer for the (projectile) script. However, in practice this is impractical. Scripts where I needed the above behaviour required writing 200 lines, just so I could show/hide some variables in the inspector! furthermore this 'solution' just isn't scalable, as you would have to write custom draw code for each script!. My solution to this involves using attributes to define when a variable is shown or not (and to handle the drawing) (in real time!) Which changes the above image to:
So, What do we need to do?
Create a generic attribute which any variable can use
Use reflection to get another variable
Check to see if that variable is of a particular value

The most basic condition (to decide if one variable should be shown or not) is a Boolean.if Varible A is True Show Varible Belse Don't show Varible B

First we have to declare our fields, this is pretty standard, however on variable B we will have to declare it with our attribute (conditional)public bool a;[Conditional("a", true)]public int b;
as you can see, the attribute takes in two parameters; "a" and True. The first parameter is the name of the parameter we want to check. The second parameter is the value the first parameter needs to be to make variable b show. These are both stored with in the Attribute.
We need to create a drawer, which will draw the variable in editor, for our attribute. We do this by doing:[CustomPropertyDrawer(typeof(ConditionalAttribute))]public class ConditionalDrawer : PropertyDrawer{ public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { .... }}
The OnGUI method will handle drawing the variable in editor. As you can see, it has a SerializedProperty parameter, this is our variable "b". We need to do some reflection magic on that parameter to get variable "a" and check it's value. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { ConditionalAttribute conAtr = attribute as ConditionalAttribute; string path = GetPath(property); string conditionname = path + conAtr.ConditionVaribleName; ConditionalProperty = property.serializedObject.FindProperty(conditionname);} private string GetPath(SerializedProperty property) { string path = property.propertyPath; int index = path.LastIndexOf("."); return path.Substring(0, index + 1); }
This code gets the condition variable ("bool a") and stores it in ConditionalProperty. The GetPath Method is needed as the variables could be nested in an object.
?
?
Next we need to check the value of ConditionalProperty, against the value we passed (and stored) into the attribute. if (ConditionalProperty.propertyType == SerializedPropertyType.Boolean) { conAtr.ShouldShow = ConditionalProperty.boolValue == conAtr.CheckValue; }
as the same instance of the drawer is used to draw all the variables with our attribute, we can not store anything with in the drawer. we have to store everything in the attribute.
Next, still within the OnGUI method we need to draw (or not draw) the variable ("int b").if (conAtr.ShouldBeShown) EditorGUI.PropertyField(position, property, label, false);
We also need to alter the height of the variable being drawn otherwise there will be a blank space. Luckily we can just do: public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { ConditionalAttribute conAtr= attribute as ConditionalAttribute; if (!conAtr.ShouldBeShown) return 0.0f; return EditorGUI.GetPropertyHeight(property, label, true); }
within the drawer class.
Great!! we now have a variable which is shown/not shown depending on another Boolean variable. But what if we don't want to use a Boolean, what if we want to make it dependant on another type, what if it has to be greater than X or less than X. What if we want it conditional to multiple things.
Don't fear, I have thought of that! I have another constructor in the attribute:public enum OperatorEnum { Equals, NotEqualTo, GreaterThan, LessThan, EqualsOrGreaterThan, EqualsOrLessThan } public enum LogicEnum { AND, OR } //LHS, is the varible name to check which are got through reflection //Opperator, is the operator to use for the check //RHS, is the value to check against //BetweenElements, and/or to use between the last element and this element public ConditionalAttribute(string[] LHS, int[] Operator, object[] RHS, int[] BetweenElements) { int maxsize = LHS.Length; m_LHSVaribleNames = new string[maxsize]; m_Operator = new OperatorEnum[maxsize]; m_RHSValues = new object[maxsize]; m_BetweenElementsLogic = new LogicEnum[maxsize - 1]; m_LHSVaribleNames = LHS; for (int i = 0; i = (OperatorEnum)Operator; } else m_Operator = (int)OperatorEnum.Equals;//Set it to == if no value was given } for (int i = 0; i = RHS; } else m_RHSValues = RHS[RHS.Length - 1];//Set it to the last value if no value was given } for (int i = 0; i = (LogicEnum)BetweenElements; } else m_BetweenElementsLogic = LogicEnum.AND;//Set it to && if no value was given } }
unfortunately, there are only certain types which can be passed into attributes. I would have liked to do all this using a lambda to decide all this, but alas that was not possible so I had to parse the values to make the correct statement. Also, enum values can not be passed through so they need to be cast to an int.
So now if we want a new variable ("c") to be shown when:if a == true && b > 5 showelse don't show
the declaration would look like: public bool a; [Conditional("a", true)] public int b; [Conditional(new string[] { "a","b"}, new int[] { (int)ConditionalAttribute.OperatorEnum.Equals, (int)ConditionalAttribute.OperatorEnum.GreaterThan }, new object[] { true, 5}, new int[] { (int)ConditionalAttribute.LogicEnum.AND} )] public float c;
yikes that's a big constructor :(
One last thing was that because I don't know the type of the variable who's name is passed in (the condition variable) - I only know the type of the variable being drawn, I had to use(IComparable)LHS).CompareTo(RHS) == 0
for the check to know if the variable should be shown or not.
Using this attribute allows the data entry for unity to be much easier, as now you can edit fields that are relative to the options you have already chosen! You can now write, simple/complex statements and control the visibility of variables in the editor without the need of creating custom drawer's for each script. I am really happy with how this has turned out, it is really flexible and really generic. Hopefully someone else will find it as useful as I do :) Until next time, dsm full code:using UnityEngine;using System.Collections;using UnityEditor;using System;public class ConditionalAttribute : PropertyAttribute{ public enum OperatorEnum { Equals, NotEqualTo, GreaterThan, LessThan, EqualsOrGreaterThan, EqualsOrLessThan } public enum LogicEnum { AND, OR } protected string[] m_LHSVaribleNames; protected OperatorEnum[] m_Operator; protected object[] m_RHSValues; protected LogicEnum[] m_BetweenElementsLogic; protected bool m_ShouldBeShown = true; public bool ShouldBeShown { get { return m_ShouldBeShown; } set { m_ShouldBeShown = value; } } public string[] LHSVaribleNames { get { return m_LHSVaribleNames; } } public OperatorEnum[] Operator { get { return m_Operator; } } public object[] RHSValues { get { return m_RHSValues; } } public LogicEnum[] BetweenElementsLogic { get { return m_BetweenElementsLogic; } } //LHS, is the varible name to check which are got through reflection //Opperator, is the operator to use for the check //RHS, is the value to check against //BetweenElements, and/or to use between the last element and this element public ConditionalAttribute(string[] LHS, int[] Operator, object[] RHS, int[] BetweenElements) { int maxsize = LHS.Length; m_LHSVaribleNames = new string[maxsize]; m_Operator = new OperatorEnum[maxsize]; m_RHSValues = new object[maxsize]; m_BetweenElementsLogic = new LogicEnum[maxsize - 1]; m_LHSVaribleNames = LHS; for (int i = 0; i = (OperatorEnum)Operator; } else m_Operator = (int)OperatorEnum.Equals;//Set it to == if no value was given } for (int i = 0; i = RHS; } else m_RHSValues = RHS[RHS.Length - 1];//Set it to the last value if no value was given } for (int i = 0; i = (LogicEnum)BetweenElements; } else m_BetweenElementsLogic = LogicEnum.AND;//Set it to && if no value was given } } public ConditionalAttribute(string LHSVaribleName, object RHSValue) { m_LHSVaribleNames = new string[] { LHSVaribleName }; m_RHSValues = new object[] { RHSValue }; m_Operator = new OperatorEnum[] { OperatorEnum.Equals }; } public ConditionalAttribute() { }}///////Conditional//Decides if a varible should be shown in the inspector depending on another (boolean) varible[CustomPropertyDrawer(typeof(ConditionalAttribute))]public class ConditionalDrawer : PropertyDrawer{ public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { if (!bute.ShouldBeShown) return 0.0f; return EditorGUI.GetPropertyHeight(property, label, true); } SerializedProperty ConditionalProperty; public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { bute.ShouldBeShown = ShouldShow(property); if (bute.ShouldBeShown) EditorGUI.PropertyField(position, property, label, false); } private string GetPath(SerializedProperty property) { string path = property.propertyPath; int index = path.LastIndexOf("."); return path.Substring(0, index + 1); } protected virtual ConditionalAttribute bute { get { return (ConditionalAttribute)attribute; } } protected bool ShouldShow(SerializedProperty property) { string path = GetPath(property); bool previous = false; for (int i = 0; i ; ConditionalProperty = property.serializedObject.FindProperty(conditionname); bool test = false; object lhsValue; if (ConditionalProperty.propertyType == SerializedPropertyType.Integer) { lhsValue = ConditionalProperty.intValue; } else if (ConditionalProperty.propertyType == SerializedPropertyType.Float) { lhsValue = ConditionalProperty.floatValue; } else if (ConditionalProperty.propertyType == SerializedPropertyType.Boolean) { lhsValue = ConditionalProperty.boolValue; } else if (ConditionalProperty.propertyType == SerializedPropertyType.Enum) { lhsValue = ConditionalProperty.enumNames[ConditionalProperty.enumValueIndex]; } else throw new Exception("Type needs implementing"); test = Check(lhsValue, bute.Operator, bute.RHSValues); if (bute.BetweenElementsLogic == null) { return test; } if (i != 0 && test && bute.BetweenElementsLogic[i - 1] == (int)ConditionalAttribute.LogicEnum.AND) { if (!previous) { test = false; } } if (test && i == ConditionalAttribute.LogicEnum.OR) { return true; } previous = test; } return previous; } protected bool Check(object LHS, ConditionalAttribute.OperatorEnum op, object RHS) { if (!(LHS is IComparable) || !(RHS is IComparable)) throw new Exception("Check using non basic type"); switch (op) { case ConditionalAttribute.OperatorEnum.Equals: return ((IComparable)LHS).CompareTo(RHS) == 0; case ConditionalAttribute.OperatorEnum.NotEqualTo: return ((IComparable)LHS).CompareTo(RHS) != 0; case ConditionalAttribute.OperatorEnum.EqualsOrGreaterThan: return ((IComparable)LHS).CompareTo(RHS) >= 0; case ConditionalAttribute.OperatorEnum.EqualsOrLessThan: return ((IComparable)LHS).CompareTo(RHS) 0; case ConditionalAttribute.OperatorEnum.LessThan: return ((IComparable)LHS).CompareTo(RHS)

dsm1891

dsm1891

 

The Mechanical Heart: Room Generation

The Mechanical Heart
Development Blog



Sorry for the laps in journals lately I have recently (by recently I mean 4 months ago) acquired a job as a Mobile game Developer. In this Journal I will discuss the room generation system in The Mechanical Heart. We have already discussed map generation in the game, which can be found Here.

Goal

We want to be able to randomly generate rooms. We don't know the minimum or maximum size the room can be, so the algorithm needs to be flexible and cater for many different possibilities.

Each room will have walls, floors and ceilings. They will also have entrances and exits to other rooms. The map will contain an undetermined amount of rooms.


Prologue
I was stuck for a while on how to randomly generate rooms, most games which use a random room generation system are put together like a jigsaw. That is, there are lots of different pre made pieces and they are put together to generate a room. I did not want this, in the true style of random random random, I wanted it to be fully randomly generated.

After searching around on the internet for a bit, all it took was one word. Shape. I could randomly generate a shape and that shape would determine the...shape, of the room.


*Please note: The following images have been aligned in such away that they cut of some of the tiles ( one and a half tiles from the top and the right), this was just for formatting reasons*

Creating the shape

Creating a random shape shape isn't to hard, we just need to generate random points and link them up. However, We do not wish to make a Complex Polygon. To prevent this, we have 4 set areas for our points to spawn in. and make sure a point is always proceeding of the next point.



Here we can see 4 different areas that the points can spawn in, one for the ceiling two for the walls and one for the floor.

We need to keep in mind:
(with 0,0 being top left)
When generating Ceiling points -Each new point's X needs to be greater than the previous points X
When generating Right Wall points -Each new point's Y needs to be greater than the previous points Y
When generating Floor points -Each new point's X needs to be Less than the previous points X
When generating Left Wall points -Each new point's Y needs to be Less than the previous points Y

We also need to keep in mind that the first point, and the last point is the same point.



Outlining the shape

Great! so now we have a random shape which is what our room will look like, the next step is filling any tiles outside of the shape with a tile. To do this we can use an In/out algorithm. We cast a ray from each tile position and counts the amount of times the ray intercepts the rooms shape. If the number of interceptions is even (or 0), the tile must be outside the shape. If the number of interceptions is odd, it must be inside the shape.





Here is an image of the tests. The blue line intercepts the shape twice, and green line intercepts once.

because I can ensure that there will always be an outline of tiles to the room's shape, I can combine this check with a flood fill algorithm so we do not have to check ever tile space in the room.



Setting Room boundaries
Now we have a simple room shape we can fill out the parameter of the shape with more details, setting the wall tiles to walls, and floor to loor tiles ect.

To do this we need to traverse each edge of the shape. Because we know the room shape is wound clockwise, we can say that when we are traversing the edge with a positive X this will be the ceiling, when we traverse the edge with a negative X it will be the floor.

When we traverse the edge with a positive Y this will be the Right wall, and When we traverse the edge with a negative Y this will be the Left wall.

Combining these will allow us to deal with slants.

There are some other checks that I do, however this will depend on the tile set.




Corners

The Next step is to set the corner tiles. Its important we do this last as it requires to check the surrounding tiles, and depending on their configuration it will change accordingly. if we did it in the previous step, a tile may not have been set yet, thus it will chose the wrong tile.

Here is the check we need to perform, this is the worst case scenario, often we don't need to check all 8 Tiles. For example, if we know it is the floor (nothing above the tile) we can stop after the first check.









Exits
This is the final step is to have entrances and exits, All that needs doing is to place points of the room shape outside of the room boundaries, then run the generation. The final result should look something like this:





Why not just flood fill and check each tile?

My dear friend TheChubu said I was overcomplicating this, and suggested that I just check the surroundings of each tile and choose the tile accordingly. This would have been fine if I knew that I wanted only small rooms, but I wanted to create a versatile system which would work with many rooms. I also wanted to be able to put nest the room shapes, that is have a shape in side the room shape, to give a solid block of tiles inside the shape.

This system works very well and is very flexible and is capable of working with many games.

Here is the final image of the room.





I am very happy with this algorithm, it sets out to achieve every thing I wanted it too

Until next time!
Dsm

dsm1891

dsm1891

 

The Mechanical Heart: Art Update

The Mechanical Heart
Development Blog


This Week I would like to share some of the art and the process we have gone through from the concept.

Enemies

Here are some concepts for the enemies in The Mechanical Heart. The Brief was pretty simple(ish) old, worn out, killer robots that are slightly amphomorphic.


This Robot was a crab like robot which spat gears (A.K.A bullets) out of its side (head?).


This is my favourite piece of concept art, clearly the meanest robot of the bunch. His menacing melee attack would punish all that come close.


And Finally a ranger robot, armed with a crossbow firing bolts towards its enemies. Its wheel 'legs' would allow it to chase its prey quickly.

Here is a picture with all 3, makes a nice Desktop background if anybody is looking for one.





Here are the latest rendition of the enemies, they still need a lot of work in some places, but they are getting there.










Ingame

Unfortunately there isn't much concept art for the gameplay. But it is set in an old slightly derelict factory, that is owned by a crazed inventor.











This is some semi-concept art of the outside environment (floor tiles are right, background and content isnt).





This is inside of the factory, I am really pleased how this turned out. Need to weight the background tiles, so there are more blank ones. But never the less me gusta!


And the final peace of art is from the menu screen (also a nice wall paper):








UI Concept

I have never really like bars and meters to display information to the player. This is why I decided to have a representation of the gun, with the reloading animation (hammer cocking back), once the hammer is cocked back the gun is ready to fire. I would still like to play around with ideas of representing health instead of having the healthmeter in the corner.




Well, That's about all the art I have, but in conclusion I would say it is looking good.

Until next time!
DSM

dsm1891

dsm1891

 

The Mechanical Heart: Good Vibrations

The Mechanical Heart
Development Blog


One of the biggest problems with creating 2D games is adding weight to the players actions, if you are not careful the controls can feel 'floaty' or light. Good animations can really help combat having your main character float around the screen, but another good way, which I will discuss today, is screen shake. Screen shake allows the player to really feel different actions, such as taking damage or recoil of a gun. These effects can reach their full potential when paired with vibration on a controller.

Goal
Create a algorithm that adds weight to the controls by the means of violently moving the camera. The camera movement should be random, but always return to the original position the camera was in.


Step 1 - Screen Shake
The First stage of making your screen shake 'feel' good is the camera being positioned along a path and returning to the same point as it left off. At first I thought it would be a good idea to add a 'shake frequency' variable so I could tell the camera only to X amount of times per second, however after implementing this, and playing around with the values, I decided to remove it. In my opinion you should try and move the camera as much as you can per second I.E. ever frame. Ok, so lets concentrate on a simple screen shake:CameraUpdate(){If the screen should be shakingincCameraPositionrandom amount(from 1 to MAX_AMOUNT) - HALF_MAX AMOUNT) in x directionincCameraPosition (random amount(from 1 to MAX_AMOUNT) - HALF_MAX AMOUNT) in the y direction}
This will simply move the camera around the origin. However there is a reason we dont rely on bogo sort to sort a list, the method above technically will return to origin if we leave it for long enough, the likely hood of that happening is slim. Instead if we add each movement to a list (vector in this case), then when the screenshake is half way through its time we go back through the list and move in the opposite direction.std::vector direction;CameraUpdate(){If the shake time 0 ){incCameraPosition(-direction[0]); // move in the opposite directiondirection.erase(direction.begin());//remove that direction from the vector}}
I first experimented with starting from the end of the list (the last shake of the camera) and working my way backwards to the start. However it turns out humans are good at pattern recognition and it didn't give the random feel I wanted. So starting at the front, moving in the opposite direction then deleting and carrying on to the next one, works best.


Step 2 - Polish

I found that most 2D games stop with the code above, but I wanted to add another layer of polish to the screen shake. I wanted to add a directional bias to the screen shake. This will enhance the feeling of recoil, or taking damage. For example, if the player fires a gun to the right, the screen should shake to the left and vice versa.

My first thought of doing this was that the recoil direction should be accumulative, that is the screen shake should only move in the direction of the recoil. However, I did want the other axis component to stay the same (for recoil to the left/right, the screen would still shake up and down).direction.push_back(XMFLOAT3(((rand()%maxRumble)+1)-ancor+rumbledir.x,((rand()%maxRumble)+1)-ancor+rumbledir.y,0));// Where ancor is half of maxRumble+1// And rumbledir is the direction the screen shake should shake i.e.:// -1//-1 0 -1// -1
This did not have the feel I wanted for the recoil as you can see below:


[size=2]Graphics are not representative of final graphics in game
[size=2]Artifacting is caused by recording device

[size=2]So I decided to revisit the drawing board. I decided on adding a slight bias of which direction the recoil.





[size=2] [size=2][size=2]Graphics are not representative of final graphics in game
[size=2] [size=2][size=2]Artifacting is caused by recording device

[size=2]Unfortunately the recoding device skipped about half of the screen shake frames, so it isn't immediately obvious that the screen shake isn't accumulative in the direction of the recoil. It is a lot more noticeable in game, and if I can reproduce the results in .gif form I will update this blog.

[size=2]Here is an image illustrating the recoil, each and every different frame is coloured.




[size=2]


[size=2]Timing and shake amount

[size=2]These will vary for your game, but for The Mechanical Heart I played around with the values a lot, I found that for firing a weapon, the total amount of time the screen should shake for is about 0.2 seconds. Although, if you wanted to create a feeling of a more powerful weapon and greater recoil I would suggest going up to ~0.5 seconds.

[size=2]The amount to move the camera each frame is subjective for your game, for The Mechanical Heart, who's graphics are currently 64px x 64px tiles, I found moving the camera from -5 to +5 pixels per frame.


Conclusion
I am really happy with the screen shake, it really adds weight to what would have been 'floaty' or light input. I am happy with the result, so it is unlikely I will revisit this, but if I do I will most assuredly make a blog post about it.
You may have noticed I was increasing the camera position in 3 axis (x,y and z) but I always kept the Z axis at 0 - therefore not increasing it at all. The reason I kept it there was for a place holder, I may decide to move the camera on the Z axis (zooming in and out) when shaking the screen. I think this would give a nice effect, but I haven't had time to play with it.

[size=2]Until next time,
[size=2]Dsm

dsm1891

dsm1891

 

The Mechanical Heart: Solo+ Development

The Mechanical Heart
Development Blog

I had planned on writing about screen shake this week, but unfortunately the screen shake I came up with didn't look as good as I wanted. So (hopefully) I will get time to finish it next week. So instead I would like to talk about a development style (/ team size) that I have adapted for The Mechanical Heart which is Solo+ Development.

What is Solo+ Development?

I am pretty sure I am not the person who coined the term, I think I may have first heard it at Develop 2014, after extensive googling I couldn't find a mention on it on the internet so I might have just coined it. Solo+ development (at least my definition of it) is one person creating a product, in this case a game, and areas of that product is outsourced to freelancers. The company is owned by the person creating the product.

The Pros
One of the perks to solo+ is the fact you have no partners and/or employees to look after. Although I agree that you need to 'look after' your freelancers, this is often easier than having employees. This means your company will be easier to manage.


Pure Solo Development is risky, ever tried making a cup of tea whilst juggling knives and riding a unicycle? Having to create the sound and art assets along with the code and not to mention game design is a lot to have on your plate. I am not saying it is impossible, but this is where time management is critical. I have serious respect for any pure solo developer!

Work when you want. If you are a procrastinator you might want to consider this as a negative, but being able to set your own schedule of things is a real life saver when you have a traditional job on the side. One week you could set up to add in a debug console, the next is to add a whole new mechanic. Flexibility is key when you have other commitments.

The Cons
It can be lonely at the top. Not having one board with the project can be demotivation at times. Even not being able to talk about the project when ever you want is a real bummer.

Feedback is often hard to come by. Without a team to tell you your idea is stupid, or that feature X should be like A you can carry on with a plan that you have had for months, only to realise you have wasted development time.

Communication with freelancers can be tricky at times. Not being hired under a full company can lead to freelancers not feeling confident in the product and dropping it / stop doing work. This has happened to me twice now, and believe me when I say that these issues sneak up on you, usually you only see there was an issue when you look back and wonder what went wrong.

Preventing The Cons




Addressing the first two is easy. To anybody, I would suggest creating a blog, this allows you to express yourself about the project and seeing other people liking your project and giving feedback is a real motivator. It also lets you evaluate where you have come from, being able to look back and see how your project was weeks or months ago, and seeing how much you have progressed will spur you on to carry on development.

For the communication, I hope I have solved my communication issues. Now I am using slack, it is a communication tool which allows teams to talk to each other. What this has which other services doesn't is different chat rooms and the fact it is on lots of different platforms. For example I usually talk to my artist using my mobile, and he is on PC.


That just about wraps it up, no doubt I have forgotten a few points, so may edit this a few times.

Until Next Time!
DSM

dsm1891

dsm1891

 

The Mechanical Heart: Engine Upgrade

The Mechanical Heart
Development Blog
This week marks the final(ish) turning point for TMH's Engine. If you have read previous additions you ay know the engine was originally written in C++ and used Direct X 9 Graphics library. A little over a month ago, I decided to upgrade the graphics library to Direct X 11. Unfortunately this took way longer than expected (See Appendix A). But at last I have a working version of the engine using Direct X 11.

In other news TMH has got a new logo / artwork for 'The Mechanical Heart':


So Why The Upgrade to Direct X 11?

Firstly, and maybe the most important reason was that graphical programming is one of my weakest areas of programming, so I wanted to expand my knowledge and learn new techniques. Among those techniques, I really wanted to add lighting/shadowing to TMH, I feel this will add great depth and vastly improve the graphical fidelity of the game. Here I have to shout out Migi0027 because, he has been/will be, a big help getting lights to work in the game. He recently released a lighting blog entry which looks really good.

Another reason I wanted to upgrade was the ability to use shaders. I am aware that you can use shaders with Direct X 9, however at the time I was using the Fixed Function Pipeline. And I thought if I had to change the pipeline, I might as well use the latest version of the library.

Finally, maybe one of my biggest motivator, I am now using a Camera instead of drawing straight onto the projection. This may seem trivial but it now allows me to do lots of different effects with ease. I previously moved or drew each image with an offset according to where my 'pseudo' camera was, I.E. moved the world to simulate the camera moving. This was suppose to be a temporary measure, however it stayed in the engine for far too long. One of these effects I want to play around with is screen shake. You can read up on my techniques in my blog post:Good Vibrations .


What's next?
Well, I am glad I have got the engine working with Direct X 11, Some areas need tweaking but that should take a couple weeks at most. Lights will no doubt take a bit longer and lots of fine tweaking.






As you can see, not that I expected there to be, but there is no graphical difference with drawing images. But things start to look good when I add a simple light to the scene.




This is only a glimpse of things to come, but it is an exciting time for TMH.

As I previously said, graphics programming isn't my forte, so after lights/shadows are implemented this may be the last time I touch graphics in this project* and as a result of that I am getting excited to go back to mechanics programming.

*unless I decide to port to Open GL, So lets hope there isn't my demand for that


Until next time,
DSM

[size=2]Appendix A
[size=2]I would like to apologise for lack of development blogs, last few weeks have been hectic from job interviews / tests to working 54 hour weeks. I do try to keep this as a weekly blog, but rest asure I have the next few blogs planned . Also I was blown away by the popularity of my last blog entry thank you all who liked/upvoted and a special thanks to Gamedev.net for featuring it. I definatly know the standards you guys like now, so I will try to keep any technical blogs up to standards from now on

dsm1891

dsm1891

 

The Mechanical Heart: Map Generation

The Mechanical Heart
Development Blog

In this issue I would like to talk about the map generation in TMH, if you're unaware of the storyline I would recommend catching up and read the first development blog. True to most rogue-like( like)s TMH will feature randomly generated, room based maps. TMH will challenge the player of navigating through lots of different rooms to get to the destination room(s). I wanted the player to feel lost in The Inventors factory, and constantly twisting and turning through different rooms. This is so the path that player will take will take will mimic the crazed pathways of The inventors mind.

When designing the algorithm for the map generation there are X goals to keep in mind, they are:
Destination room to be accessible from any room in the map.
Start room to destination room path should not be as the crow flies.
Able to handle different sized rooms.
Conforms to Euclidean spacing.

Firstly, I decided on a simple two dimensional array to hold each room that the player would be traversing. For the Number One and Number Two goal I decided to use a path finding algorithm to generate nodes from the start room to the destination room. The location of each node would be the location of a room in the array. I based the path finding algorithm of A* algorithm, however I had to devise a way of making the path it would create... less efficient, and here is the point I coin the name A[sup]-[/sup] algorithm (maybe I need a better name, suggestions?).




This is pretty simple to do, I simply add a random number between 0 and X to the cost of each node, the higher X is the more random the path would be. However, there does seem to be a sweet spot, as if X is too high the cost of the node will be negligible and the path will no longer bend and twist towards the destination room. I Also added dividers and barriers the A[sup]-[/sup] would have to work around.

I have created a small program so you can try the A[sup]-[/sup] for yourself.

The next step in the map generation is to use the path generated to fill the map with different rooms. There are a couple of assumptions that we have to make before we do this. The first assumption is that all rooms that are about to be filled are the size of the smallest room, and that 1 element in the array has that size 'in the real world space'. This is to ensure there will always be an adjacent room when we start to add and remove rooms. However this causes problems as demonstrated in the gif below. Because there are different sized rooms the is a chance that the map will not conform to Euclidean space, rooms that clash with Euclidean space are marked in red.



Room Based Euclidean Space Algorithm (RBES)

RBES is an algorithm that takes a generated map, conforms it to euclidean space and then links the rooms together. This algorithm is needed because there are rooms with different sizes, and the rooms are selected randomly. This leaves the rooms in the map prone to overlapping each other. This can cause problems with linking of rooms, and logical path taking of the player, which leads to confusing gameplay experience. This, overlapping or sharing the same space, is known as non-eclidean space or non-eclidean geometry. non-eclidean space allows for deformation of 'normal' space allowing objects and places to occupy the same space as each other, this lends itself well for some games which aims to confuse the player with the nonsensical world layout. However this does not fit the theme of the game, and thus the game world will need to conform to Euclidean space.

RBES has two main steps in the algorithm, the first step is checks and set, this step checks that the rooms to conform to Euclidean space and handles them if they don't, and the second step links the rooms together using portals. When the player enters a portal the main character will be teleported to the corresponding room.

Check and Set
Rooms The first step of RBES is to conform the generated map to Euclidean space. It checks that none of the rooms overlap and if they do it deals with the overlapping room accordingly. This is a fairly simple process, cycle through each room and check if the room the relative position of the subroom(a subroom is the area of a room that could be divided into the smallest possible size for a room) in the matrix contains a room.For each sub room If there is a room in that subroom's relative position Delete that room
This is simple and quick, however this algorithm has a major flaw, it doesn't take into account for any rooms that are prior to the current room's position, for example:



To correct this each matrix entry before the current subroom on the X axis will need to be checked.
The altered algorithm is:For each subroom If there is a room in that subroom's relative position Delete that roomFor each subroom on the Y axis For each room before current subroom on the X axis While there is a room and that room intercepts current subroom Replace that room with another random room

Linking rooms
Now we can be sure that the map conforms to Euclidean space we can place portals to link the rooms together. This will allow the player to travel from one room to another. Each portal contains the information of the destination room, player position in that room, and camera position. All of these things can be worked out from: The size of the room and adjacent room and the position of the room and adjacent room in the array.

Rooms can be linked in a one to many fashion, this means that a room can be linked to multiple different rooms, how many rooms said room is inked to depends on two factors; room size and if there is an available room. To link the rooms, each room and its subrooms need to check if there is an adjacent room(or subroom) in real world space.For all of the rooms For the perimeter of the room If there is a subroom of any previous room adjacent to any of the current subroom set a portal from the current subroom to the adjacent subroom set a portal from the adjacent subroom to the current subroom
?
?
?
?
The final map looks like:



This can be ran multiple times to create different routes that the player can traverse.


I am pretty happy how the map generation worked out, it meets the specification pretty neatly, and creates some interesting pathways. I may end up tweaking it and or making it more efficient. I was also thinking of making an article about it, but I am still undecided...

Until next time,
dsm?

dsm1891

dsm1891

 

The Mechanical Heart: Snow and My Ineptitude

The Mechanical Heart
Development Blog


Where better to start the Dev-blog than what the player will see first when playing the game, the main menu. We wanted the main menu to really set the scene of the game, if you have read the previous issue you will know the game is set in a factory located in a baron wasteland outside of a city. My artist got to work and created the following image.




As pretty as the picture is, I felt the image the image looked rather flat even for a menu in a 2D game. To make the image more dynamic my artist suggested to add clouds which crept across the ice and snow which fell from the sky. Adding clouds was simple enough, as they are just images which move Left->Right or Right->Left... placing them where the artist wanted them was a different story, after getting a graphical representation from the artist to where he wanted them place the clouds I was able to place them where he wanted them.

However the snow was another story entirely, hence the title of this blog. I now, have come to realise that I am the only person who [s]thinks[/s] KNOWS that snow falls with a pendulum type motion when there is no wind, similar to how a leaf falls.



(a rough mock up)


After Creating a rough version of how I wanted the snow to fall I asked for feedback. The mass majority of people pointed out [s]my mistake[/s] that they think that snow falls straight down, and not with a swing type movement. I decided to consult with my artist again and he confirmed that he envisioned what everybody else was saying. He gave me instructed me to do the following for optimum snow movement:
200+ snowflakes on the screen
Random fall time
Random lifetime - then fade out
Random speed
Random angle, but all falling Right->Left

These where all pretty simple specifications and where implemented in no time. I also decided to make it look like, vary rarely, a snowflake would stick to the players monitor and fade out.


Finally, we decided Help and Controls/Options menu should pop up above their respected buttons, and tell the player about the game and the controls.



The menu is mostly finish finished I just need to add the game title to the main menu. I would also like to add (sky) clouds to the scene, I think it will look nice if I layered them behind/in front of the factory which will also help to reduce the 'flatness' of the image. Another addition might be adding smoke which billows from the chimneys of the factory.

I'm still looking for feed back on the Menu and the Blog, so don't hesitate to let me know!

Until Next time,
Dsm

Note: the fonts are a little pixelated but I will be upgrading the graphic system in the future so I will fix that then. Also, I realise I could put the Controls into the help menu, but I will, in the future, adding more options (to the controls menu) and increasing the blurb (in help menu)

dsm1891

dsm1891

 

The Mechanical Heart - An Introduction

THE MECHANICAL HEART
Development Blog

Welcome all,

I have decided to create a weekly development blog of my current project titled The Mechanical Heart. In this issue I will outline what you can come to expect from this blog and an introduction to the game.


About the Blog
In this blog I will me covering all aspects of the development of TMH (The Mechanical Heart), from design to programming to art, however as I am primarily a coder I expect most blogs to be about features and their implementation into the game. I will be updating this weekly (hopefully), I aim to release a new issue every Sunday or maybe Monday if I do not have the time. Its also worth noting most of the art with in the game is placeholder stuff, but it 'should' be totally replaced soon as I have an artist working for me. This issue is a bit bland with blocks of text, in later issues I will try to illustrate as much as possible as nobody likes blogs with walls of text.

Commence the wall of text!


About the Game
Almost a year ago I was just about to start my final year at university, for my thesis/final project I decided to create a game and it's engine (which I scored 90% on!), that is the product of what I have today and hopefully the base of a released game in the future. The game ( and it's engine) is being developed in C++ and using [s]DirectX 9[/s] DirectX 11 for the graphics API.

The Mechanical Heart is a Rogue like like like like (how many likes are we using these days?). It has deep inspirations from games such as Rogue Legacy and Binding of Isaac and draws aspects from those games. The game is about a Mad inventor who has stole an object of great power, The Mechancical heart. It is up to the player to venture into his factory to retrieve the treasured object. However standing in-between you and it, are The Inventors contraptions which will do everything in their power to stop the player in the tracks.

[indent=1]Prologue
[indent=1]Your city for many years has been powered by a powerful device known as the Mechanical Heart. A powerful invention which limits have not yet been reached. The inventor of said device gave the Mechanical heart to the city as a gift. But now he grows tired and bitter as the city and its people grew rich, profiting of his device that he alone invented.

[indent=1]After many years of jealousy The Inventor became disjointed and was cast out of the city. As an outcast he plotted a devious plan, to take back what he saw as his, and his alone. Before the citizens knew what happened The Inventor had succeeded in his plan to steal the Mechanical Heart, and the city was plunged into darkness.

[indent=1]Powerless the city soon delved deep into poverty, and disease spread across far and wide, unable to function, unable to rebuild. For too long they relied on the Mechanical Heart. Now it is up to you to restore power and glory to your city. However the, now mad, Inventor will not make it easy for you. He now resides in his derelict factory on the outskirts of the city. The Inventor has created numerous contraptions throughout the factory to stop you in your tracks!


About the Team
This section should be pretty short and sweet, because at the moment the team, Binary Cats, consists of just me. I am the sole driving force on this projects and do most/all of the work on it. I am, however, outsourcing the music and art, and although I do not have a composer as of yet I have an awesome artist who is currently working on the art for my game.


About Me
So who am I? I have just graduated University with a first in BSc Computer Game Development. I really enjoy video games, but these days I find more joy in developing them than playing, I am skilled in C++ and Java And I enjoy programming in my spare time. I am undergoing this project as I search for a Job in the Game industry.


That's it for this entry,

Until next time,
Dsm

dsm1891

dsm1891

  • 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!