At the end of this week I can say game is almost finished!

Huzzah! Game as it should be is pretty much finished – well there is always something that can be added, improved or modified – but as far as I am considered Ā game should look like it looks atm.

Obviously, it needs final touches – tidying up GUI for instance.
and before handing it out I still need to improve zombies’ behavior, add some more animations, and most important implement behavior module into marines class.

but as I mentioned – I am pretty happy with what I have done.

Economic system is an interesting one.

We start with 500 coins, or whatever it is šŸ˜‰
then every 10 seconds we add x into the pull – where x is defined by 5*number of houses – number of marines. – I was thinking a bit about that and it seems to be a reasonable solution.
as well Limit system has been added – into economics manager class – to avoid negative values for income and other issues. our population limit is 5 times number of houses – note: scv is excluded. Yes, I know it is a bit weird but lets say SCV is not a human ;P

yes I know I haven’t done much this week but in my defense – I am sick and on Saturday I was in Dundee – Games in Scotland – pretty awesome event where teams such as Veemee, Codeplay or Digital Goldfish were presenting what are they doing and who they are looking for in terms of employment.
Some photos below:




We can buy stuff!

Finally I have prototyped pouching units system – it uses messaging system, however I am having weird bug, when I am getting more marines animation for them is speeding up. I am wondering if it is caused by using pointer to the animation.. well it shouldn’t, should it? to be fair animation system was designed for animating single instance of the object but still.. it should be flexible enough to handle that.

I haven’t tested that on buildings yet… – memo added šŸ™‚

the scenario is:
when single building is selected we can press “T” to train marines, atm. it is done instantly and target location for new “trained” unit is set to fixed location.

future improvements include:

  • developing training time
  • changeable spawn location
  • implement cost
  • as far as I am thinking about that game.. I need decent GUI!

there is loads to do.. argh.. damn you father time! why one day has only 24hrs?!

2D Zombieesh Continues

That was freaking remarkable week,

Meetings Meetings Meetings.

Apparently I have enough “clients” to open my own company. Yeah.. who could even thought about that? World is crazy.

anyway, this is not what post will be about.

What I want to show is today’s achievement. Zombeesh project šŸ™‚ – yes as you can see I have implemented sprites from Starcraft – still there is a lot to do – shadows, moving elements, etc but I need to create working prototype of a game in less than month.. and believe me it will be tough.. Group project, own company – planning, game development for xBox360 – yes on site We šŸ™‚ will be developing xBox game well I cannot tell much about it yet but nick name for a project is “Craft” – yeah I need work something better.. but that can wait. Back to the topic

  • I have managed to implement animations – but making them work is later issue.
  • GUI manager allows me to add text on a screen to any position – future development placing images and animations – can be shifted for later on.
  • SCV on a screen can buildĀ barracks in selected place, but to do that need to get there,
  • Small fix for approximationĀ error has been placed – SCV wasn’t moving to exact place, if it is close enough it/he (?) stops.

This weekend’s development plan – allow barracks to trainĀ Marines/Ghosts

I can select you!


yeah this red triangle means – I am selected.. I will be working on sprites manager over the weekend..
At least.. I have managed to select sprites inside of box described by start point and end point – both defined by mouse click and release.

Class probably will be improved in the future but now.. welcome to AddToSelected method

void PlayerManager::addEntityToSelected(POINT mouseBoxStart, POINT mouseBoxEnd){
  std::map::iterator iter = playersEntities.begin();
  for(; iter != playersEntities.end(); ++iter){
    if(mouseBoxStart.x> mouseBoxEnd.x){
      mouseBoxStart.x +=mouseBoxEnd.x;
      mouseBoxEnd.x = mouseBoxStart.x - mouseBoxEnd.x;
      mouseBoxStart.x -= mouseBoxEnd.x;
    }
    if(mouseBoxStart.y> mouseBoxEnd.y){
      mouseBoxStart.y +=mouseBoxEnd.y;
      mouseBoxEnd.y = mouseBoxStart.y - mouseBoxEnd.y;
      mouseBoxStart.y -= mouseBoxEnd.y;
    }
    bool collisionResult = false;
    if(mouseBoxStart.x < = iter->second->getPosition().x && iter->second->getPosition().x < = mouseBoxEnd.x){
      if(mouseBoxStart.y <= iter->second->getPosition().y && iter->second->getPosition().y < = mouseBoxEnd.y){
        collisionResult = true;
      }
    }
    //if point is inside square then add to selected
    if(collisionResult == true){
      playersSelectedEntities[iter->second->getID()] = iter->second;
    }
  }
}

idea of this method is to search player entities list.
let me explain

when program is adding new objects to the scene it is adding new entities. Entities can have tag/name simple if check at this stage can save a bit of CPU later on, when instead of searching through all entities on the map we are searching only list of players entities that are pointing to exact entity.

void PlayerManager::markSelected(ID3DXSprite* sprite){
  std::map::iterator iter = playersSelectedEntities.begin();
  for(; iter != playersSelectedEntities.end(); ++iter){
    D3DXVECTOR3 deltaPosition = iter->second->getPosition() - LevelManager::getOffset();
    sprite->Draw(texture, 0, 0, &deltaPosition, D3DCOLOR_XRGB(255,255,255));
  }
}

markSelected method is the one that needs little bit more brain storming on. At the moment I am keeping it in PlayerManager class.. which in my opinion is little bit weird.. but in my defense.. we want to mark “Players” selected entities.. don’t we?

Zombeesh back in 2D

After lately chat with my tutor I have to move back to 2D based game. – timeĀ pressureĀ and general overloading forced me to make thisĀ decision.
GDD must be finished by tomorrow – but shall not fear! I have some resources. I will borrow units tile set from star craft – come on zombies looks almost like infected marine

as well as terrain tiles – provided by Maniak – thanks man!

I am improving level manager so I will be able to deal with offsets and a stuff.. as far as now I have prototype and hopefully it will be ready in next couple hours.

// LevelManager.h

#pragma once

#ifndef LEVELMANAGER_H
#define LEVELMANAGER_H

[...]
#include "Level.h"

class LevelManager
{
private:
  //list of maps
  static std::map levels;
  static int currentLevelId;	
public:
  static LevelManager* instance;
  static void init();
  static void loadLevel(Level* level); // load level
  static void unloadLevel(Level* level); 
  static void registerLevel(Level* level); //add level to levels pool
  static Level* getLevel(int id) ;
  static D3DXVECTOR3 getOffset(); //gets offset off current map;

  LevelManager();
  ~LevelManager();
};
#endif
// LevelManager.cpp
#include "LevelManager.h"

int LevelManager::currentLevelId=-1; //no level
LevelManager* LevelManager::instance =0;
std::map LevelManager::levels = std::map();

LevelManager::LevelManager(){}

void LevelManager::init(){
  LevelManager::instance = new LevelManager();
}

LevelManager::~LevelManager(){
  if(!levels.empty()){
    std::map::iterator iter = levels.begin();
    for(; iter != levels.end(); ++iter){
      delete iter->second;
      iter->second = 0;
    }
    levels.clear();
  }
}

void LevelManager::loadLevel(Level* level){
  registerLevel(level);
  LevelManager::currentLevelId = levels.size();
}

void LevelManager::unloadLevel(Level* level){
  std::map::iterator iter = levels.find(level->getId());
  if(iter != levels.end())
    levels.erase(iter);
}

void LevelManager::registerLevel(Level* level){
  //get size of current levels list and increment by one
  int size = levels.size() + 1;
  levels[size]= level;
  level->setId(size);
}

//ok do I need to register all entitys into level? - I guess I do. need to double check that with Kevin
Level* LevelManager::getLevel(int id){
  std::map::iterator iter = levels.find(id);
  if(iter != levels.end()){
    return iter->second;
  }
  return 0;
}

D3DXVECTOR3 LevelManager::getOffset(){
  std::map::iterator iter = levels.find(currentLevelId);
  if(iter != levels.end())
    return iter->second->getOffset();
  return D3DXVECTOR3(0,0,0);
}

I see meshes everywhere!

Huzza!! I did it!

I have learned how to create a mesh from .x file format! – now I only need to apply picking and I am good to go!

// Mesh.h
#pragma once
#ifndef MESH_H
#define MESH_H

[...]

class Mesh
{
  friend class MeshInstance;
public:
  Mesh();
  ~Mesh();
  Mesh(LPCSTR fName, IDirect3DDevice9* dev);
  HRESULT Load(LPCSTR fName, IDirect3DDevice9* Dev);
  void Render();
  void Release();
private:
  IDirect3DDevice9* m_pDevice;
  ID3DXMesh* m_pMesh;
  std::vector m_textures;
  std::vector m_materials;
  D3DMATERIAL9 m_white;
};

class MeshInstance{
public: 
  MeshInstance();
  MeshInstance(Mesh* meshPtr);
  void Render();

  void SetMesh(Mesh* m) { m_pMesh = m;}
  void SetPosition(D3DXVECTOR3 p) { m_pos = p; }
  void SetRotation(D3DXVECTOR3 r) { m_rot = r; }
  void SetScale(D3DXVECTOR3 s) { m_sca = s; }

private:
  Mesh* m_pMesh;
  D3DXVECTOR3 m_pos, m_rot, m_sca;
};
#endif
// Mesh.cpp
#include "Mesh.h"

Mesh::Mesh(){
  m_pDevice = NULL;
  m_pMesh = NULL;
}

Mesh::Mesh(LPCSTR fName, IDirect3DDevice9* dev){
  m_pDevice = dev;
  m_pMesh = NULL;
  Load(fName, m_pDevice);
}

Mesh::~Mesh(){
  Release();
}

HRESULT Mesh::Load(LPCSTR fName, IDirect3DDevice9* dev){
  m_pDevice = dev;

  //Set m_white material
  m_white.Ambient = m_white.Specular = m_white.Diffuse  = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
  m_white.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
  m_white.Power = 1.0f;

  Release();

  //Load new m_pMesh
  ID3DXBuffer * adjacencyBfr = NULL;
  ID3DXBuffer * materialBfr = NULL;
  DWORD noMaterials = NULL;

  if(FAILED(D3DXLoadMeshFromX(fName, D3DXMESH_MANAGED, m_pDevice,	
			      &adjacencyBfr, &materialBfr, NULL, 
			      &noMaterials, &m_pMesh)))
    return E_FAIL;

  D3DXMATERIAL *mtrls = (D3DXMATERIAL*)materialBfr->GetBufferPointer();

  for(int i=0;i< (int)noMaterials;i++){
    m_materials.push_back(mtrls[i].MatD3D);

    if(mtrls[i].pTextureFilename != NULL){
      char textureFileName[90];
      strcpy(textureFileName, "meshes/");
      strcat(textureFileName, mtrls[i].pTextureFilename);
      IDirect3DTexture9 * newTexture = NULL;
      D3DXCreateTextureFromFile(m_pDevice, textureFileName, &newTexture);			
      m_textures.push_back(newTexture);
    }
    else m_textures.push_back(NULL);
  }

  m_pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE,
			   (DWORD*)adjacencyBfr->GetBufferPointer(), NULL, NULL, NULL);

  adjacencyBfr->Release();
  materialBfr->Release();

  return S_OK;
}

void Mesh::Render(){
  for(int i=0;i< (int)m_materials.size();i++) {	
    if(m_textures[i] != NULL)m_pDevice->SetMaterial(&m_white);
    else m_pDevice->SetMaterial(&m_materials[i]);
    m_pDevice->SetTexture(0,m_textures[i]);
    m_pMesh->DrawSubset(i);
  }
}

void Mesh::Release(){
  //Clear old mesh...
  if(m_pMesh != NULL){
    m_pMesh->Release();
    m_pMesh = NULL;
  }

  //Clear textures and materials
  for(int i=0;i< (int)m_textures.size();i++)
    if(m_textures[i] != NULL)
      m_textures[i]->Release();
    m_textures.clear();
}

MeshInstance::MeshInstance(){
  m_pMesh = NULL;
  m_pos = m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
}

MeshInstance::MeshInstance(Mesh* meshPtr){
  m_pMesh = meshPtr;
  m_pos = m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
}

void MeshInstance::Render(){
  if(m_pMesh != NULL){
    D3DXMATRIX p, r, s;
    D3DXMatrixTranslation(&p, m_pos.x, m_pos.y, m_pos.z);
    D3DXMatrixRotationYawPitchRoll(&r, m_rot.y, m_rot.x, m_rot.z);
    D3DXMatrixScaling(&s, m_sca.x, m_sca.y, m_sca.z);		
    D3DXMATRIX world = s * r * p;
    m_pMesh->m_pDevice->SetTransform(D3DTS_WORLD, &world);
    m_pMesh->Render();
  }
}
// ObjectClass.h
#ifndef OBJECTCLASS_H
#define OBJECTCLASS_H

[...]
#include "debug.h"
#include "mesh.h"

HRESULT LoadObjectResources(IDirect3DDevice9* Device);
void UnloadObjectResources();

#define OBJ_TREE 0
#define OBJ_STONE 1

class ObjectClass{
public:
  ObjectClass();
  ObjectClass(int t, D3DXVECTOR3 pos, D3DXVECTOR3 rot, D3DXVECTOR3 sca);
  void Render();

private:
  MeshInstance m_meshInstance;
  int m_type;
};
#endif
// ObjectClass.cpp
#include "ObjectClass.h"

std::vector objectMeshes;

HRESULT LoadObjectResources(IDirect3DDevice9* device){
  Mesh* one = new Mesh("meshes/one.x", device);
  objectMeshes.push_back(one);
  Mesh* two= new Mesh("meshes/two.x", device);
  objectMeshes.push_back(two);
  return S_OK;
}

void UnloadObjectResources(){
  for(int i=0; i< (int)objectMeshes.size(); i++)
    objectMeshes[i]->Release();
  objectMeshes.clear();
}

ObjectClass::ObjectClass(){
  m_type =0;
}

ObjectClass::ObjectClass(int t, D3DXVECTOR3 pos, D3DXVECTOR3 rot, D3DXVECTOR3 sca){
  m_type = t;
  m_meshInstance.SetPosition(pos);
  m_meshInstance.SetRotation(rot);
  m_meshInstance.SetScale(sca);
  m_meshInstance.SetMesh(objectMeshes[m_type]);
}

void ObjectClass::Render(){
  m_meshInstance.Render();
}

usage is really simple:

in our main program class game/application/app you name it.

we need to add include

#include "ObjectClass.h"

then in Init method for your program place

  LoadObjectResources(m_pDevice); 

it is loading resources do our device.

to add object call

  AddObject(0, INTPOINT(x, y));	//objec one
  else if(m_pHeightMap->GetHeight(x, y) >= 1.0f && hm3.GetHeight(x, y) > 0.9f && rand()%20 == 0)
    AddObject(1, INTPOINT(x, y));	//object two

I am calling it in terrain class.

at the moment placed randomly

void Terrain::AddObject(int type, INTPOINT mappos)
{
  D3DXVECTOR3 pos = D3DXVECTOR3((float)mappos.x, m_pHeightMap->GetHeight(mappos), (float)-mappos.y);	
  D3DXVECTOR3 rot = D3DXVECTOR3((rand()%1000 / 1000.0f) * 0.13f, (rand()%1000 / 1000.0f) * 3.0f, (rand()%1000 / 1000.0f) * 0.13f);

  float sca_xz = (rand()%1000 / 1000.0f) * 0.5f + 0.5f;
  float sca_y = (rand()%1000 / 1000.0f) * 1.0f + 0.5f;
  D3DXVECTOR3 sca = D3DXVECTOR3(sca_xz, sca_y, sca_xz);

  m_objects.push_back(ObjectClass(type, pos, rot, sca));
}

374 FPS not bad!