Posts Tagged ‘java’

Last games I made were all top-down, this had quite some advantages, for one you only need one set of animations/graphics for all directions and with an  isometric view, sprites can overlap.

I solved this in my code to seperate the static content from the dynamtic content (static vegetation, vs moving units/agents).  In my case there are less agents than vegetation. So I loop through the static objects and see what it’s y positions is. This makes sure you only have to sort your static objects once on their y position, and you’ll only have to keep track of the y position of your moving agents. Besides sorting agents on the same level, I’ve also got different Z levels for rendering, this what keeps the tree canopy above the trunk of tree with a higher Y value.

public void draw(Graphics graphics) throws SlickException 
{
 
 Iterator iter = agentViews.values().iterator();
 float agentY = 0;
 AgentView agView = null;
  // Get the first agent
 if(iter.hasNext())
 {
   agView = (AgentView) iter.next();
   agentY = agView.getModel().getY();
 }
 // Loop through all the static objects on the same level
 boolean processingAgents;
 for(AgentView vegView : vegetiationViewsL0) 
 {
 
 float y = vegView.getModel().getY();
 
 if(agView != null)
 {
    // As long as the y  of the static object is higher (so lower on the screen) it will draw it first
 if(y >= agentY )
 {
   vegView.draw(graphics);
 }
 else
 {
    // Else draw the agent and check if there are other agents with a higher y than the current static object
   agView.draw(graphics);

 processingAgents = true;
 while(processingAgents)
 {
   if(iter.hasNext())
   {
     agView = (AgentView)iter.next();
     agentY = agView.getModel().getY();
     if(agentY > y)
     {
       agView.draw(graphics);
     }
     else
     {
        processingAgents = false;
     } 
   }
   else
   {
     agView= null;
     processingAgents = false;
   } 
 }
 vegView.draw(graphics);
 //System.out.println("Tree" + y); 
 }
 }
 else
 {
 vegView.draw(graphics);
 }
 
 }

fhZLR3P

Battlelance 0.03

Posted: 2013/07/24 in Battlelance
Tags: , , ,

It´s been a while, but I´m still working on my Java projects. I had some concurrency issues on collections, which should be solved now (I hope), damn you multi-threading! I’ve added a new spawn for the dungeon master, the Kobold. A sly creature that lurkes in the shadows, good for ambushing pesky adventurers that are entering his lair. He’s also better at disabling traps then the skeleton, it takes a thief to catch a thief, right?

The changelog:

  • Fixed: Some concurency issues with multi-threading
  • Fixed: As DM selecting unit abilities could cause screen flashing
  •  ADD: Kobolts, spawn for DM for stealth and disabling player traps

I’m also working on a few bigger projects within Battlelance in the background:

  • AI for adventurers and DM
  • Inventory system
  • Character creation system

But those will probably take a very long time to finish and I’m in no hurry, so we’ll see how far I get with those 🙂

While testing I found some nasty bugs, most of these are addressed in this release. Please let me know if you find others, this is after all just an alpha version, if you can even call it that 🙂 And with help I can find and fix them.

  • Fixed: End turn bug, end turn didn’t register with all the clients
  • Fixed: Selection/action when somebody was standing on a trap
  • Fixed: Update vision when opening a door
  • Change: Movement/Actions have different labels
  • Fixed: Disable device label didn’t vanish after end turn
  • Fixed: Can’t run into a trap if somebody is already standing on it

After a few months of work I’m releasing an alpha version of the game for people to play.  It’s the core of the gameplay for you to check out. This is an early version so here are a few things that aren’t in yet:

  • Animations on characters
  • Sounds or music
  • Lots of dungeon master tools
  • And there might still be some bugs here and there

So what is in this version you ask?

  • Become a wizard and choose between a white, red and black wizard. Or become a thief, fighter or cleric
  • Play an entire party of 4 characters and control them all, or if you’re with more people you can split control between players
  • Play online, over LAN or PBEM
  • Play as a dungeon master and summon monsters out of the line of sight of the party
  • Play deathmatch games and take on other characters
  • There are currently 26 different player abilities (spells, weapons and skills) and this will increase in future version, perhaps with input from you
  • Particle effects for most abilities
  • Build on Java and opengl, so it should work on Windows, Linux and Mac (you might need to copy the native libraries from Battlelance\native\<platform> to Battlelance\native. On default Windows libraries will be loaded.

Installation
  1. Make sure you have Java 1.7 installed. Or download it here.
  2. Extract the Zip file anywhere.
  3. If you want to set your resolution other then default edit this in etc/game.properties (open with any texteditor)
  4. If you want to do a PBEM, you can set your SMTP server settings in the same file, so Battelance can automatically send your turn files.
  5. For Windows users, just run the Battlelance.bat file
  6. For Linux users run: java -Djava.library.path=”native/linux” -jar BattleLance.jar etc/game.properties
  7. Mac users run: java -Djava.library.path=”native/macosx” -jar BattleLance.jar etc/game.properties

And play! Do mind, this is a multiplayer game, there is no AI build in at this moment (this might be something for the future).

Have fun!

Burning skeletons alive! Or something...

Burning skeletons alive! Or something…

In this blog I don’t want to just ‘praise’ my games, but I would like to give some technical insights in how they technically work. Mind you, the solutions that I’m using are not in any way the perfect solution to certain problems. They work for my situation and if you’re looking to copying it, that’s fine but a different context might require a different solution.

Another warning, I’m neither a great writer nor is my first language English. So I might become a bit incoherent as I jump from one subject to another.

Today I want to talk about save games. There are different ways to implement saving/loading in your game. One way to do it is to save all the current agents (characters and other ingame objects), but this means you’ll have to save all the effects and the current state of them as well. Like an invisibility spell that wears off in one more turn.

Battlelance saves its games by first of all saving the initial setup, which is just an object with a few arrays to record per playable character the player ID, player name, class, team number and some game master attributes like spawns, traps and abilities. With this information and the map the game can be set to its start position.

Once the players start the game all kind of data is being transferred over the network, to make sure this all happens in the right order and no threads access the same resources at once, each event that the game receives (movement, damage, summons, end turn, etc. etc.) is being push into a queue and afterwards processed. I’ll go more into this in another blog about the multiplayer aspect of the game. Sufficient to say is that these events constitute the consequences off all the actions that have taken place. So if somebody attacks, only the damage (if any) that’s done is enough to reconstruct the events that have happened.

Once the event is processed it’s stored in a savegame queue and once the game is saved this entire queue with the initial setup, and by replaying each event in turn the game is progressed to the same state as before.

Here is a snipplet of code of how the Save game object is written to a file and how it’s retrieved.

public static void SaveGame(GameContainer container, ConcurrentLinkedQueue<Object> saveGame)
{
  try
  {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    SaveGame game = new SaveGame(saveGame, container.getInitialState(), container.getMap2(), container.getGameName());
    oos.writeObject(game);
    oos.flush();
    byte[] binary = baos.toByteArray();
    String text = Base64.encodeBase64String(binary);
    PrintWriter out = new PrintWriter("save/" + container.getGameName() + ".btl");
    out.println(text);
    out.flush();
    out.close();
  }
  catch (Exception e)
  {
    e.printStackTrace();
  }
}

public static SaveGame LoadGame(String file)
{
  try
  {
    String text = readFile(file);
    byte[] binary = Base64.decodeBase64(text);
    ByteArrayInputStream baos = new ByteArrayInputStream(binary);
    ObjectInputStream oos = new ObjectInputStream(baos);
    return (SaveGame)oos.readObject();
  }
  catch (Exception e)
  {
    e.printStackTrace();
  }
  return null;
 }