Samstag, 27. August 2016

Vote & Help Developing CamoTactics!


Involving the gaming community is important making a great game. For this purpose I have created two polls that allow you to share your thoughts on CamoTactics.



Future Content


The first poll is all about future content to be added to the game. You can give it a shot on Google Forms. By filling this out you help me focusing on the feature you would like to play most. Make sure to share your ideas, no matter how silly they may sound! They may lead to other interesting ideas. :)

Your User Experience


The second poll is about your gaming experience with CamoTactics. If you played the game you can submit your feedback here on Google Forms. If you didn't play CamoTactics yet, go do it nao!


Happy voting and thank you for playing CamoTactics!


Freitag, 26. August 2016

Life is like Gamedev

It happens to me when I code all the time: Create something just to later discard it and start new from scratch. You make two steps forward just to make one step back again. It's frustrating sometimes.

Come to think of it, it's just like real life. Sometimes you're trying to make a change in your life, trying to adapt some habits, like trying to stick to your marketing schedule or diet plan. Then there's times when things happen, you slack and fall back to your old habits.

It's a bit like marble in a funnel that's slowly rolling towards the hole in the center. You're trying to roll towards the center, but sometimes you go too fast and bounce back to the outer edge. You do this until you finally achieve your final breakthrough: when your good habits finally stick and your code finally works (well... mostly ;) ).

Just like in gamedev.

So when you practice going through this with gamedev, it will likely spread over other parts of your life.

Code away, never stop creating and keep making awesome games!


Donnerstag, 25. August 2016

CamoTactics Arena Mode & Missions in 7.2!

Despite of delays because of real life stuff (I HATE moving twice within two months D;) progress was still made on CamoTactics!

Prepare your sitting device for new features, pics and gifs:



For one, enjoy feeding your foes some lead in arena mode! This isn't just a dummy feature, this has functionality and the character/weapon you've chosen will be carried into the arena.





Sail through the tutorial mission with ease! Missions now feature a very handy command line style trigger handling that lets you do almost anything on mission/objective start, success or failure. This is very important for the campaign of the game.





Your positional awareness is now provided by this very useful HUD aiming aid! You will see why you need this when moving around and shooting...





A few fixes and improvements include but are not limited to:

  • Better infantry graphics
  • Fixes for picking up items
  • Fixes for mounting vehicles
  • Fixes for wrong light positions
  • Faster renderer (very noticable if you compare it to 7.1)
  • Mission and Statistics Screen
  • Better Camouflage implementation
Making this game is a lot like wading in deep water not knowing what features fit and which to discard, considering a lot of that is experimental (not to mention lost time when discarding one). That process takes ages but the results are promising already and I have no doubt the end product will be amazing!

These features are to come very soon with CamoTactics Alpha 7.2. Until then, please check out CamoTactics Alpha 7.1 here:


CamoTactics Alpha 7.1

Samstag, 16. Juli 2016

Why PokemonGo is such a success

Only a few weeks in after its release, PokemonGo has become a hit for gamers world wide. It even goes so far that people are paying less attention and getting themselves hurt and deputies making demands to regulate the game.
 
But what exactly made it such a success?

First off, the player base of Pokemon is huge. Pokemon has been around for decades and influenced generations of gamers and accumulated a vast following during that time. It's a game that can be played with your smartphone everywhere at anytime (that is if the servers aren't shitting the bed). Another side effect is, you also connect with people as they venture to the same Pokemon hotspots as you.

While the gameplay isn't much at the moment, it still taps into the desire of discovery and collecting all Pokemon - or collecting enough Pokemon candy to level up your favorites. What is genius about it is that it takes the act of catching them to real life - no doubt that for some gamers, dreams came true!


So in other words, you have:
  • a high accessibility mobile game
  • a giant following of fans of all ages
  • bringing a well-selling gaming franchise to real life
  • game mechanics that stimulate the urge to collect and discover (Pokemon and their spawning points, in this case)
They really got out the best of what they already had and struck a real hit on the mobile market.

I remember back a year or so Nintendo's decision to go mobile was generally met with skepticism. Now they have managed to create a hype that will not only change the game industry, but also society. Forever.

Well done, Nintendo. Well done.


Mittwoch, 6. Juli 2016

Creating a Mission System in Java


So... how do you create a Mission System?

I asked myself this question twice so far and recently I came up with the following approach. This system is relatively simple but you can do most of basic missions with it. It consists of a tree with depth 3: Mission, Objectives. Conditions. Each of the components has a mission state, consisting of PENDING, SUCCESS and FAILURE.

First, I will describe the classes needed, which is then followed by their java code at the end of this article.


The general structure is as follows:






Mission:
  • A Mission has a title, a debrief description and a short description. 
  • A Mission has multiple objectives.
  • As general rule, a mission is deemed a success if all its child objectives are deemed successful.

Objective:
  • An Objective has numerous conditions.
  • Objectives have a different behavior per type, described below:

    Default: All objectives must be set to success for a mission to return success.
    Failure: If this objective is failed, the entire mission fails.
    Optional: The objective is effectively ignored by the mission, but can be used to, say, determine a score.
     
  • By default, they are not being updated once a condition was met or failed, but you can change them to run permanent updates.
 
Conditions
  • All conditions must be met for an Objective to be successful. Behavior types (default, failure, optional) do not apply here to keep it simple. To make up for that, I've added the possibility to invert them.
  • Conditions are implemented by you via an interface and an abstract helper class. 
  • For GUI purposes, there's also methods to display the condition as string for the end user.

To use it, you setup your Mission, Objectives and Conditions and call Mission.update() each time you update your game.

Here's the code:



Mission


/**
 *
 * @author B5cully
 */
public class Mission {
  
    public String title;
    public String debrief;
    public String summary;   
    public LinkedList<Objective> objectives = new LinkedList();
    Objective.State state = Objective.State.PENDING;

    public Mission() {
    }
   
    public Mission(String title) {
        this.title = title;
    }

   
    public Objective.State getState() {
        return state;
    }
   
    public void addObjective(Objective obj) {
        objectives.add(obj);
    }
   
    public void start() {
        for( Objective objective : objectives ) {
            objective.start();
        }
    }
   
    public void stop() {
        for( Objective objective : objectives ) {
            objective.stop();
        }
    }

    /**
     * Updates this mission's state
     * @return
     */
    public void update() {
        int i=0;
        boolean success = true;
        boolean failure = false;
        for( Objective objective : objectives ) {
            switch (objective.state) {
                case SUCCESS:
                    if( objective.constant_check ) objective.checkState();
                    break;
                case FAILURE:
                    if( objective.constant_check ) objective.checkState();
                    break;
                case PENDING:
                    objective.checkState();
                    break;
            }
            switch( objective.type ) {
                case NORMAL: {
                    success = i == 0 ? objective.state.equals(Objective.State.SUCCESS) :
                                   success && objective.state.equals(Objective.State.SUCCESS);               
                } break;
                case OPTIONAL: {
                    //ignore the objective
                } break;
                case FAIL: {
                    //only consider fail state
                    failure = failure || objective.state.equals(Objective.State.FAILURE);                       
                } break;
                   
            }
            i++;
        }
        if( success ) {
            state = Objective.State.SUCCESS;
        }
        if( failure ) {
            state = Objective.State.FAILURE;
        }
    }





Objective

/**
 *
 * @author B5cully
 */
public class Objective {
  
    public enum Type{
        /**
         * The objective contributes to success of the mission.
         */
        NORMAL,
        /**
         * The objective counts as fail condition of the mission.+
         * If one objective of this type closes with failure,
         * the entire mission fails. The pending state of
         * FAIL objectives are ignored in the total outcome.
         */
        FAIL,
        /**
         * The objective is optional, it has no effect
         * on the total outcome.
         */
        OPTIONAL;
    }
    public enum State{
        PENDING, SUCCESS, FAILURE;
    }
  
    public String title;
    /**if this is true, the objective is constantly validated. If false,
       the objective is validated once and succeeds permanently once triggered.*/
    public boolean constant_check;
    /***/
    public Type type = Type.NORMAL;
    State state = State.PENDING;
    /**
     * All conditions must be met in order for na objective to
     * succeed.
     */
    LinkedList<ConditionImpl> conditions = new LinkedList<ConditionImpl>();

    public Objective() {
    }
  
    public Objective(String title) {
        this.title = title;
    }
  
    public void addCondition(ConditionImpl condition) {
        conditions.add(condition);
    }
  
    public void start() {
        for( ConditionImpl condition : conditions ) {
            condition.start();
        }
    }
  
    public void stop() {
        for( ConditionImpl condition : conditions ) {
            condition.stop();
        }
    }
  

    @Override
    public String toString() {
        String s = "";
        int i =0;
        for( ConditionImpl condition : conditions ) {
            s += condition.getName() + ": " + condition.getDisplayedText();
            if( i > 0 && i < conditions.size()) s += "\n";
            i++;
        }
        return s;
    }

    public State getState() {
        return state;
    }
  
    public void checkState() {
        boolean success = false;
        int i =0;

        //check the conditions
        for( ConditionImpl condition : conditions ) {
          
            state = condition.getState();
          
            if( !state.equals(State.PENDING) && constant_check) {
                //still update the condition if constant check enabled
                condition.checkState();
            } else
            if( state.equals(State.PENDING) ) {
                //pending: simply update. No updates if failed or succeeded.
                condition.checkState();
            }
            success = i == 0 ? state.equals(Objective.State.SUCCESS) :
                               success && state.equals(Objective.State.SUCCESS);
            switch( state ) {
                case FAILURE: {
                    this.state = State.FAILURE;
                    return;
                }
                default: break;
            }
            i++;
        }
        if( success) this.state = State.SUCCESS;
        else this.state = State.PENDING;
    }
}



Condition 


/**
 *
 * @author B5cully
 */
public interface ConditionImpl {
  

    /**
     * Invoked on condition start.
     */
    public void start();
   
    /**
     * Gets the name of this condition
     * @return
     */
    public String getName();
    /**
     * A Localized, properly formatted display
     * text for this condition.
     * @return
     */
    public String getDisplayedText();
   
    /**
     * @return the state of the condition
     */
    public Objective.State getState();
   
    /**
     * Evaluates the state of this condition. This normally involves
     * calculations.
     */
    public void checkState();
   
    /**
     * Invoked on condition stop (e.g. when
     * it has failed or is being reset)
     */
    public void stop();

}

Here's the helper class for Condition, followed by an example implementation. 


/**
 *
 * @author B5cully
 */
public abstract class Condition implements ConditionImpl {
  
    protected Objective.State state = Objective.State.PENDING;
    protected boolean inverted = false;
    /**
     * The name of this condition.
     */
    protected String name;
    /**
     * A format string to display the condition.
     */
    protected String format_string;
    /**
     * The string returned for display. This is usually
     * name + String.format(format_string, args), where
     * args is relevant info about the condition.
     */
    protected String displayed_text;

    public Condition(String name, String format_string) {
        this.name = name;
        this.format_string = format_string;
    }
   
    @Override
    public String getName() {
        return name;
    }
   
    /**
     * Inverts the result. E.g. Instead of delivering
     * SUCCESS by default, FAILED is being returned.
     * @param inverted
     */
    public void setInverted(boolean inverted) {
        this.inverted = inverted;
    }
   
    @Override
    public void start() {
    }

    @Override
    public Objective.State getState() {
        return state;
    }

    @Override
    public void stop() {
    }
}


/**
 *
 * @author B5cully
 */
public class ConditionKilledEnemies extends Condition{

    LinkedList<Entity> enemies = new LinkedList<Entity>();
    LinkedList<ListenerEntityImpl> listeners = new LinkedList<ListenerEntityImpl>();
    int size = 0;
   
    String current_displayed_text = "";
   
    {
        format_string = "%d/%d";
    }

    public ConditionKilledEnemies() {
        super("Killed", "%d/%d");
    }
   
    public void registerEnemy(Entity enemy) {
        //add enemy to list
        //add a entity listener that tracks the enemy death
        //and adds to the counter here
        ListenerEntityImpl listener = getListener(enemy);
        enemy.addEntityListener( listener);
        enemies.add(enemy);
        listeners.add(listener);
        size++;
        current_displayed_text = String.format(format_string, enemies.size(), size);
    }
   
    public ListenerEntityImpl getListener(Entity enemy) {
        return new ListenerEntityImpl() {

            @Override
            public void onDeath(EntityMobile object) {
                super.onDeath(object);
                int index = enemies.indexOf(object);
                if( index >= 0 ) {
                    enemies.remove(index);
                    listeners.remove(index);
                    current_displayed_text = String.format(format_string, enemies.size(), size);
                }
            }
        };
    }
   
    @Override
    public String getDisplayedText() {
        return current_displayed_text;
    }

    @Override
    public void checkState() {
        //success if the list is empty
        if( enemies.isEmpty() ) state = Objective.State.SUCCESS;
        else state = Objective.State.PENDING;
    }
   

Donnerstag, 23. Juni 2016

How to Make Leaving Your Comfort Zone a Habit

In an earlier article, I talked about how important it is to get out of your comfort zone. But how do you actually get out of it?

Before I start, it's important to keep in mind the following:
  1. If you want to achieve goals, you must acquire habits that help you accomplish them. 
  2. Nothing will change if you don't stop making excuses. If the time to make a change isn't now, then when?


These two things are essential in understanding what I'm about to tell you next.

"Getting out of your comfort zone" may be one goal in a larger chain of goals you have in mind.Once you achieve it, all other goals can be accomplished with greater ease. So how could a habit look like that helps you get off your lazy bumcheeks?


Find something...
  • that doesn't require a huge effort to start doing (highly accessible)
  • that pushes you to the limit, at your own discretion 
  • lets you explore and expand said limits.

Let me show you two of these habits I acquired:

  • Taking cold showers. Cold showers expand your blood vessels, thus giving your metabolism a rush of energy. They may help if you are struggling with making physical exercise a habit, too. The fact you are forcing yourself to cold water exposure is a perfect way to teach yourself to get out of your comfort zone (and defeat the "innere Schweinehund" - the "inner lazy skunk" - as we Germans say). If you shower everyday make it a habit! That being said, you don't have to jump right into cold water. What I do is to wash myself normally, then proceed with cold shower, gradually making the water colder - and remain in the shower for a maximum of two minutes. Next time I'd shower I will try to make it even colder, trying to push my own limits. Keep in mind that if you notice you start shivering or feel your limbs are getting numb, you should stop with the shower and get yourself warm as soon as possible. Push your limits, but never drive it too far!

  • Physical exercise. Similarly to taking cold showers, it fires up your metabolism. Besides it keeps you fit and healthy. To make exercise a habit, I started doing situps before going to shower in the evening. For me personally I choose a familiar environment for exercise (the bed in my room), which meant less effort for me to start doing it. You can do whatever exercise you feel most comfortable with, like stretch lessons, situps, yoga - simply chose the lesser evil ;). Just keep in mind that workout - if done wrong - can be damaging to your health (like kickboxing with limb weights on). So if in doubt, I highly recommend seeking professional advice.

With these two habits I am fostering I basically got used to getting out of my comfort zone. Slowly I am expanding this to other parts of my life. I must say it helped me getting to know the unknown called "discipline".


But beware: Do not ever think about slipping on any of these habits. If you don't have time for them now, you're not going to have time for them later - because you are more inclined to find an excuse for not doing them at all. Try to remember this: If you're not investing in good habits now, then when? 


What will remain if you lost everything you have? You. So invest in yourself. Because you are the most valuable asset you have.

Samstag, 18. Juni 2016

How to avoid bad Color Schemes

Notice: you may want to get Krita in order to follow the steps described below.

I've adviced a few indie programmers with their games already. And all of them had a common issue: color choice. Good old infamous programmer art. How do you get better at it?!


Now I could bombard you guys with dry color theory in this post. But eventually this is all just "theory" and not necessarily helpful for you in practice (especially if you lack the understanding for it).

So let's start off with applied color theory. I'll show you some pics while explaining the basic concepts, adapted to gamedev.



Contrast



Every picture can be minimized to black and white, right? You have hotspots here and there that attract your attention. You have dark areas that create contrast and can be used to create multiple effects in the audience (like emotion or tension).



In the above picture, there seems to be a dark blue cloud luring over what appears to be a yellow valley. Notice the white areas on the right and left top corners of the picture that surround the darker areas. The contrast of the cloud is rather prominent, creating a tense scenery. The tilted angle adds to the dramatic display.


Now the interesting thing about this is, that a lot of this can be applied to games. You want your enemies to stand out, peaceful items also needs to be highlighted (the white areas) and obstacles that cannot be passed (dark blue cloud). And then you have your environment, that balances out those two elements (yellow/purple valley).



You do not want to have a very similar contrast for your background and your walls, for example. Or all your backgrounds, obstacles and player in the same brightness of color. It will look mushy and they won't stand out, making your game look worse and harder to play.


Look at this picture here:


This looks like a ornamented floor, right? Let me show you what happens when I make the green tiles darker.



Now these tiles actually look more like walls that encase a tiny room. Darker. Impassable. Something you probably should not even bother messing around with!

Contrast is an important tool to set apart different elements in your game. If you have moving entities, they must be distinguishable from the rest of the environment.

Let's take a look at this screenshot of Sonic The Hedgehog (Genesis).



The overall environment is relatively bright, happy even. Yet the enemies are still easily to spot and distinguishable from the rest because they have a very strong color (red) that does not appear in the rest of the environment. Sonic himself has a different hue than the water, too.



Color


So much for contrast. How to choose the correct color?


You can choose colors using color wheels or similar provided by graphics programs. If you keep moving the color wheel towards cyan in Krita and pick one color every now and then, it's a very good starting point to figure out rough colors that fit.



Like this, I've chosen this color palette. Let's imagine I want these colors in my game. These aren't perfect, but definitely usable.

The color picture looks like this:



So let's apply the contrast lesson here. I put the color picture layer over the contrast the black and white contrast layer. Then I applied blend mode "Darken" in Krita on the color picture layer. You can download this file here, by the way!




So the result looks like this:


...which is a pretty solid color scheme to use for your game. To modify it, you can use the HSV tool of Krita to make further adjustments. Keep in mind you will have to readjust colors to the correct contrast if you do that. The second color of "player, enemies" is too similar to the first color of "backgrounds" and may make problems in a final game!




Getting Color Schemes


You don't have to do this process all the time. There are numerous websites and tools that help you chose a fitting color palette. One of these tools is paletton:



Another website that is very useful is www.colourlovers.com. It provides very handy, user-created palettes. The palettes displayed below are actually very interesting colors to use in a game already.





Choosing the right Color Scheme for your game


So how do you choose the correct coloring scheme for your game? 

It always depends what kind of game you are making and what kind of atmosphere, experience and emotion you want to create. Colors can be a very powerful tool to help achieve this, as they have a strong subconscious effect.

If you make a post-apocalyptic game, you should probably use pastel colors (colors without high saturation) - as long as it looks rotten and pale, you're good to go!
When making a horror game, you may want to do the same. Or you maybe want to use dark colors only, with red being the only brighter color.

But not only the colors themselves are important, but also the context they are perceived. If the gameplay makes it clear there is danger near, I will perceive a red-black color scheme differently than say, a blue-black. The cold, blue colors may even create a sense of despair!

In the picture below, I created a few color combinations and listed the words that came to my mind when looking at them.


You can do the same experiment by looking at other games, movies or art and asking yourself how what you see make you feel. That also helps you figuring out a good color mood for your own game.


I hope this article helped you figure out more about colors and color schemes! What are your favorite games in terms of colors and atmosphere?