Sign in to follow this  
  • entries
    2
  • comments
    0
  • views
    311

About this blog

This blog will serve as a public dev diary of my upcoming and first release, Dystopian Lights. So far it is only available for download from http://solumgames.com where I have self-published. I will release the game in stages, and first it will be for the Android mobile operating system. Once I have updated it enough throughout the rest of 2017 I will release it on the Google Play Store and probably some other platforms as well. Once it is out and polished to my expectations I will release it on Windows/Linux, hopefully through steam, and then I will follow-up with an iOS and Mac release if all goes as planned. Periodically I will post some code that I am using to develop the game which is in C# via mono and monogame. If it helps anyone in the future with their own projects then that is awesome, and please feel free to use any code that I post here without restriction.

If you have ever played Geometry Wars on the Xbox 360 then you will be very familiar with how this game plays. There are a few key differences in the gameplay elements, such as the enemy behaviors are far different, and your ship can be upgraded and customized throughout the game as you earn points for destroying your enemies. I chose this style of game as my first large project as I have enjoyed playing games like Geometry Wars and many other shoot em up games like gradius or even metal slug. I hope to replicate the fast based shooting action as well as adding some other focal points to the gameplay that have not been introduced often or ever.

I should be releasing a new dev blog at least once a week, and hope to do so even more frequently. It just all depends on how much time I allow myself to work on this project versus consuming the electronic amenities that I am trying to create. Hope you guys enjoy the blog and stick around for the updates to come.

Entries in this blog

kostile

I am excited to say that I have gotten a bit of work done on Dystopian Lights recently and also excited to see that people are downloading it and trying it out on their android devices. I haven't received any feedback yet, and please don't hesitate to give any critique or suggestions. I am really open to everything as this is my first serious project that I think has any validity of professionalism in it, and I really would like to see it succeed. I do have a few updates for you guys and will have a new version ready for download by this weekend, but here is the new stuff I've been working on.

1. Capacitor

I have enjoyed playing shooter games on mobile devices but many of the free to play or inexpensive ones all do something similar with their weapons schemes. Generally you select a ship and it has specific weapons with it, or you toggle on and off the different weapons you have while only being able to shoot one weapon at a time. Since I am such a fan of the chaos and destruction in these games I was trying to come up with a good way to enable the player to have all weapons active at the same time without it being too overpowered. My solution is a capacitor. Your regenerate energy every second and certain weapons use more energy than others. When your energy is depleted, you can only use your basic shot. With this enhancement to the game, it has given it a new level of customizability and even greater balance. It has also given rise to new ideas that will be implemented before I release the next version which should be before the end of the month. You can still toggle off and on your weapons in order to control your capacitor usage, or you can just watch it drain and toggle off automatically and wait for it to regenerate.

Small disclaimer: The grid is not as detailed in the android version as it appears in this image

blog2picture.thumb.png.9a3d15c4fc31d8dddf531c6ca1ed885e.png

2. Health Packs

One thing that was missing from the game was the ability to heal after you have taken damage. Since there should be ample amounts of chaos, then you should really be able to heal after all the damage that you have taken. Each enemy now has a 10% chance to drop a health pack on death. Another way to heal right now is to level up. When you level up you heal fully. This may change in the future as it does seem a bit overpowered and throws the balance of the game off quite a bit.

3. Balance

I am working on balancing things in the game to make it feel like you get a good amount of time of play before you die and where your skill can extend that time substantially if you are good at dodging and killing things. This is no easy task and I imagine balancing changes will continue from here on out until the full game is released. Some of the changes are the required points you need to level up each time. It's a simple algorithm and can be easily extended to add more balance later if needed. Besides just the points required for leveling be updated, I have also changed around some of the spawning algorithm. Spawning happens in two forms in this game. There are random spawns, and pattern spawns. With the random spawning, a random enemy that falls within the level range of the current players level will spawn at a random location within the bounds of the game and outside of the hit radius of the player. The other form is the patterns. A pattern is randomly selected based on a few conditions and will spawn around the player. Usually it will appear as a circle or triangle. The pattern spawn will be forced every 15 seconds or so, sometimes exceeding the max enemies a player would see at the given level of random enemies, but is still limited. This form still uses the same algorithm for enemy selection, which is something that I need to revisit as the enemy selection favors higher level enemies the higher level the player is and scales at a very unbalanced rate.

Future Updates to Come

Some of the changes I hope to have finished for my update this month will be more upgrades. For one, I will probably make the shot weapon the default weapon, and then the missile and laser will have to be unlocked with points which can be further upgraded. The missiles will have an option to increase amount fired at a time. The laser will have options for increasing damage, length, and capacitor efficiency. The player will have a new upgrade for max capacitor and I will also be making a lot more balancing changes. I would like to start adding sound effects in the game soon and already have a system designed and implemented for sound effects and music. It will add a nice touch and probably make the ambiance of the game a lot better. Another thing I would like to add is some different sprites for certain tiers of weapon upgrades. It looks very static at this moment and if your weapon projectile changes every 3 to 4 points spent, it could add a nice touch. The player ship will also change here in the very near future. One thing that I have been meaning to work on is a turret sprite for each weapon. Right now it only exists for the laser as you can see in the picture above but even then it is not as dynamic as I would like. For instance, with the shot weapon, you might have 5 waves coming and having a single static image might not be the pleasing to look at as it will not match up properly as one would expect. This might mean creating a lot of different images for each different combination of weapon and the count of the projectile that each weapon has but this would add an exponential amount of work to do. In order to minimize this work, I might procedurally generate a turret sprite based on what weapon is active. The system might take some time, but then I would only have to make a few images that are spliced together based on the procedural system rather than creating 500 images for different combinations of weapons and weapon levels.

Some Code:

Something I wanted to share with everyone was the code that I use for my health bar and the capacitor energy bar. With this code you will notice that there are 2 draw methods that are being utilized. That is due to the nature of the game and it's post processing to achieve the glow effect. The PercentBar.Draw() method will draw the darker lines that you see inside of the health and capacitor bars, whereas the background is the DrawPostProcessed. This is probably a poor name for the method as it's not post processing anything, it could be renamed to DrawLines and DrawBackround for a better naming convention but this works for me since I am just trying to distinguish between what is post processed for the glow effects and what is not. The parameters foregroundColor and backgroundColor are optional and will default to green and red, which is what the health bar uses, but you can also make the foreground color anything that you choose as well as the background color. If you give the backgroundColor a 0 alpha value then it will just look like the bar is shrinking if it decreases in size or will look like it is growing if it is increased. This PercentBar class can be used to represent any kind of percentage that you want to display such as health, energy, or even a loading bar.

    public class PercentBar
    {
        private float width;
        private float height;
        private Color backgroundColor;
        private Color foregroundColor;
        private Vector2 location;
        private float percentShown;

        public PercentBar(float width, float height, Vector2 location, Color? foregroundColor = null, Color? backgroundColor = null)
        {
            this.width = width;
            this.height = height;
            this.location = location;
            this.backgroundColor = backgroundColor ?? Color.Red * 0.6f;
            this.foregroundColor = foregroundColor ?? Color.Green * 0.6f;
            percentShown = 1;
        }

        public void updatPercent(float current, float max)
        {
            percentShown = (current / max);
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            float segmentSpacing = 4;
            float segmentWidth = 2;
            float segments = width * (percentShown) / segmentSpacing;

            for (int i = 0; i < segments - 2; i++)
            {
                spriteBatch.Draw(Primitives.line, new Vector2(location.X + (i * segmentSpacing), location.Y), scale: new Vector2(segmentWidth, height), color: foregroundColor);
            }
        }

        public void DrawPostProcessed(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(Primitives.line, new Vector2(location.X - 5, location.Y - height * 0.25f), color: foregroundColor, scale: new Vector2(width * percentShown, height * 1.45f));
            spriteBatch.Draw(Primitives.line, new Vector2(width * percentShown + (location.X - 5), location.Y - height * 0.25f), color: backgroundColor, scale: new Vector2(Math.Abs(width * percentShown - width), height * 1.45f));
        }

        public float PercentShown
        {
            get { return percentShown; }
            set { percentShown = value; }
        }

        public float Width
        { get {return width; } }

        public Vector2 Location
        { get { return location; } }
    }

 

kostile

So to start the day I am going to share with you guys how I use touch controls and touch "joysticks" in Dystopian Lights (previously Neon Android) to control movement and crosshair aim. Initially I had a floating joystick system where you would tap and hold in a certain area but the response to that system has been heavily negative, so I have redone the code running the joysticks and with refactoring I have made them static as well as extremely reusable. This code is tested in monogame for android and should work for iOS as well if you are using the mono and the monogame framework. What I wasn't aware of when I wrote my first joysticks, is that monogame has a cool feature for touchlocation IDs that allows for greater control without having to worry about which touch is which, we already know if we assign it an ID on touch. You can view the code and use however you want if you decide you like it.

If you have ever used monogame and you look at the scaling in the draw method, you will notice that I multiply the scale by 0.001f. This is because the Primitives.circle texture has a radius of 500. There may be some other oddities in the code, if you do use it and have any questions, don't hesitate to ask. The code is at the end of the blog.

So this is one of the updates for the game, as well as a proper title. I have been developing the game under a working title "Neon Android" for quite some time but I have always known that this isn't going to fly as the actual title of the game. Dystopian Lights rang a good bell for me when thinking about how I want the game portrayed. For now it sits as a very similar, almost clone of, Geometry Wars. This is intended for art and play style to some degree, but with many varying factors I think the two games will stand far apart from one another once Dystopian Lights is a finished product.

One of the other upcoming changes for the game is the change in the GUI. It has been heavily improved on mobile platforms. Previously the GUI was tiny and fit for a computer, but now it looks okay on Android and you can actually navigate the menus when upgrading your weapons. Also I have changed the buttons for weapon selection to be highlighted when selected so you actually know what's firing without having to pay attention to your projectile.

59f00514f3a89_Capture_2017-10-24-22-24-06.thumb.png.d1ee9c3b7f99641d40cf6210fdc1ba81.png

 

So from here, the plan is to release an update on my website by this Friday, which will include the changes I have showcased here as well as a few other minor changes. Right now the game is only available on Android and is available for download from my website, https://solumgames.com so please head there if you want to check it out. I will have more Dev Blogs in the future and hope to do a minimum of one a week until the end of the year, when I will release it on the Android app market and then see about working for a PC release. The largest problem I have encountered so far while developing this game is the spawning pattern. If anyone has any recommendations for setting up a spawner that gets infinitely more difficult, please feel free to give your input. I have a system right now that works, but its scaling is terrible and it feels like end game within about 5 minutes. There is some obvious tweaking and balancing that I still need to work out as well, so if anyone trys the game and would enjoy something being different, feel free to let me know what I should change.

Some of the ideas I have for the future of the game will be to include a story mode. My thoughts keep going around to scripted spawns, and then some animations with full screen-width chat boxes that show an avatar of the character speaking. There will be at least a few boss fights and some over the top story that would make this game seem like a space opera straight out of the cheesiest movie you have ever seen on the Sci-Fi network. I have also been working out this idea where your player has a capacitor that can only sustain so many weapons for so long. If I do add it, the shot weapon will probably always be available, when you use your missile and laser in tandem with something else, depending on your capacitor recharge rate and max capacitor, you will run out of energy which will cause your capacitor to short and then the only weapon available until it fully recharges will be the shot weapon. Health packs are coming as well. They will be random drops from enemies and they will heal different amounts based on the enemy killed. 

So far I am happy to see that I have about 40 downloads of the game just from my website alone. I have not received any feedback from any users of the software that I don't know, so please if you are downloading it, speak up with any critique or recommendations. I would love to hear, the good, the bad, and the ugly.

 

    public class Joystick
    {
        private Vector2 outerLocation;
        private Vector2 innerLocation;
        private Vector2 direction;
        private Color innerColor = new Color(0.2f, 0.2f, 0.2f, .5f);
        private Color outerColor = new Color(.5f, .5f, .5f, .5f);
        private float innerRadiusRatio;
        private float outerRadius;
        private int touchId;

        public Joystick(Vector2 location, int radius)
        {
            outerLocation = location;
            innerLocation = location;
            outerRadius = radius;
            innerRadiusRatio = 0.3f;
        }

        public Vector2 Direction
        {
            get { return direction; }
        }

        public void Update(TouchCollection touchCollection)
        {
            foreach (TouchLocation tl in touchCollection)
            {
                if (tl.State == TouchLocationState.Pressed)
                {
                    if (AOneMath.Distance(outerLocation.X, tl.Position.X, outerLocation.Y, tl.Position.Y) <= outerRadius)
                    {
                        touchId = tl.Id;
                    }
                }

                if (touchId != tl.Id)
                {
                    continue;
                }

                if (tl.State == TouchLocationState.Moved)
                {
                    float dirX = tl.Position.X - outerLocation.X;
                    float dirY = tl.Position.Y - outerLocation.Y;

                    direction.X = dirX;
                    direction.Y = dirY;
                    direction.Normalize();

                    float length = AOneMath.Distance(tl.Position.X, outerLocation.X, tl.Position.Y, outerLocation.Y);

                    if (length > outerRadius - outerRadius * 0.5f)
                    {
                        length = outerRadius - outerRadius * 0.5f;
                    }

                    innerLocation.X = outerLocation.X + direction.X * length;
                    innerLocation.Y = outerLocation.Y + direction.Y * length;
                }

                if (tl.State == TouchLocationState.Released)
                {
                    innerLocation = outerLocation;
                    direction.X = 0;
                    direction.Y = 0;
                }
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(Primitives.circle, position: Vector2.Subtract(outerLocation, new Vector2(outerRadius / 2, outerRadius / 2)), 
                             scale: new Vector2(outerRadius * 0.001f, outerRadius * 0.001f), 
                             color: innerColor);
            spriteBatch.Draw(Primitives.circle, 
                             position: Vector2.Subtract(innerLocation, new Vector2(outerRadius * innerRadiusRatio / 2, outerRadius * innerRadiusRatio / 2)), 
                             scale: new Vector2(outerRadius * innerRadiusRatio * 0.001f, outerRadius * innerRadiusRatio * 0.001f), 
                             color: outerColor);
        }
    }
 
Sign in to follow this