Noble Master Games
Noble Master Games
Navigation
Categories:

Search:

Meta:

Archives:
Reviews Forums Dev. Blog ⊕  

Noble Master Developer’s Blog

September 1, 2010

Age of Conquest: Editor – Beta Release!

Filed under: Announcement, Development — noblemaster @ 10:03 pm

A beta version of the Age of Conquest Map Editor has been released! The editor features the full map editing functionality. The editor also includes and a map upload & download system. Submit your creations now!

Visit the Age of Conquest Modding Discussions & Workshop forum on the Multiplayer Hub for download and information.

Age of Conquest Editor (beta)

Age of Conquest Editor (beta)

August 31, 2010

Star Rating Panel for Java Swing

Filed under: Development — noblemaster @ 9:32 am
Star Rating

Star Rating

I couldn’t find a good star rating component for Java Swing, so I rolled my own. The star rating component displays the current current rating (yellow stars), as well as a “selected” rating (reddish stars). The “selected” rating can be changed by a user. If the “selected” rating is changed, all the listeners will be notified of the change.

Example (5 stars, 3.78 average rating, 3 stars initial selection):

  StarRater starRater = new StarRater(5, 3.61, 3);
  starRater.addStarListener(new StarRater.StarListener() {
    public void handleSelection(int selection) {
      // a new number of stars has been selected
      do something...
    }
  });
  add(starRater);   // add the component to the container...

The star rating component will initially be used to rate maps in Age of Conquest.

Here is the download for both source code & star images (Photoshop). Note that I included the star images as byte array in the source code for your convenience. You are obviously free to use your own as well. Please consider both source code as well as images in the Public Domain. If you would like to credit me for the work that’s great, otherwise, no problem either:

August 24, 2010

King of the Hill for Age of Conquest

Filed under: Development — noblemaster @ 10:55 am
England Zone

England Zone

Age of Conquest will have a new game type available. King of the Hill will require a player or a team to hold a certain area on the map for a given time to win the game. Target flags will define the zone.

For additional suggestions, please post your ideas here in the blog!

August 19, 2010

Color Swatch & Color Selector for Java

Filed under: Development — noblemaster @ 3:44 pm
Color Swatch (Java)

Color Swatch (Java)

The color selector (JColorChooser) for Java is rather ugly, so I decided to write my own color chooser. The color chooser is made up of two components:

  • ColorSelector: A button which displays the currently selected color and pops up the ColorSwatch when clicked.
  • ColorSwatch:  Displays a color swatch with clickable colors. The color swatch expects a two-dimensional array of colors as input that will be displayed in the swatch.

The color selector and swatch will be used for Age of Conquest to make it more convenient to select a color in the map editor (less cumbersome). Please note, the five columns to the left are specifically designed colors for Age of Conquest to give maps a medieval look & feel. Although other colors can be chosen as well, it is recommended to use the medieval colors when creating new scenarios for the game.

Here is the code for both components. Please consider the code Public Domain. Feel free to use and modify it any way you please. Although, I would appreciate to be credited, it is not necessary to do so. Enjoy!

ColorSelector.java

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JPopupMenu;

/**
 * Represents a color selector.
 *
 * @author noblemaster
 * @since August 16, 2010
 */
public class ColorSelector extends JButton {

  /** The default colors. */
  private static final int[][] DEFAULT_COLORS = new int[][] {
      { 0xFFFFFF, 0xEEEEEE, 0xDDDDDD, 0xCCCCCC
       , 0xBBBBBB, 0xAAAAAA, 0xFFCC00, 0xFF9900
       , 0xFF6600, 0xFF3300, 0x999999, 0x888888
       , 0x666666, 0x444444, 0x222222, 0x000000 },
      { 0x99CC00, 0x000000, 0x000000, 0x000000
       , 0x000000, 0xCC9900, 0xFFCC33, 0xFFCC66
       , 0xFF9966, 0xFF6633, 0xCC3300, 0x000000
       , 0x000000, 0x000000, 0x000000, 0xCC0033 },
      { 0xCCFF00, 0xCCFF33, 0x333300, 0x666600
       , 0x999900, 0xCCCC00, 0xFFFF00, 0xCC9933
       , 0xCC6633, 0x330000, 0x660000, 0x990000
       , 0xCC0000, 0xFF0000, 0xFF3366, 0xFF0033 },
      { 0x99FF00, 0xCCFF66, 0x99CC33, 0x666633
       , 0x999933, 0xCCCC33, 0xFFFF33, 0x996600
       , 0x993300, 0x663333, 0x993333, 0xCC3333
       , 0xFF3333, 0xCC3366, 0xFF6699, 0xFF0066 },
      { 0x66FF00, 0x99FF66, 0x66CC33, 0x669900
       , 0x999966, 0xCCCC66, 0xFFFF66, 0x996633
       , 0x663300, 0x996666, 0xCC6666, 0xFF6666
       , 0x990033, 0xCC3399, 0xFF66CC, 0xFF0099 },
      { 0x33FF00, 0x66FF33, 0x339900, 0x66CC00
       , 0x99FF33, 0xCCCC99, 0xFFFF99, 0xCC9966
       , 0xCC6600, 0xCC9999, 0xFF9999, 0xFF3399
       , 0xCC0066, 0x990066, 0xFF33CC, 0xFF00CC },
      { 0x00CC00, 0x33CC00, 0x336600, 0x669933
       , 0x99CC66, 0xCCFF99, 0xFFFFCC, 0xFFCC99
       , 0xFF9933, 0xFFCCCC, 0xFF99CC, 0xCC6699
       , 0x993366, 0x660033, 0xCC0099, 0x330033 },
      { 0x33CC33, 0x66CC66, 0x00FF00, 0x33FF33
       , 0x66FF66, 0x99FF99, 0xCCFFCC, 0xFFFFE3
       , 0xFFFFFF, 0xFFE3FF, 0xCC99CC, 0x996699
       , 0x993399, 0x990099, 0x663366, 0x660066 },
      { 0x006600, 0x336633, 0x009900, 0x339933
       , 0x669966, 0x99CC99, 0xE3FFFF, 0xFFFFFF
       , 0xFFFFFF, 0xFFCCFF, 0xFF99FF, 0xFF66FF
       , 0xFF33FF, 0xFF00FF, 0xCC66CC, 0xCC33CC },
      { 0x003300, 0x00CC33, 0x006633, 0x339966
       , 0x66CC99, 0x99FFCC, 0xCCFFFF, 0x3399FF
       , 0x99CCFF, 0xCCCCFF, 0xCC99FF, 0x9966CC
       , 0x663399, 0x330066, 0x9900CC, 0xCC00CC },
      { 0x00FF33, 0x33FF66, 0x009933, 0x00CC66
       , 0x33FF99, 0x99FFFF, 0x99CCCC, 0x0066CC
       , 0x6699CC, 0x9999FF, 0x9999CC, 0x9933FF
       , 0x6600CC, 0x660099, 0xCC33FF, 0xCC00FF },
      { 0x00FF66, 0x66FF99, 0x33CC66, 0x009966
       , 0x66FFFF, 0x66CCCC, 0x669999, 0x003366
       , 0x336699, 0x6666FF, 0x6666CC, 0x666699
       , 0x330099, 0x9933CC, 0xCC66FF, 0x9900FF },
      { 0x00FF99, 0x66FFCC, 0x33CC99, 0x33FFFF
       , 0x33CCCC, 0x339999, 0x336666, 0x006699
       , 0x003399, 0x3333FF, 0x3333CC, 0x333399
       , 0x333366, 0x6633CC, 0x9966FF, 0x6600FF },
      { 0x00FFCC, 0x33FFCC, 0x00FFFF, 0x00CCCC
       , 0x009999, 0x006666, 0x003333, 0x3399CC
       , 0x3366CC, 0x0000FF, 0x0000CC, 0x000099
       , 0x000066, 0x000033, 0x6633FF, 0x3300FF },
      { 0x00CC99, 0x000000, 0x000000, 0x000000
       , 0x000000, 0x0099CC, 0x33CCFF, 0x66CCFF
       , 0x6699FF, 0x3366FF, 0x0033CC, 0x000000
       , 0x000000, 0x000000, 0x000000, 0x3300CC },
      { 0x000000, 0x222222, 0x444444, 0x666666
       , 0x888888, 0x999999, 0x00CCFF, 0x0099FF
       , 0x0066FF, 0x0033FF, 0xAAAAAA, 0xBBBBBB
       , 0xCCCCCC, 0xDDDDDD, 0xEEEEEE, 0xFFFFFF },
  };

  /** The rollover color. */
  private static final Color ROLLOVER_COLOR = new Color(0x20ffffff, true);

  /** The current color. */
  private Color color;
  /** The available colors. */
  private Color[][] colors;

  /**
   * The constructor.
   */
  public ColorSelector() {
    this(Color.RED, getDefaultColors());
  }

  /**
   * The constructor.
   *
   * @param color  The active color.
   * @param colors  The colors to select from.
   */
  public ColorSelector(Color color, Color[][] colors) {
    this.color = color;
    this.colors = colors;

    // set background
    setOpaque(false);

    // listen to clicks and display popup as needed
    addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent arg0) {
        // create and show swatch
        final JPopupMenu popup = new JPopupMenu();
        popup.setOpaque(false);
        ColorSwatch swatch = new ColorSwatch(ColorSelector.this.colors);
        swatch.addColorListener(new ColorSwatch.ColorListener() {
          public void handleColor(Color color) {
            // set the new color
            if (color != null) {
              ColorSelector.this.setColor(color);
            }

            // hide the popup
            popup.setVisible(false);
          }
        });
        popup.add(swatch);
        popup.show(ColorSelector.this, getWidth() / 2, getHeight() / 2);
      }
    });
  }

  /**
   * Returns the color.
   *
   * @return  The color.
   */
  public Color getColor() {
    return color;
  }

  /**
   * Sets the color.
   *
   * @param color  The color.
   */
  public void setColor(Color color) {
    this.color = color;
  }

  /**
   * Returns the colors.
   *
   * @return  The colors.
   */
  public Color[][] getColors() {
    return colors;
  }

  /**
   * Sets the colors.
   *
   * @param colors  The colors.
   */
  public void setColors(Color[][] colors) {
    this.colors = colors;
  }

  /**
   * Returns the base colors.
   *
   * @return  The base colors.
   */
  public static Color[][] getDefaultColors() {
    Color[][] colors = new Color[DEFAULT_COLORS.length][DEFAULT_COLORS[0].length];
    for (int y = 0; y < colors.length; y++) {
      for (int x = 0; x < colors[0].length; x++) {
        colors[y][x] = new Color(DEFAULT_COLORS[y][x]);
      }
    }
    return colors;
  }

  /**
   * Returns the preferred size.
   *
   * @return  The preferred size.
   */
  @Override
  public Dimension getPreferredSize() {
    return new Dimension(60, 30);
  }

  /**
   * Returns the margin.
   *
   * @return  The margin.
   */
  private int margin() {
    return 3;
  }

  /**
   * Draws this component.
   *
   * @param g  Where to draw to.
   */
  @Override
  public void paint(Graphics g) {
    // use antialiasing
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    int width = getWidth();
    int height = getHeight();
    int x = 0;
    int y = 0;
    int margin = margin();

    // draw border
    getBorder().paintBorder(this, g, 0, 0, width - 1, height - 1); 

    // draw the color
    g.setColor(color);
    g.fillRoundRect(x + margin, y + margin
                 , width - (2 * margin), height - (2 * margin), 5, 5);

    // draw effect as need
    ButtonModel model = getModel();
    if (model.isPressed()) {
      g.setColor(ROLLOVER_COLOR);
      g.fillRoundRect(x + margin, y + margin
                 , width - (2 * margin), height - (2 * margin), 5, 5);
      g.fillRoundRect(x + margin, y + margin
                , width - (2 * margin), height - (2 * margin), 5, 5);
    }
    else if (model.isRollover()) {
      g.setColor(ROLLOVER_COLOR);
      g.fillRoundRect(x + margin, y + margin
               , width - (2 * margin), height - (2 * margin), 5, 5);
    }
  }
}

ColorSwatch.java:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.event.MouseInputListener;

/**
 * Displays a color swatch.
 *
 * @author noblemaster
 * @since August 16, 2010
 */
public class ColorSwatch extends JPanel {

  /** The rollover color. */
  private static final Color ROLLOVER_COLOR = new Color(0x80ffffff, true);

  /** The listener. */
  public static interface ColorListener {

    /**
     * Called if a color has been activated.
     *
     * @param color  The color.
     */
    void handleColor(Color color);
  }

  /** The listeners. */
  private transient List
 listeners = new ArrayList();

  /** The colors. */
  private Color[][] colors;

  /** The rollover color. */
  private Color rolloverColor = null;

  /**
   * The constructor.
   */
  public ColorSwatch() {
    this(new Color[0][0]);
  }

  /**
   * The constructor.
   *
   * @param colors  The colors to select from.
   */
  public ColorSwatch(Color[][] colors) {
    this.colors = colors;

    // set look
    setOpaque(true);
    setBackground(Color.WHITE);
    setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));

    // add listener
    MouseInputListener mouseListener = new MouseInputListener() {
      public void mousePressed(MouseEvent event) {
        Color color = getColor(event.getX(), event.getY());

        // notify about selection
        for (int i = 0; i < listeners.size(); i++) {
          listeners.get(i).handleColor(color);
        }
      }
      public void mouseMoved(MouseEvent event) {
        rolloverColor = getColor(event.getX(), event.getY());
        repaint();
      }
      public void mouseDragged(MouseEvent event) {
        // not used
      }
      public void mouseReleased(MouseEvent event) {
        // not used
      }
      public void mouseClicked(MouseEvent arg0) {
        // not used
      }
      public void mouseEntered(MouseEvent arg0) {
        // not used
      }
      public void mouseExited(MouseEvent arg0) {
        rolloverColor = null;
        repaint();
      }
    };
    addMouseListener(mouseListener);
    addMouseMotionListener(mouseListener);
  }

  /**
   * Returns the colors.
   *
   * @return  The colors.
   */
  public Color[][] getColors() {
    return colors;
  }

  /**
   * Sets the colors.
   *
   * @param colors  The colors.
   */
  public void setColors(Color[][] colors) {
    this.colors = colors;
  }

  /**
   * Returns the preferred size.
   *
   * @return  The preferred size.
   */
  @Override
  public Dimension getPreferredSize() {
    int colorSize = getColorSize();
    int colorSpacing = getColorSpacing();
    int margin = getMargin();
    return new Dimension((colorSize + colorSpacing) * colors[0].length
                              + (2 * margin) - colorSpacing
                       , (colorSize + colorSpacing) * colors.length
                              + (2 * margin) - colorSpacing);
  }

  /**
   * Returns the margin/insets from where the colors are painted. Override this method to paint the colors
   * further inside.
   *
   * @return  The margin.
   */
  public int getMargin() {
    return 2;
  }

  /**
   * Returns the color for the given coordinate.
   *
   * @param x  The x coordinate.
   * @param y  The y coordinate.
   * @return  The color or null if not found.
   */
  private Color getColor(int x, int y) {
    int margin = getMargin();
    int colorSize = getColorSize();
    int colorSpacing = getColorSpacing();
    x -= margin;
    y -= margin;
    int col = x / (colorSize + colorSpacing);
    int row = y / (colorSize + colorSpacing);
    if ((col < 0) || (col >= colors[0].length) || (row < 0)
                       || (row >= colors.length)) {
      return null;
    }
    else {
      return colors[row][col];
    }
  }

  /**
   * Returns the spacing.
   *
   * @return  The spacing.
   */
  private int getColorSpacing() {
    return getColorSize() > 2 ? 1 : 0;
  }

  /**
   * Returns the size of a color thingy.
   *
   * @return  The color size in pixels.
   */
  private int getColorSize() {
    if ((colors[0].length <= 12) && (colors.length <= 8)) {
      return 15;
    }
    else if ((colors[0].length <= 24) && (colors.length <= 16)) {
      return 7;
    }
    else if ((colors[0].length <= 48) && (colors.length <= 32)) {
      return 5;
    }
    else if ((colors[0].length <= 96) && (colors.length <= 64)) {
      return 3;
    }
    else {
      return 1;
    }
  }

  /**
   * Draws this component.
   *
   * @param g  Where to draw to.
   */
  @Override
  protected void paintComponent(Graphics g) {
    // use antialiasing
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    int width = getWidth();
    int height = getHeight();
    int margin = getMargin();
    int colorSize = getColorSize();
    int colorSpacing = getColorSpacing();

    // background fill
    g.setColor(getBackground());
    g.fillRect(0, 0, width, height);

    // draw the colors
    for (int y = 0; y < colors.length; y++) {
      for (int x = 0; x < colors[0].length; x++) {         Color color = colors[y][x];         g.setColor(color);         g.fillRect(x * (colorSize + colorSpacing) + margin                  , y * (colorSize + colorSpacing) + margin                  , colorSize                  , colorSize);                  // draw rollover?         if (colorSpacing > 0) {
          if (color == rolloverColor) {
            g.setColor(ROLLOVER_COLOR);
            g.fillRect(x * (colorSize + colorSpacing) + margin
                , y * (colorSize + colorSpacing) + margin
                , colorSize
                , colorSize);
          }
        }
      }
    }
  }

  /**
   * Adds a listener.
   *
   * @param listener  The listener.
   */
  public void addColorListener(ColorListener listener) {
    listeners.add(listener);
  }

  /**
   * Removes a listener.
   *
   * @param listener  The listener.
   */
  public void removeColorListener(ColorListener listener) {
    listeners.remove(listener);
  }
}

August 13, 2010

GUI Components: Slider + Progress Bar

Filed under: Development — noblemaster @ 2:21 pm
Slider and Progress Bar

Slider and Progress Bar

Age of Conquest III will feature two new GUI components: slider and progress bar. Both components have been designed by Sergey “Serjio” Churbanov who created most other graphics for Age of Conquest III as well.

August 11, 2010

Splash Screen – Noble Master

Filed under: Development — noblemaster @ 8:56 am

Spent some time creating a splash screen…

Animated Splash Screen (Noble Master)

Splash Screen (Noble Master)

July 29, 2010

Age of Conquest: Income & Expenses

Filed under: Development — noblemaster @ 10:38 am

Due to numerous requests, below is a description of income & expenses in Age of Conquest III. The system is up and running on Android already and will come to PC, Macintosh & Linux soon.

The income and expenses for each turn are calculated as follows:

World world = ... // the world including everything
Entity entity = ... // the empire we are doing the calculations for

// assets
long money = entity.getMoney();

// income: tax
long taxIncome = getTaxIncome(world.getProduction(entity),
                              entity.getTaxRate(),
                              entity.getMorale());
money += taxIncome;

// income: vassals
for (Entity vassal: vassals) {
  long vassalIncome = getTaxIncome(world.getProduction(vassal),
                                   vassal.getTaxRate(),
                                   vassal.getMorale());
  money += getVassalPay(taxIncome);
}

// expenses: economy and military spending
money -= getEconomySpending(taxIncome, entity.getSpendingEconomy()));
money -= getMilitarySpending(world.getMilitary(entity),
                             entity.getSpendingMilitary()));

// expenses: tributes to vassal masters
for (Entity master: masters) {
  money -= getVassalPay(taxIncome);
}

Please note, production is a factor of economy x population.

Utility functions to calculate costs as well as economy, population and military increases/decreases depending on the spending settings chosen.

  /** The percent the vassal pays. */
  public static final int VASSAL_PAY_PERCENTAGE = 10;

  /** The standard economy spending in percent [0, 100]. */
  public static final int STANDARD_SPENDING_ECONOMY = 80;
  /** The standard military spending in percent [0, 100]. */
  public static final int STANDARD_SPENDING_MILITARY = 80;

  /**
   * Returns the tax for the given number of people.
   *
   * @param production  The production.
   * @param taxRate  The tax rate in percent [0, 100].
   * @param morale  The morale in percent [0, 100].
   * @return  The tax.
   */
  public long getTaxIncome(long production, int taxRate, int morale) {
    return Math.round(Math.pow(production * 0.08d, 0.96d) * taxRate/10*morale/100);
  }

  /**
   * Returns the payment a vassal slave has to pay to
   * his master based on his production.
   *
   * @param taxIncome  The tax income of the vassal slave.
   * @return  The pay a vassal slave has to pay to his master.
   */
  public long getVassalPay(long taxIncome) {
    return taxIncome * VASSAL_PAY_PERCENTAGE / 100;
  }

  /**
   * Returns the investment spending for the given tax income.
   *
   * @param taxIncome  The tax income.
   * @param economySpending  The economy spending.
   * @return  The expenses.
   */
  public long getEconomySpending(long taxIncome, int economySpending) {
    return (taxIncome / 10) * economySpending / STANDARD_SPENDING_ECONOMY;
  }

  /**
   * Returns the economy increase for the given spending rate.
   *
   * @param economySpending  The spending.
   * @return  The increase factor. Stays stable for 1, decreases
   * or less than 1 and increases for more than 1.
   */
  public float getEconomyIncrease(int economySpending) {
    return 1.03f + ((economySpending - Market.STANDARD_SPENDING_ECONOMY) * 0.03f / 100);
  }

  /**
   * Returns the population increase for the given spending rate.
   *
   * @param economySpending  The spending.
   * @return  The increase factor. Stays stable for 1, decreases
   * for less than 1 and increases for more than 1.
   */
  public float getPopulationIncrease(int economySpending) {
    return 1.01f + (economySpending * 0.001f);
  }

  /**
   * Returns the upkeep cost for the given number of military units.
   *
   * @param military  The military units.
   * @param militarySpending  The military spending.
   * @return  The upkeep cost.
   */
  public long getMilitarySpending(long military, int militarySpending) {
    return (military / 5) * militarySpending / STANDARD_SPENDING_MILITARY;
  }

  /**
   * Returns the military increase for the given spending rate.
   *
   * @param militarySpending  The spending.
   * @return  The increase factor. Stays stable for 1, decreases
   * for less than 1 and increases for more than 1.
   */
  public float getMilitaryIncrease(int militarySpending) {
    return 1.0f + ((militarySpending - Market.STANDARD_SPENDING_MILITARY) * 0.5f / 100);
  }

Age of Conquest: Menu Screen

Filed under: Development — noblemaster @ 9:33 am

Looks like I am done a lot earlier than anticipated! I uploaded Age of Conquest Lite with iPad support yesterday night to the iTunes store for review. Shouldn’t be long until it is approved (or rejected). I will release “World Conquest” featuring the world map thereafter.

Find below the menu screen layout for the single player version of the game:

Age of Conquest: Menu Screen

July 28, 2010

Latest Screenshots for AoC Version III

Filed under: Development — noblemaster @ 10:01 am

Age of Conquest III for iPad is close to completion. It should take about one week of development, then one or more weeks to get the application approved in the Apple iTunes store. Age of Conquest Lite (map of Europe) will be upgraded first to give existing users the chance to play the game not only on iPod Touch and iPhone but also on the iPad. The world map will be released thereafter.

See below for current development screenshots for the iPad version (World Conquest). Please note, this is the medium-sized world map. The full-size world map will be available on desktop (PC, Mac, Linux) only due to memory limitations.

Age of Conquest III - Screenshot 1

Age of Conquest III - Screenshot 2

July 13, 2010

Age of Conquest Progress Report

Filed under: Development — noblemaster @ 1:11 pm

Battle!

After taking things easy for a few weeks, I am ready to re-start game development for Age of Conquest. I just received another set of graphics from the artist (Sergey). This is the final batch including about 30 icons.

I already started developing the various iPad screens. All that was missing were the graphics. Now, that I received the final batch from Sergey, I should be able to bring iPad development to a close within the next 4-6 weeks. After that, the desktop (PC, Macintosh & Linux) version is up next. I should be able to get the desktop version (single player) ready before December.

June 30, 2010

Winner’s Podium for Age of Conquest III

Filed under: Development — noblemaster @ 1:40 am

Things for Age of Conquest III are progressing slowly. I am currently waiting for all the graphics to come in to finally get started with full-time development on the next installment of Age of Conquest for PC, Macintosh & Linux computers.

See below for the latest graphics (Winner’s Podium).

Age of Conquest Winner's Podium

June 16, 2010

Pandemic Wars Prototype

Filed under: Development — noblemaster @ 2:40 am

Below a first prototype for Pandemic Wars. The goal is to spread a disease by changing the disease parameters including infectivity, mortality, restistance, transmission modi etc. Or optionally, the goal could be to stop the spread of a disease. It will be possible to have more than one disease at the same time battling for ultimate annihilation.

Please provide feedback!

May 31, 2010

User Interface DRAFT

Filed under: Development — noblemaster @ 9:18 pm

Below is an early draft for the user interface for the menu screens in Age of Conquest III. It’s still a work in progress, so things will be moved around/adjusted as needed.

User Inferface DRAFT - Age of Conquest

May 28, 2010

Age of Conquest III: Empire Screen

Filed under: Development — noblemaster @ 2:46 am

Age of Conquest Version III will have a slightly modified tax and spending screen compare to Version II. The new empire adjustment screen will allow adjusting tax rate and both military and economy spending.

  • Tax Rate: The tax rate affects morale. A tax rate of 10% will keep morale stable. Morale is a multiplier for tax income. Keeping the tax rate low, will increase morale and yield to a higher income in the future. Keeping the tax rate high will allow for short-term tax income gains, but reduce tax income in the future due to lowered morale.
  • Economy: Economy spending can be used to grow both population and economy each turn.
  • Military: Military spending of 80% will keep the number of military units stable. Increasing the spending will grow military units on all the provinces each turn. Decreased spending will do the opposite.

The empire screen is optional for all games and can be disabled as needed.

Empire Adjustment Screen

May 21, 2010

Map Modding: Nice Province Borders

Filed under: Development — noblemaster @ 3:13 pm

This is a Photoshop tutorial on how to create nice-looking 3D borders for map provinces. The instructions are actually quite simple as long as you keep borders in a separate layer.

  1. Make sure all the borders are located in a separate Photoshop layer. The border lines are preferably black and 1px wide. Please note that the Age of Conquest Map Editor can export all the border lines automatically. Otherwise, use either the Photoshop brush or line tool to draw the border lines beforehand.
  2. Follow the instructions below and edit the border layer properties to enhance the look of the border lines.

Please note that the guidelines will work as well in other graphics tools such Gimp (free).

Border Line Enhancement /w Photoshop

May 19, 2010

Age of Conquest in Taiwan

Filed under: Development — noblemaster @ 9:19 am

S Mart Logo

Age of Conquest has been released in the S Mart Store in Taiwan for Android devices. The game has been translated to Chinese by my friend Alex.

I was going to post a direct link to the game in the store, unfortunately that is not possible as the site only uses HTTP POST to link pages. To find the game, click on the 3rd tab from the left and then select the bottommost item in the 2nd menu list on the left-hand side.

Store URL: http://www.smartapp.tw

Translator: Kin “The Dog” Wang a.k.a. Alex

Age of Conquest on SmartApp.tw

May 17, 2010

Anniversary: 10 Year of Age of Conquest

Filed under: Announcement, Business, Development — noblemaster @ 8:33 am

Age of Conquest

It’s May 17, 2010 – It’s the 10 year anniversary of Age of Conquest. The game started its humble origins ten years ago to the day (yes, I checked the database). Age of Conquest has been online most of the time since 2000 and managed to obtain a small group of followers over the years. The game has been ported to Windows, Macintosh, Linux, iPhone/iPod as well as Android.

The following releases have been slated for the upcoming months:

  • Age of Conquest World Map Edition for iPad: This is a large size map featuring all the continents of Earth.
  • Age of Conquest III for PC, Mac, Linux: This includes both a single player version of the game as well as an online version.

May 13, 2010

World Map Preview

Filed under: Development — noblemaster @ 9:05 am

Another world map preview which includes the latest unit and structure graphics for Age of Conquest III. The map is scheduled for release on iPad, iPhone and iPod Touch next.

Graphics:  Robert Altbauer
Map & Modding: Travis Bowling

World Map Preview (Age of Conquest)

May 11, 2010

Old vs New (AoC Graphics)

Filed under: Development — noblemaster @ 8:01 pm

I am staring at it for too long. Do the new graphics make a difference or is it better to keep the status quo?

Old vs New Graphics (Age of Conquest)

May 3, 2010

Live Coding Session

Filed under: Announcement, Development — noblemaster @ 11:02 am

So, I am going to do a live screencast of a coding session for Age of Conquest. I have initially looked into LiveStream but I am not impressed with the quality of the live video feed. Instead, I’ll use Microsoft SharedView. The application is free, so simply download and install it. I’ll post the session name and password when I start the session.

The session is scheduled for:

Thursday, May 6, 18:30pm – around mignight
Time Zone: Hawaii, GMT-10
Download & Install: SharedView
Session Name & Password: Live NOW (May 6, 18:30)

LiveStream Screenshot:

LiveStream Screenshot

Older Posts »
Age of Conquest - Online Multiplayer Strategy Game