Did some reading up on some of the various UI techniques, I'll hopefully have something to show for it tomorrow. I added some functionality to the window, it should automatically scale the window size to fit within whatever resolution you are using leaving room for the taskbar. Alt enter should work to make it full screen now, and esc will exit the window.
Here is the current code, which i cleaned up a bit:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace Airlands
{
public class CoreGame : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
GraphicsDevice device;
Matrix projectionMatrix;
float xValue = new float();
float yValue = new float();
Model hexTileModel;
Model mainTowerModel;
Airland focusAirland;
Airland testAirland;
Airland testAirland1;
Airland testAirland2;
List<Airland> airlandList = new List<Airland>();
private void SetUpCamera()
{
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 0.01f, 3000.0f);
}
private Model LoadModel(string assetName)
{
Model newModel = Content.Load<Model>(assetName);
return newModel;
}
private void DrawModel(Model currentModel, Vector3 currentModelLocation, Vector3 airlandLocation)
{
Matrix[] CurrentTransforms = new Matrix[currentModel.Bones.Count];
currentModel.CopyAbsoluteBoneTransformsTo(CurrentTransforms);
foreach (ModelMesh mesh in currentModel.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = (CurrentTransforms[mesh.ParentBone.Index]*Matrix.CreateRotationX (MathHelper.PiOver2)* (Matrix.CreateTranslation (currentModelLocation)*Matrix.CreateTranslation(airlandLocation))* focusAirland.airlandWorldMatrix);
effect.View = focusAirland.airlandViewMatrix;
effect.Projection = projectionMatrix;
effect.EnableDefaultLighting();
}
mesh.Draw();
}
}
public CoreGame()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
graphics.PreferredBackBufferWidth = graphics.GraphicsDevice.DisplayMode.Width;
graphics.PreferredBackBufferHeight = (graphics.GraphicsDevice.DisplayMode.Height - 64);
graphics.IsFullScreen = false;
graphics.ApplyChanges();
Window.Title = "Airlands";
Window.AllowUserResizing = false;
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
device = graphics.GraphicsDevice;
yValue = (float)Math.Sqrt(3);
xValue = 3;
SetUpCamera();
hexTileModel = LoadModel("Models\\HexTile");
mainTowerModel = LoadModel("Models\\MainTower");
testAirland = new Airland();
testAirland1 = new Airland();
testAirland2 = new Airland();
airlandList.Add(testAirland);
airlandList.Add(testAirland1);
airlandList.Add(testAirland2);
testAirland.GenerateAirland("player", (new Vector3(0, 0, 0)));
testAirland1.GenerateAirland("player1", (new Vector3(3*xValue, -1*yValue, -10)));
testAirland2.GenerateAirland("player2", (new Vector3(12 * xValue, 2 * yValue, -20)));
focusAirland = testAirland;
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
KeyboardState keyState = Keyboard.GetState();
if (keyState.IsKeyDown(Keys.Up))
focusAirland.xrotangle += 0.05f;
if (keyState.IsKeyDown(Keys.Down))
focusAirland.xrotangle -= 0.05f;
if (keyState.IsKeyDown(Keys.Left))
focusAirland.yrotangle -= 0.05f;
if (keyState.IsKeyDown(Keys.Right))
focusAirland.yrotangle += 0.05f;
if (keyState.IsKeyDown(Keys.Q))
focusAirland.zoomValue -= 0.15f;
if (keyState.IsKeyDown(Keys.A))
focusAirland.zoomValue += 0.15f;
if (keyState.IsKeyDown(Keys.Z))
focusAirland.SetZDestination(-10);
if (keyState.IsKeyDown(Keys.X))
focusAirland.SetZDestination(10);
if (keyState.IsKeyDown(Keys.W))
focusAirland = testAirland;
if (keyState.IsKeyDown(Keys.E))
focusAirland = testAirland1;
if (keyState.IsKeyDown(Keys.R))
focusAirland = testAirland2;
if (keyState.IsKeyDown(Keys.Escape))
this.Exit();
if (keyState.IsKeyDown(Keys.RightAlt))
{
if (keyState.IsKeyDown(Keys.Enter))
{
if (graphics.IsFullScreen == false)
graphics.IsFullScreen = true;
else graphics.IsFullScreen = false;
graphics.ApplyChanges();
}
}
foreach (Airland thisAirland in airlandList)
thisAirland.UpdateAirland();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
device.Clear(Color.CornflowerBlue);
foreach (Airland thisAirland in airlandList)
{
foreach (Vector3 tileLocation in thisAirland.tileLocationList)
DrawModel(hexTileModel, tileLocation, thisAirland.airlandLocation);
foreach (Vector3 structureLocation in thisAirland.structureLocationList)
DrawModel(mainTowerModel, structureLocation, thisAirland.airlandLocation);
}
base.Draw(gameTime);
}
}
}
and the Airland class code:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace Airlands
{
class Airland
{
string ownerName;
public Vector3 airlandLocation = new Vector3();
Vector3 sourceTile = new Vector3(0, 0, 0);
public List<Vector3> tileLocationList = new List<Vector3>();
public List<Vector3> structureLocationList = new List<Vector3>();
float x = 3;
float y = (float)(Math.Sqrt(3));
public float xrotangle;
public float yrotangle;
public float zoomValue;
public float destination = new float();
public Matrix airlandViewMatrix;
public Matrix airlandWorldMatrix;
public void UpdateAirland()
{
if (this.airlandLocation.Z > this.destination)
this.DecreaseAltitude();
if (this.airlandLocation.Z < this.destination)
this.IncreaseAltitude();
Vector3 xrotAxis = new Vector3(3 * this.xrotangle, this.xrotangle, 2 * this.xrotangle);
xrotAxis.Normalize();
Vector3 yrotAxis = new Vector3(3 * this.yrotangle, this.yrotangle, 2 * this.yrotangle);
yrotAxis.Normalize();
this.airlandViewMatrix = (Matrix.CreateLookAt(new Vector3(0, 0, this.zoomValue), new Vector3(0, 0, this.airlandLocation.Z), new Vector3(0, 1, 0)));
this.airlandWorldMatrix = ((Matrix.CreateTranslation((-this.airlandLocation)) * Matrix.CreateRotationZ(-this.yrotangle) * Matrix.CreateRotationX(this.xrotangle)));
}
public void AddTile(Vector3 tileLocation)
{
this.tileLocationList.Add(tileLocation);
}
public void AddStructure(Vector3 structureLocation)
{
this.structureLocationList.Add(structureLocation);
}
public void DecreaseAltitude()
{
this.airlandLocation.Z += -.02f;
}
public void IncreaseAltitude()
{
this.airlandLocation.Z += .02f;
}
public void SetZDestination(float zDestination)
{
this.destination = (this.airlandLocation.Z + zDestination);
}
public void GenerateAirland(string ownerName, Vector3 ingameLocation)
{
this.ownerName = ownerName;
this.airlandLocation = ingameLocation;
this.destination = ingameLocation.Z;
this.zoomValue = 20;
this.AddTile(sourceTile);
this.AddStructure(sourceTile);
this.AddStructure(new Vector3(-x, 3 * -y, 0));
this.AddTile(sourceTile + new Vector3(0, 2 * y, 0));
this.AddTile(new Vector3(x, y, 0));
this.AddTile(new Vector3(x, -y, 0));
this.AddTile(new Vector3(0, 2 * -y, 0));
this.AddTile(new Vector3(-x, -y, 0));
this.AddTile(new Vector3(-x, y, 0));
this.AddTile(new Vector3(-x, 3 * -y, 0));
}
}
}
I'm still teaching myself a lot of this so if anyone notices any glaring flaws in my code please point them out
I am going to be going for unit customization similar to Alpha Centauri, even though I hadn't realized it when i was doing the planning. How I would like the game to work is thusly:
you have a population
you have some of that population levied into your military. They can then train in the use of various types of equipment, becoming more adept over time. You will need to obtain the equipment that your military will be equipped with. Perhaps your friend has a great batch of iron he is making into high quality swords, he sends you a shipment of 100 of his latest batch, which you give to your soldiers. Local wildlife has been plentiful and you have a good deal of extra leather that you have been tanning. You are able to focus your population's efforts on turning those hides into leather armor, which being made by unskilled peasantry turn out rather poor quality, but better than nothing.
While it will have an effect on your army as swordsmen may be fairly balanced against other melee weapon types. My goal is such that there will never be a "wearing pink gives you +5 attack" scenario. I would rather have the player decide "well wearing pink is great against people wearing brown, even if those wearing green have an advantage against it.... hmm maybe i should stick with wearing a balanced color like orange." By fine tuning the way that the advantages and disadvantages spread, I think that it creates a system where armies are based around achieving a balance, while also creating a wide variety of troop types.
In battle the idea is going to be that your units will generally rout rather than be annihilated, so while you make suffer a defeat, your armies may lose men, but won't be annihilated like a general RTS.
I would like units of soldiers to have a wide variety of stats that are tracked, similarly to Civil War Generals 1 and 2, where each unit measured its level of organization, how bloodied they were, and its morale, which affected their capacity to fight, and willingness to follow orders. These were things that were affected by the skills of their commanding officer, and could be improved by resting the unit. (a good commander like sherman could reorganize his unit much better than a skill-less one)
I haven't plotted out what stats I would like to include and their effects, but I do have some ideas.
Currently in my mind docking is simply put, bumping into another airland. I've considered grapples, and how to catch someone, this will likely have a magical explanation, but there will be some sort of mechanic to ensure that you can engage in combat with a target that you want to attack even if they are aware that you are attacking ( ie i don't want people to just be able to move away from you at the same speed) And there will be a mechanic that allows for one player to retreat from the fight at the cost of losing tiles.
Once we get to the point of a working game i'll start looking at ports to mac and linux, if someone more familiar with these wants to do it before then i'd be more than happy to provide whatever data they need.