initial version ( megaglest 3.2.3-beta3 )
This commit is contained in:
commit
0ce9b5fcac
|
@ -0,0 +1,391 @@
|
|||
#include "configuration.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "xml/xml_parser.h"
|
||||
#include "util/util.h"
|
||||
#include "util/properties.h"
|
||||
#include "util/conversion.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Xml;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Configurator{
|
||||
|
||||
// ===============================================
|
||||
// class Configuration
|
||||
// ===============================================
|
||||
|
||||
Configuration::~Configuration(){
|
||||
for(int i= 0; i<fieldGroups.size(); ++i){
|
||||
delete fieldGroups[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Configuration::load(const string &path){
|
||||
loadStructure(path);
|
||||
loadValues(fileName);
|
||||
}
|
||||
|
||||
void Configuration::loadStructure(const string &path){
|
||||
|
||||
XmlTree xmlTree;
|
||||
xmlTree.load(path);
|
||||
|
||||
const XmlNode *configurationNode= xmlTree.getRootNode();
|
||||
|
||||
//title
|
||||
title= configurationNode->getChild("title")->getAttribute("value")->getValue();
|
||||
|
||||
//fileName
|
||||
fileName= configurationNode->getChild("file-name")->getAttribute("value")->getValue();
|
||||
|
||||
//icon
|
||||
XmlNode *iconNode= configurationNode->getChild("icon");
|
||||
icon= iconNode->getAttribute("value")->getBoolValue();
|
||||
if(icon){
|
||||
iconPath= iconNode->getAttribute("path")->getValue();
|
||||
}
|
||||
|
||||
const XmlNode *fieldGroupsNode= configurationNode->getChild("field-groups");
|
||||
|
||||
fieldGroups.resize(fieldGroupsNode->getChildCount());
|
||||
|
||||
for(int i=0; i<fieldGroups.size(); ++i){
|
||||
const XmlNode *fieldGroupNode= fieldGroupsNode->getChild("field-group", i);
|
||||
FieldGroup *fieldGroup= new FieldGroup();
|
||||
fieldGroup->load(fieldGroupNode);
|
||||
fieldGroups[i]= fieldGroup;
|
||||
}
|
||||
}
|
||||
|
||||
void Configuration::loadValues(const string &path){
|
||||
Properties properties;
|
||||
|
||||
properties.load(path);
|
||||
|
||||
for(int i=0; i<fieldGroups.size(); ++i){
|
||||
FieldGroup *fg= fieldGroups[i];
|
||||
for(int j=0; j<fg->getFieldCount(); ++j){
|
||||
Field *f= fg->getField(j);
|
||||
f->setValue(properties.getString(f->getVariableName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Configuration::save(){
|
||||
Properties properties;
|
||||
|
||||
properties.load(fileName);
|
||||
|
||||
for(int i=0; i<fieldGroups.size(); ++i){
|
||||
FieldGroup *fg= fieldGroups[i];
|
||||
for(int j=0; j<fg->getFieldCount(); ++j){
|
||||
Field *f= fg->getField(j);
|
||||
f->updateValue();
|
||||
if(!f->isValueValid(f->getValue())){
|
||||
f->setValue(f->getDefaultValue());
|
||||
f->updateControl();
|
||||
}
|
||||
properties.setString(f->getVariableName(), f->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
properties.save(fileName);
|
||||
}
|
||||
|
||||
string Field::getInfo() const{
|
||||
return name+" (default: " + defaultValue + ")";
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class FieldGroup
|
||||
// ===============================================
|
||||
|
||||
FieldGroup::~FieldGroup(){
|
||||
for(int i= 0; i<fields.size(); ++i){
|
||||
delete fields[i];
|
||||
}
|
||||
}
|
||||
|
||||
void FieldGroup::load(const XmlNode *groupNode){
|
||||
|
||||
name= groupNode->getAttribute("name")->getValue();
|
||||
|
||||
fields.resize(groupNode->getChildCount());
|
||||
for(int i=0; i<fields.size(); ++i){
|
||||
const XmlNode *fieldNode= groupNode->getChild("field", i);
|
||||
|
||||
Field *f= newField(fieldNode->getAttribute("type")->getValue());
|
||||
|
||||
//name
|
||||
const XmlNode *nameNode= fieldNode->getChild("name");
|
||||
f->setName(nameNode->getAttribute("value")->getValue());
|
||||
|
||||
//variableName
|
||||
const XmlNode *variableNameNode= fieldNode->getChild("variable-name");
|
||||
f->setVariableName(variableNameNode->getAttribute("value")->getValue());
|
||||
|
||||
//description
|
||||
const XmlNode *descriptionNode= fieldNode->getChild("description");
|
||||
f->setDescription(descriptionNode->getAttribute("value")->getValue());
|
||||
|
||||
//default
|
||||
const XmlNode *defaultNode= fieldNode->getChild("default");
|
||||
f->setDefaultValue(defaultNode->getAttribute("value")->getValue());
|
||||
|
||||
f->loadSpecific(fieldNode);
|
||||
|
||||
if(!f->isValueValid(f->getDefaultValue())){
|
||||
throw runtime_error("Default value not valid in field: " + f->getName());
|
||||
}
|
||||
|
||||
fields[i]= f;
|
||||
}
|
||||
}
|
||||
|
||||
Field *FieldGroup::newField(const string &type){
|
||||
if(type=="Bool"){
|
||||
return new BoolField();
|
||||
}
|
||||
else if(type=="Int"){
|
||||
return new IntField();
|
||||
}
|
||||
else if(type=="Float"){
|
||||
return new FloatField();
|
||||
}
|
||||
else if(type=="String"){
|
||||
return new StringField();
|
||||
}
|
||||
else if(type=="Enum"){
|
||||
return new EnumField();
|
||||
}
|
||||
else if(type=="IntRange"){
|
||||
return new IntRangeField();
|
||||
}
|
||||
else if(type=="FloatRange"){
|
||||
return new FloatRangeField();
|
||||
}
|
||||
else{
|
||||
throw runtime_error("Unknown field type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class BoolField
|
||||
// ===============================================
|
||||
|
||||
void BoolField::createControl(wxWindow *parent, wxSizer *sizer){
|
||||
checkBox= new wxCheckBox(parent, -1, "");
|
||||
checkBox->SetValue(strToBool(value));
|
||||
sizer->Add(checkBox);
|
||||
}
|
||||
|
||||
void BoolField::updateValue(){
|
||||
value= boolToStr(checkBox->GetValue());
|
||||
}
|
||||
|
||||
void BoolField::updateControl(){
|
||||
checkBox->SetValue(strToBool(value));
|
||||
}
|
||||
|
||||
bool BoolField::isValueValid(const string &value){
|
||||
try{
|
||||
strToBool(value);
|
||||
}
|
||||
catch(const exception &){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class IntField
|
||||
// ===============================================
|
||||
|
||||
void IntField::createControl(wxWindow *parent, wxSizer *sizer){
|
||||
textCtrl= new wxTextCtrl(parent, -1, value.c_str());
|
||||
sizer->Add(textCtrl);
|
||||
}
|
||||
|
||||
void IntField::updateValue(){
|
||||
value= textCtrl->GetValue();
|
||||
}
|
||||
|
||||
void IntField::updateControl(){
|
||||
textCtrl->SetValue(value.c_str());
|
||||
}
|
||||
|
||||
bool IntField::isValueValid(const string &value){
|
||||
try{
|
||||
strToInt(value);
|
||||
}
|
||||
catch(const exception &){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class FloatField
|
||||
// ===============================================
|
||||
|
||||
void FloatField::createControl(wxWindow *parent, wxSizer *sizer){
|
||||
textCtrl= new wxTextCtrl(parent, -1, value.c_str());
|
||||
sizer->Add(textCtrl);
|
||||
}
|
||||
|
||||
void FloatField::updateValue(){
|
||||
value= textCtrl->GetValue();
|
||||
}
|
||||
|
||||
void FloatField::updateControl(){
|
||||
textCtrl->SetValue(value.c_str());
|
||||
}
|
||||
|
||||
bool FloatField::isValueValid(const string &value){
|
||||
try{
|
||||
strToFloat(value);
|
||||
}
|
||||
catch(const exception &){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class StringField
|
||||
// ===============================================
|
||||
|
||||
void StringField::createControl(wxWindow *parent, wxSizer *sizer){
|
||||
textCtrl= new wxTextCtrl(parent, -1, value.c_str());
|
||||
textCtrl->SetSize(wxSize(3*textCtrl->GetSize().x/2, textCtrl->GetSize().y));
|
||||
sizer->Add(textCtrl);
|
||||
}
|
||||
|
||||
void StringField::updateValue(){
|
||||
value= textCtrl->GetValue();
|
||||
}
|
||||
|
||||
void StringField::updateControl(){
|
||||
textCtrl->SetValue(value.c_str());
|
||||
}
|
||||
|
||||
bool StringField::isValueValid(const string &value){
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class EnumField
|
||||
// ===============================================
|
||||
|
||||
void EnumField::createControl(wxWindow *parent, wxSizer *sizer){
|
||||
comboBox= new wxComboBox(parent, -1, "", wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
|
||||
for(int i=0; i<enumerants.size(); ++i){
|
||||
comboBox->Append(enumerants[i].c_str());
|
||||
}
|
||||
comboBox->SetValue(value.c_str());
|
||||
sizer->Add(comboBox);
|
||||
}
|
||||
|
||||
void EnumField::updateValue(){
|
||||
value= comboBox->GetValue();
|
||||
}
|
||||
|
||||
void EnumField::updateControl(){
|
||||
comboBox->SetValue(value.c_str());
|
||||
}
|
||||
|
||||
bool EnumField::isValueValid(const string &value){
|
||||
return true;
|
||||
}
|
||||
|
||||
void EnumField::loadSpecific(const XmlNode *fieldNode){
|
||||
const XmlNode *enumsNode= fieldNode->getChild("enums");
|
||||
for(int i=0; i<enumsNode->getChildCount(); ++i){
|
||||
const XmlNode *enumNode= enumsNode->getChild("enum", i);
|
||||
enumerants.push_back(enumNode->getAttribute("value")->getValue());
|
||||
}
|
||||
};
|
||||
|
||||
// ===============================================
|
||||
// class IntRange
|
||||
// ===============================================
|
||||
|
||||
void IntRangeField::createControl(wxWindow *parent, wxSizer *sizer){
|
||||
slider= new wxSlider(parent, -1, strToInt(value), min, max, wxDefaultPosition, wxDefaultSize, wxSL_LABELS);
|
||||
sizer->Add(slider);
|
||||
}
|
||||
|
||||
void IntRangeField::updateValue(){
|
||||
value= intToStr(slider->GetValue());
|
||||
}
|
||||
|
||||
void IntRangeField::updateControl(){
|
||||
slider->SetValue(strToInt(value));
|
||||
}
|
||||
|
||||
bool IntRangeField::isValueValid(const string &value){
|
||||
try{
|
||||
strToInt(value);
|
||||
}
|
||||
catch(const exception &){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void IntRangeField::loadSpecific(const XmlNode *fieldNode){
|
||||
const XmlNode *minNode= fieldNode->getChild("min");
|
||||
min= strToInt(minNode->getAttribute("value")->getValue());
|
||||
|
||||
const XmlNode *maxNode= fieldNode->getChild("max");
|
||||
max= strToInt(maxNode->getAttribute("value")->getValue());
|
||||
}
|
||||
|
||||
string IntRangeField::getInfo() const{
|
||||
return name + " (min: " + intToStr(min)+ ", max: " + intToStr(max) + ", default: " + defaultValue + ")";
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class FloatRangeField
|
||||
// ===============================================
|
||||
|
||||
void FloatRangeField::createControl(wxWindow *parent, wxSizer *sizer){
|
||||
textCtrl= new wxTextCtrl(parent, -1, value.c_str());
|
||||
sizer->Add(textCtrl);
|
||||
}
|
||||
|
||||
void FloatRangeField::updateValue(){
|
||||
value= textCtrl->GetValue();
|
||||
}
|
||||
|
||||
void FloatRangeField::updateControl(){
|
||||
textCtrl->SetValue(value.c_str());
|
||||
}
|
||||
|
||||
bool FloatRangeField::isValueValid(const string &value){
|
||||
try{
|
||||
float f= strToFloat(value);
|
||||
return f>=min && f<=max;
|
||||
}
|
||||
catch(const exception &){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FloatRangeField::loadSpecific(const XmlNode *fieldNode){
|
||||
const XmlNode *minNode= fieldNode->getChild("min");
|
||||
min= strToFloat(minNode->getAttribute("value")->getValue());
|
||||
|
||||
const XmlNode *maxNode= fieldNode->getChild("max");
|
||||
max= strToFloat(maxNode->getAttribute("value")->getValue());
|
||||
};
|
||||
|
||||
string FloatRangeField::getInfo() const{
|
||||
return name + " (min: " + floatToStr(min)+ ", max: " + floatToStr(max) + ", default: " + defaultValue + ")";
|
||||
}
|
||||
|
||||
}//end namespace
|
|
@ -0,0 +1,237 @@
|
|||
#ifndef _CONFIGURATOR_CONFIGURATION_H_
|
||||
#define _CONFIGURATOR_CONFIGURATION_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
#include "xml/xml_parser.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
using Shared::Xml::XmlNode;
|
||||
|
||||
namespace Configurator{
|
||||
|
||||
class Field;
|
||||
class FieldGroup;
|
||||
|
||||
// ===============================
|
||||
// class Configuration
|
||||
// ===============================
|
||||
|
||||
class Configuration{
|
||||
public:
|
||||
typedef vector<FieldGroup*> FieldGroups;
|
||||
|
||||
private:
|
||||
string title;
|
||||
string fileName;
|
||||
bool icon;
|
||||
string iconPath;
|
||||
FieldGroups fieldGroups;
|
||||
|
||||
public:
|
||||
~Configuration();
|
||||
|
||||
void load(const string &path);
|
||||
|
||||
void loadStructure(const string &path);
|
||||
void loadValues(const string &path);
|
||||
|
||||
void save();
|
||||
|
||||
const string &getTitle() const {return title;}
|
||||
const string &getFileName() const {return fileName;}
|
||||
bool getIcon() const {return icon;}
|
||||
const string &getIconPath() const {return iconPath;}
|
||||
|
||||
int getFieldGroupCount() const {return fieldGroups.size();}
|
||||
FieldGroup *getFieldGroup(int i) const {return fieldGroups[i];}
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class FieldGroup
|
||||
// ===============================
|
||||
|
||||
class FieldGroup{
|
||||
public:
|
||||
typedef vector<Field*> Fields;
|
||||
|
||||
private:
|
||||
Fields fields;
|
||||
string name;
|
||||
|
||||
public:
|
||||
~FieldGroup();
|
||||
|
||||
int getFieldCount() const {return fields.size();}
|
||||
Field *getField(int i) const {return fields[i];}
|
||||
const string &getName() const {return name;}
|
||||
|
||||
void load(const XmlNode *groupNode);
|
||||
|
||||
private:
|
||||
Field *newField(const string &type);
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class Field
|
||||
// ===============================
|
||||
|
||||
class Field{
|
||||
protected:
|
||||
string name;
|
||||
string variableName;
|
||||
string description;
|
||||
string value;
|
||||
string defaultValue;
|
||||
|
||||
public:
|
||||
virtual ~Field()= 0{}
|
||||
|
||||
const string &getName() const {return name;}
|
||||
const string &getVariableName() const {return variableName;}
|
||||
const string &getDescription() const {return description;}
|
||||
const string &getValue() const {return value;}
|
||||
const string &getDefaultValue() const {return defaultValue;}
|
||||
|
||||
void setName(const string &name) {this->name= name;}
|
||||
void setVariableName(const string &variableName) {this->variableName= variableName;}
|
||||
void setDescription(const string &description) {this->description= description;}
|
||||
void setValue(const string &value) {this->value= value;}
|
||||
void setDefaultValue(const string &defaultValue) {this->defaultValue= defaultValue;}
|
||||
|
||||
virtual void loadSpecific(const XmlNode *fieldNode){};
|
||||
virtual string getInfo() const;
|
||||
|
||||
virtual void createControl(wxWindow *parent, wxSizer *sizer)= 0;
|
||||
virtual void updateValue()= 0;
|
||||
virtual void updateControl()= 0;
|
||||
virtual bool isValueValid(const string &value)= 0;
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class BoolField
|
||||
// ===============================
|
||||
|
||||
class BoolField: public Field{
|
||||
private:
|
||||
wxCheckBox *checkBox;
|
||||
|
||||
public:
|
||||
virtual void createControl(wxWindow *parent, wxSizer *sizer);
|
||||
virtual void updateValue();
|
||||
virtual void updateControl();
|
||||
virtual bool isValueValid(const string &value);
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class IntField
|
||||
// ===============================
|
||||
|
||||
class IntField: public Field{
|
||||
private:
|
||||
wxTextCtrl *textCtrl;
|
||||
|
||||
public:
|
||||
virtual void createControl(wxWindow *parent, wxSizer *sizer);
|
||||
virtual void updateValue();
|
||||
virtual void updateControl();
|
||||
virtual bool isValueValid(const string &value);
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class FloatField
|
||||
// ===============================
|
||||
|
||||
class FloatField: public Field{
|
||||
private:
|
||||
wxTextCtrl *textCtrl;
|
||||
|
||||
public:
|
||||
virtual void createControl(wxWindow *parent, wxSizer *sizer);
|
||||
virtual void updateValue();
|
||||
virtual void updateControl();
|
||||
virtual bool isValueValid(const string &value);
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class StringField
|
||||
// ===============================
|
||||
|
||||
class StringField: public Field{
|
||||
private:
|
||||
wxTextCtrl *textCtrl;
|
||||
|
||||
public:
|
||||
virtual void createControl(wxWindow *parent, wxSizer *sizer);
|
||||
virtual void updateValue();
|
||||
virtual void updateControl();
|
||||
virtual bool isValueValid(const string &value);
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class EnumField
|
||||
// ===============================
|
||||
|
||||
class EnumField: public Field{
|
||||
private:
|
||||
wxComboBox *comboBox;
|
||||
vector<string> enumerants;
|
||||
|
||||
public:
|
||||
virtual void createControl(wxWindow *parent, wxSizer *sizer);
|
||||
virtual void updateValue();
|
||||
virtual void updateControl();
|
||||
virtual bool isValueValid(const string &value);
|
||||
|
||||
virtual void loadSpecific(const XmlNode *fieldNode);
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class IntRangeField
|
||||
// ===============================
|
||||
|
||||
class IntRangeField: public Field{
|
||||
private:
|
||||
wxSlider *slider;
|
||||
int min;
|
||||
int max;
|
||||
|
||||
public:
|
||||
virtual void createControl(wxWindow *parent, wxSizer *sizer);
|
||||
virtual void updateValue();
|
||||
virtual void updateControl();
|
||||
virtual bool isValueValid(const string &value);
|
||||
|
||||
virtual void loadSpecific(const XmlNode *fieldNode);
|
||||
virtual string getInfo() const;
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class FloatRangeField
|
||||
// ===============================
|
||||
|
||||
class FloatRangeField: public Field{
|
||||
private:
|
||||
wxTextCtrl *textCtrl;
|
||||
float min;
|
||||
float max;
|
||||
|
||||
public:
|
||||
virtual void createControl(wxWindow *parent, wxSizer *sizer);
|
||||
virtual void updateValue();
|
||||
virtual void updateControl();
|
||||
virtual bool isValueValid(const string &value);
|
||||
|
||||
virtual void loadSpecific(const XmlNode *fieldNode);
|
||||
virtual string getInfo() const;
|
||||
};
|
||||
|
||||
|
||||
}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,197 @@
|
|||
#include "main.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/icon.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Configurator{
|
||||
|
||||
// ===============================================
|
||||
// class MainWindow
|
||||
// ===============================================
|
||||
|
||||
|
||||
const int MainWindow::margin= 10;
|
||||
const int MainWindow::panelMargin= 20;
|
||||
const int MainWindow::gridMarginHorizontal= 30;
|
||||
|
||||
MainWindow::MainWindow(){
|
||||
|
||||
SetExtraStyle(wxFRAME_EX_CONTEXTHELP);
|
||||
|
||||
configuration.load("configuration.xml");
|
||||
|
||||
Create(NULL, -1, "", wxDefaultPosition, wxDefaultSize, wxCAPTION | wxSYSTEM_MENU);
|
||||
|
||||
SetTitle(("Configurator - " + configuration.getTitle() + " - Editing " + configuration.getFileName()).c_str());
|
||||
|
||||
if(configuration.getIcon()){
|
||||
wxIcon icon;
|
||||
icon.LoadFile(configuration.getIconPath().c_str(), wxBITMAP_TYPE_ICO);
|
||||
SetIcon(icon);
|
||||
}
|
||||
|
||||
notebook= new wxNotebook(this, -1);
|
||||
|
||||
wxSizer *mainSizer= new wxBoxSizer(wxVERTICAL);
|
||||
wxSizer *topSizer= new wxBoxSizer(wxHORIZONTAL);
|
||||
topSizer->Add(notebook, 0, wxALL, 0);
|
||||
mainSizer->Add(topSizer, 0, wxALL, margin);
|
||||
|
||||
for(int i=0; i<configuration.getFieldGroupCount(); ++i){
|
||||
|
||||
//create page
|
||||
FieldGroup *fg= configuration.getFieldGroup(i);
|
||||
wxPanel *panel= new wxPanel(notebook, -1);
|
||||
notebook->AddPage(panel, fg->getName().c_str());
|
||||
|
||||
//sizers
|
||||
wxSizer *gridSizer= new wxFlexGridSizer(2, margin, gridMarginHorizontal);
|
||||
wxSizer *panelSizer= new wxBoxSizer(wxVERTICAL);
|
||||
panelSizer->Add(gridSizer, 0, wxALL, panelMargin);
|
||||
panel->SetSizer(panelSizer);
|
||||
|
||||
for(int j=0; j<fg->getFieldCount(); ++j){
|
||||
Field *f= fg->getField(j);
|
||||
FieldText *staticText= new FieldText(panel, this, f);
|
||||
staticText->SetAutoLayout(true);
|
||||
gridSizer->Add(staticText);
|
||||
f->createControl(panel, gridSizer);
|
||||
idMap.insert(IdPair(staticText->GetId(), staticText));
|
||||
}
|
||||
}
|
||||
|
||||
//buttons
|
||||
wxSizer *bottomSizer= new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
buttonOk= new wxButton(this, biOk, "OK");
|
||||
buttonApply= new wxButton(this, biApply, "Apply");
|
||||
buttonCancel= new wxButton(this, biCancel, "Cancel");
|
||||
buttonDefault= new wxButton(this, biDefault, "Default");
|
||||
bottomSizer->Add(buttonOk, 0, wxALL, margin);
|
||||
bottomSizer->Add(buttonApply, 0, wxRIGHT | wxDOWN | wxUP, margin);
|
||||
bottomSizer->Add(buttonCancel, 0, wxRIGHT | wxDOWN | wxUP, margin);
|
||||
bottomSizer->Add(buttonDefault, 0, wxRIGHT | wxDOWN | wxUP, margin);
|
||||
|
||||
infoText= new wxTextCtrl(this, -1, "Info text.", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY);
|
||||
infoText->SetSize(infoText->GetSize().x, 2*infoText->GetSize().y/3);
|
||||
infoText->SetBackgroundColour(buttonOk->GetBackgroundColour());
|
||||
|
||||
mainSizer->Add(infoText, 1, wxGROW | wxALL | wxALIGN_CENTER, margin);
|
||||
mainSizer->Add(bottomSizer, 0, wxALIGN_CENTER);
|
||||
|
||||
SetBackgroundColour(buttonOk->GetBackgroundColour());
|
||||
|
||||
SetSizerAndFit(mainSizer);
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void MainWindow::onButtonOk(wxCommandEvent &event){
|
||||
configuration.save();
|
||||
Close();
|
||||
}
|
||||
|
||||
void MainWindow::onButtonApply(wxCommandEvent &event){
|
||||
configuration.save();
|
||||
}
|
||||
|
||||
void MainWindow::onButtonCancel(wxCommandEvent &event){
|
||||
Close();
|
||||
}
|
||||
|
||||
void MainWindow::onButtonDefault(wxCommandEvent &event){
|
||||
for(int i=0; i<configuration.getFieldGroupCount(); ++i){
|
||||
FieldGroup *fg= configuration.getFieldGroup(i);
|
||||
for(int j=0; j<fg->getFieldCount(); ++j){
|
||||
Field *f= fg->getField(j);
|
||||
f->setValue(f->getDefaultValue());
|
||||
f->updateControl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onClose(wxCloseEvent &event){
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void MainWindow::onMouseDown(wxMouseEvent &event){
|
||||
setInfoText("");
|
||||
}
|
||||
|
||||
void MainWindow::setInfoText(const string &str){
|
||||
infoText->SetValue(str.c_str());
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(MainWindow, wxFrame)
|
||||
EVT_BUTTON(biOk, MainWindow::onButtonOk)
|
||||
EVT_BUTTON(biApply, MainWindow::onButtonApply)
|
||||
EVT_BUTTON(biCancel, MainWindow::onButtonCancel)
|
||||
EVT_BUTTON(biDefault, MainWindow::onButtonDefault)
|
||||
EVT_CLOSE(MainWindow::onClose)
|
||||
EVT_LEFT_DOWN(MainWindow::onMouseDown)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ===============================================
|
||||
// class FieldText
|
||||
// ===============================================
|
||||
|
||||
FieldText::FieldText(wxWindow *parent, MainWindow *mainWindow, const Field *field):
|
||||
wxStaticText(parent, -1, field->getName().c_str())
|
||||
{
|
||||
this->mainWindow= mainWindow;
|
||||
this->field= field;
|
||||
}
|
||||
|
||||
void FieldText::onHelp(wxHelpEvent &event){
|
||||
string str= field->getInfo()+".";
|
||||
if(!field->getDescription().empty()){
|
||||
str+= "\n"+field->getDescription()+".";
|
||||
}
|
||||
mainWindow->setInfoText(str);
|
||||
}
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE(FieldText, wxStaticText)
|
||||
EVT_HELP(-1, FieldText::onHelp)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ===============================================
|
||||
// class App
|
||||
// ===============================================
|
||||
|
||||
bool App::OnInit(){
|
||||
try{
|
||||
mainWindow= new MainWindow();
|
||||
mainWindow->Show();
|
||||
}
|
||||
catch(const exception &e){
|
||||
wxMessageDialog(NULL, e.what(), "Exception", wxOK | wxICON_ERROR).ShowModal();
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int App::MainLoop(){
|
||||
try{
|
||||
return wxApp::MainLoop();
|
||||
}
|
||||
catch(const exception &e){
|
||||
wxMessageDialog(NULL, e.what(), "Exception", wxOK | wxICON_ERROR).ShowModal();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int App::OnExit(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
}//end namespace
|
||||
|
||||
IMPLEMENT_APP(Configurator::App)
|
|
@ -0,0 +1,101 @@
|
|||
#ifndef _CONFIGURATOR_MAIN_H_
|
||||
#define _CONFIGURATOR_MAIN_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/cshelp.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/sizer.h>
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
using std::pair;
|
||||
using std::map;
|
||||
|
||||
namespace Configurator{
|
||||
|
||||
// ===============================
|
||||
// class MainWindow
|
||||
// ===============================
|
||||
|
||||
class MainWindow: public wxFrame{
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
private:
|
||||
typedef pair<int, wxWindow*> IdPair;
|
||||
typedef map<int, wxWindow*> IdMap;
|
||||
|
||||
private:
|
||||
static const int margin;
|
||||
static const int panelMargin;
|
||||
static const int gridMarginHorizontal;
|
||||
|
||||
enum ButtonId{
|
||||
biOk,
|
||||
biApply,
|
||||
biCancel,
|
||||
biDefault
|
||||
};
|
||||
|
||||
private:
|
||||
IdMap idMap;
|
||||
Configuration configuration;
|
||||
wxButton *buttonOk;
|
||||
wxButton *buttonApply;
|
||||
wxButton *buttonCancel;
|
||||
wxButton *buttonDefault;
|
||||
wxNotebook *notebook;
|
||||
wxTextCtrl *infoText;
|
||||
|
||||
public:
|
||||
MainWindow();
|
||||
|
||||
void onButtonOk(wxCommandEvent &event);
|
||||
void onButtonApply(wxCommandEvent &event);
|
||||
void onButtonCancel(wxCommandEvent &event);
|
||||
void onButtonDefault(wxCommandEvent &event);
|
||||
void onClose(wxCloseEvent &event);
|
||||
void onMouseDown(wxMouseEvent &event);
|
||||
|
||||
void setInfoText(const string &str);
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class FieldText
|
||||
// ===============================
|
||||
|
||||
class FieldText: public wxStaticText{
|
||||
private:
|
||||
MainWindow *mainWindow;
|
||||
const Field *field;
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
public:
|
||||
FieldText(wxWindow *parentm, MainWindow *mainWindow, const Field *field);
|
||||
|
||||
void onHelp(wxHelpEvent &event);
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class App
|
||||
// ===============================
|
||||
|
||||
class App: public wxApp{
|
||||
private:
|
||||
MainWindow *mainWindow;
|
||||
|
||||
public:
|
||||
virtual bool OnInit();
|
||||
virtual int MainLoop();
|
||||
virtual int OnExit();
|
||||
};
|
||||
|
||||
}//end namespace
|
||||
|
||||
DECLARE_APP(Configurator::App)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,304 @@
|
|||
#include "main.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "graphics_factory_basic_gl.h"
|
||||
#include "graphics_interface.h"
|
||||
#include "util.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Graphics::Gl;
|
||||
using namespace Shared::Util;
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Shared{ namespace G3dViewer{
|
||||
|
||||
// ===============================================
|
||||
// class MainWindow
|
||||
// ===============================================
|
||||
|
||||
const string MainWindow::versionString= "v1.3.4";
|
||||
const string MainWindow::winHeader= "G3D viewer " + versionString + " - Built: " + __DATE__;
|
||||
|
||||
MainWindow::MainWindow(const string &modelPath):
|
||||
wxFrame(
|
||||
NULL, -1, winHeader.c_str(),
|
||||
wxPoint(Renderer::windowX, Renderer::windowY),
|
||||
wxSize(Renderer::windowW, Renderer::windowH))
|
||||
{
|
||||
renderer= Renderer::getInstance();
|
||||
this->modelPath= modelPath;
|
||||
model= NULL;
|
||||
playerColor= Renderer::pcRed;
|
||||
|
||||
speed= 0.025f;
|
||||
|
||||
glCanvas = new GlCanvas(this);
|
||||
|
||||
glCanvas->SetCurrent();
|
||||
|
||||
renderer->init();
|
||||
|
||||
|
||||
menu= new wxMenuBar();
|
||||
|
||||
//menu
|
||||
menuFile= new wxMenu();
|
||||
menuFile->Append(miFileLoad, "Load");
|
||||
menu->Append(menuFile, "File");
|
||||
|
||||
//mode
|
||||
menuMode= new wxMenu();
|
||||
menuMode->AppendCheckItem(miModeNormals, "Normals");
|
||||
menuMode->AppendCheckItem(miModeWireframe, "Wireframe");
|
||||
menuMode->AppendCheckItem(miModeGrid, "Grid");
|
||||
menu->Append(menuMode, "Mode");
|
||||
|
||||
//mode
|
||||
menuSpeed= new wxMenu();
|
||||
menuSpeed->Append(miSpeedSlower, "Slower");
|
||||
menuSpeed->Append(miSpeedFaster, "Faster");
|
||||
menu->Append(menuSpeed, "Speed");
|
||||
|
||||
//custom color
|
||||
menuCustomColor= new wxMenu();
|
||||
menuCustomColor->AppendCheckItem(miColorRed, "Red");
|
||||
menuCustomColor->AppendCheckItem(miColorBlue, "Blue");
|
||||
menuCustomColor->AppendCheckItem(miColorYellow, "Yellow");
|
||||
menuCustomColor->AppendCheckItem(miColorGreen, "Green");
|
||||
menu->Append(menuCustomColor, "Custom Color");
|
||||
|
||||
menuMode->Check(miModeGrid, true);
|
||||
menuCustomColor->Check(miColorRed, true);
|
||||
|
||||
SetMenuBar(menu);
|
||||
|
||||
//misc
|
||||
model= NULL;
|
||||
rotX= 0.0f;
|
||||
rotY= 0.0f;
|
||||
zoom= 1.0f;
|
||||
lastX= 0;
|
||||
lastY= 0;
|
||||
anim= 0.0f;
|
||||
|
||||
CreateStatusBar();
|
||||
|
||||
timer = new wxTimer(this);
|
||||
timer->Start(40);
|
||||
|
||||
if(!modelPath.empty()){
|
||||
Model *tmpModel= new ModelGl();
|
||||
renderer->loadTheModel(tmpModel, modelPath);
|
||||
model= tmpModel;
|
||||
GetStatusBar()->SetStatusText(getModelInfo().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow(){
|
||||
delete renderer;
|
||||
delete model;
|
||||
delete timer;
|
||||
delete glCanvas;
|
||||
}
|
||||
|
||||
void MainWindow::onPaint(wxPaintEvent &event){
|
||||
renderer->reset(GetClientSize().x, GetClientSize().y, playerColor);
|
||||
renderer->transform(rotX, rotY, zoom);
|
||||
renderer->renderGrid();
|
||||
|
||||
renderer->renderTheModel(model, anim);
|
||||
glCanvas->SwapBuffers();
|
||||
}
|
||||
|
||||
void MainWindow::onClose(wxCloseEvent &event){
|
||||
delete this;
|
||||
}
|
||||
|
||||
void MainWindow::onMouseMove(wxMouseEvent &event){
|
||||
|
||||
int x= event.GetX();
|
||||
int y= event.GetY();
|
||||
wxPaintEvent paintEvent;
|
||||
|
||||
if(event.LeftIsDown()){
|
||||
rotX+= clamp(lastX-x, -10, 10);
|
||||
rotY+= clamp(lastY-y, -10, 10);
|
||||
onPaint(paintEvent);
|
||||
}
|
||||
else if(event.RightIsDown()){
|
||||
zoom*= 1.0f+(lastX-x+lastY-y)/100.0f;
|
||||
zoom= clamp(zoom, 0.1f, 10.0f);
|
||||
onPaint(paintEvent);
|
||||
}
|
||||
|
||||
lastX= x;
|
||||
lastY= y;
|
||||
}
|
||||
|
||||
void MainWindow::onMenuFileLoad(wxCommandEvent &event){
|
||||
string fileName;
|
||||
wxFileDialog fileDialog(this);
|
||||
fileDialog.SetWildcard("G3D files (*.g3d)|*.g3d");
|
||||
if(fileDialog.ShowModal()==wxID_OK){
|
||||
delete model;
|
||||
Model *tmpModel= new ModelGl();
|
||||
renderer->loadTheModel(tmpModel, fileDialog.GetPath().c_str());
|
||||
model= tmpModel;
|
||||
GetStatusBar()->SetStatusText(getModelInfo().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onMenuModeNormals(wxCommandEvent &event){
|
||||
renderer->toggleNormals();
|
||||
menuMode->Check(miModeNormals, renderer->getNormals());
|
||||
}
|
||||
|
||||
void MainWindow::onMenuModeWireframe(wxCommandEvent &event){
|
||||
renderer->toggleWireframe();
|
||||
menuMode->Check(miModeWireframe, renderer->getWireframe());
|
||||
}
|
||||
|
||||
void MainWindow::onMenuModeGrid(wxCommandEvent &event){
|
||||
renderer->toggleGrid();
|
||||
menuMode->Check(miModeGrid, renderer->getGrid());
|
||||
}
|
||||
|
||||
void MainWindow::onMenuSpeedSlower(wxCommandEvent &event){
|
||||
speed/= 1.5f;
|
||||
}
|
||||
|
||||
void MainWindow::onMenuSpeedFaster(wxCommandEvent &event){
|
||||
speed*= 1.5f;
|
||||
}
|
||||
|
||||
void MainWindow::onMenuColorRed(wxCommandEvent &event){
|
||||
playerColor= Renderer::pcRed;
|
||||
menuCustomColor->Check(miColorRed, true);
|
||||
menuCustomColor->Check(miColorBlue, false);
|
||||
menuCustomColor->Check(miColorYellow, false);
|
||||
menuCustomColor->Check(miColorGreen, false);
|
||||
}
|
||||
|
||||
void MainWindow::onMenuColorBlue(wxCommandEvent &event){
|
||||
playerColor= Renderer::pcBlue;
|
||||
menuCustomColor->Check(miColorRed, false);
|
||||
menuCustomColor->Check(miColorBlue, true);
|
||||
menuCustomColor->Check(miColorYellow, false);
|
||||
menuCustomColor->Check(miColorGreen, false);
|
||||
}
|
||||
|
||||
void MainWindow::onMenuColorYellow(wxCommandEvent &event){
|
||||
playerColor= Renderer::pcYellow;
|
||||
menuCustomColor->Check(miColorRed, false);
|
||||
menuCustomColor->Check(miColorBlue, false);
|
||||
menuCustomColor->Check(miColorYellow, true);
|
||||
menuCustomColor->Check(miColorGreen, false);
|
||||
}
|
||||
|
||||
void MainWindow::onMenuColorGreen(wxCommandEvent &event){
|
||||
playerColor= Renderer::pcGreen;
|
||||
menuCustomColor->Check(miColorRed, false);
|
||||
menuCustomColor->Check(miColorBlue, false);
|
||||
menuCustomColor->Check(miColorYellow, false);
|
||||
menuCustomColor->Check(miColorGreen, true);
|
||||
}
|
||||
|
||||
void MainWindow::onTimer(wxTimerEvent &event){
|
||||
wxPaintEvent paintEvent;
|
||||
|
||||
anim= anim+speed;
|
||||
if(anim>1.0f){
|
||||
anim-= 1.f;
|
||||
}
|
||||
onPaint(paintEvent);
|
||||
}
|
||||
|
||||
string MainWindow::getModelInfo(){
|
||||
string str;
|
||||
|
||||
if(model!=NULL){
|
||||
str+= "Meshes: "+intToStr(model->getMeshCount());
|
||||
str+= ", Vertices: "+intToStr(model->getVertexCount());
|
||||
str+= ", Triangles: "+intToStr(model->getTriangleCount());
|
||||
str+= ", Version: "+intToStr(model->getFileVersion());
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(MainWindow, wxFrame)
|
||||
EVT_TIMER(-1, MainWindow::onTimer)
|
||||
EVT_CLOSE(MainWindow::onClose)
|
||||
EVT_MENU(miFileLoad, MainWindow::onMenuFileLoad)
|
||||
|
||||
EVT_MENU(miModeWireframe, MainWindow::onMenuModeWireframe)
|
||||
EVT_MENU(miModeNormals, MainWindow::onMenuModeNormals)
|
||||
EVT_MENU(miModeGrid, MainWindow::onMenuModeGrid)
|
||||
|
||||
EVT_MENU(miSpeedFaster, MainWindow::onMenuSpeedFaster)
|
||||
EVT_MENU(miSpeedSlower, MainWindow::onMenuSpeedSlower)
|
||||
|
||||
EVT_MENU(miColorRed, MainWindow::onMenuColorRed)
|
||||
EVT_MENU(miColorBlue, MainWindow::onMenuColorBlue)
|
||||
EVT_MENU(miColorYellow, MainWindow::onMenuColorYellow)
|
||||
EVT_MENU(miColorGreen, MainWindow::onMenuColorGreen)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// =====================================================
|
||||
// class GlCanvas
|
||||
// =====================================================
|
||||
|
||||
GlCanvas::GlCanvas(MainWindow * mainWindow):
|
||||
wxGLCanvas(mainWindow, -1)
|
||||
{
|
||||
this->mainWindow = mainWindow;
|
||||
}
|
||||
|
||||
void GlCanvas::onMouseMove(wxMouseEvent &event){
|
||||
mainWindow->onMouseMove(event);
|
||||
}
|
||||
|
||||
void GlCanvas::onPaint(wxPaintEvent &event){
|
||||
mainWindow->onPaint(event);
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(GlCanvas, wxGLCanvas)
|
||||
EVT_MOTION(GlCanvas::onMouseMove)
|
||||
EVT_PAINT(GlCanvas::onPaint)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ===============================================
|
||||
// class App
|
||||
// ===============================================
|
||||
|
||||
bool App::OnInit(){
|
||||
string modelPath;
|
||||
if(argc==2){
|
||||
modelPath= argv[1];
|
||||
}
|
||||
|
||||
mainWindow= new MainWindow(modelPath);
|
||||
mainWindow->Show();
|
||||
return true;
|
||||
}
|
||||
|
||||
int App::MainLoop(){
|
||||
try{
|
||||
return wxApp::MainLoop();
|
||||
}
|
||||
catch(const exception &e){
|
||||
wxMessageDialog(NULL, e.what(), "Exception", wxOK | wxICON_ERROR).ShowModal();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int App::OnExit(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
}}//end namespace
|
||||
|
||||
IMPLEMENT_APP(Shared::G3dViewer::App)
|
|
@ -0,0 +1,129 @@
|
|||
#ifndef _SHADER_G3DVIEWER_MAIN_H_
|
||||
#define _SHADER_G3DVIEWER_MAIN_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/glcanvas.h>
|
||||
|
||||
#include "renderer.h"
|
||||
#include "util.h"
|
||||
#include "window.h"
|
||||
|
||||
using Shared::Platform::Window;
|
||||
using Shared::Platform::MouseState;
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace Shared{ namespace G3dViewer{
|
||||
|
||||
class GlCanvas;
|
||||
|
||||
// ===============================
|
||||
// class MainWindow
|
||||
// ===============================
|
||||
|
||||
class MainWindow: public wxFrame{
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
public:
|
||||
static const string versionString;
|
||||
static const string winHeader;
|
||||
|
||||
enum MenuId{
|
||||
miFileLoad,
|
||||
miModeWireframe,
|
||||
miModeNormals,
|
||||
miModeGrid,
|
||||
miSpeedSlower,
|
||||
miSpeedFaster,
|
||||
miColorRed,
|
||||
miColorBlue,
|
||||
miColorYellow,
|
||||
miColorGreen
|
||||
};
|
||||
|
||||
private:
|
||||
GlCanvas *glCanvas;
|
||||
Renderer *renderer;
|
||||
|
||||
wxTimer *timer;
|
||||
|
||||
wxMenuBar *menu;
|
||||
wxMenu *menuFile;
|
||||
wxMenu *menuMode;
|
||||
wxMenu *menuSpeed;
|
||||
wxMenu *menuCustomColor;
|
||||
|
||||
Model *model;
|
||||
string modelPath;
|
||||
|
||||
float speed;
|
||||
float anim;
|
||||
float rotX, rotY, zoom;
|
||||
int lastX, lastY;
|
||||
Renderer::PlayerColor playerColor;
|
||||
|
||||
public:
|
||||
MainWindow(const string &modelPath);
|
||||
~MainWindow();
|
||||
|
||||
void Notify();
|
||||
|
||||
void onPaint(wxPaintEvent &event);
|
||||
void onClose(wxCloseEvent &event);
|
||||
void onMenuFileLoad(wxCommandEvent &event);
|
||||
void onMenuModeNormals(wxCommandEvent &event);
|
||||
void onMenuModeWireframe(wxCommandEvent &event);
|
||||
void onMenuModeGrid(wxCommandEvent &event);
|
||||
void onMenuSpeedSlower(wxCommandEvent &event);
|
||||
void onMenuSpeedFaster(wxCommandEvent &event);
|
||||
void onMenuColorRed(wxCommandEvent &event);
|
||||
void onMenuColorBlue(wxCommandEvent &event);
|
||||
void onMenuColorYellow(wxCommandEvent &event);
|
||||
void onMenuColorGreen(wxCommandEvent &event);
|
||||
void onMouseMove(wxMouseEvent &event);
|
||||
void onTimer(wxTimerEvent &event);
|
||||
|
||||
string getModelInfo();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class GlCanvas
|
||||
// =====================================================
|
||||
|
||||
class GlCanvas: public wxGLCanvas{
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
public:
|
||||
GlCanvas(MainWindow *mainWindow);
|
||||
|
||||
void onMouseMove(wxMouseEvent &event);
|
||||
void onPaint(wxPaintEvent &event);
|
||||
|
||||
private:
|
||||
MainWindow *mainWindow;
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class App
|
||||
// ===============================
|
||||
|
||||
class App: public wxApp{
|
||||
private:
|
||||
MainWindow *mainWindow;
|
||||
|
||||
public:
|
||||
virtual bool OnInit();
|
||||
virtual int MainLoop();
|
||||
virtual int OnExit();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
DECLARE_APP(Shared::G3dViewer::App)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,272 @@
|
|||
#include "renderer.h"
|
||||
|
||||
#include "opengl.h"
|
||||
#include "texture_gl.h"
|
||||
#include "graphics_interface.h"
|
||||
#include "graphics_factory_gl.h"
|
||||
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Graphics::Gl;
|
||||
|
||||
namespace Shared{ namespace G3dViewer{
|
||||
|
||||
// ===============================================
|
||||
// class MeshCallbackTeamColor
|
||||
// ===============================================
|
||||
|
||||
void MeshCallbackTeamColor::execute(const Mesh *mesh){
|
||||
|
||||
//team color
|
||||
if(mesh->getCustomTexture() && teamTexture!=NULL){
|
||||
//texture 0
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
|
||||
//set color to interpolation
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
|
||||
|
||||
//set alpha to 1
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
|
||||
//texture 1
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glMultiTexCoord2f(GL_TEXTURE1, 0.f, 0.f);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, static_cast<const Texture2DGl*>(teamTexture)->getHandle());
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||
|
||||
//set alpha to 1
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
else{
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
}
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class Renderer
|
||||
// ===============================================
|
||||
|
||||
Renderer::Renderer(){
|
||||
normals= false;
|
||||
wireframe= false;
|
||||
grid= true;
|
||||
}
|
||||
|
||||
Renderer::~Renderer(){
|
||||
delete modelRenderer;
|
||||
delete textureManager;
|
||||
}
|
||||
|
||||
Renderer * Renderer::getInstance(){
|
||||
static Renderer * renderer = new Renderer();
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void Renderer::transform(float rotX, float rotY, float zoom){
|
||||
assertGl();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glRotatef(rotY, 1.0f, 0.0f, 0.0f);
|
||||
glRotatef(rotX, 0.0f, 1.0f, 0.0f);
|
||||
glScalef(zoom, zoom, zoom);
|
||||
Vec4f pos(-8.0f, 5.0f, 10.0f, 0.0f);
|
||||
glLightfv(GL_LIGHT0,GL_POSITION, pos.ptr());
|
||||
|
||||
assertGl();
|
||||
}
|
||||
|
||||
void Renderer::init(){
|
||||
assertGl();
|
||||
|
||||
GraphicsFactory *gf= new GraphicsFactoryGl();
|
||||
|
||||
GraphicsInterface::getInstance().setFactory(gf);
|
||||
|
||||
modelRenderer= gf->newModelRenderer();
|
||||
textureManager= gf->newTextureManager();
|
||||
|
||||
//red tex
|
||||
customTextureRed= textureManager->newTexture2D();
|
||||
customTextureRed->getPixmap()->init(1, 1, 3);
|
||||
customTextureRed->getPixmap()->setPixel(0, 0, Vec3f(1.f, 0.f, 0.f));
|
||||
|
||||
//blue tex
|
||||
customTextureBlue= textureManager->newTexture2D();
|
||||
customTextureBlue->getPixmap()->init(1, 1, 3);
|
||||
customTextureBlue->getPixmap()->setPixel(0, 0, Vec3f(0.f, 0.f, 1.f));
|
||||
|
||||
//yellow tex
|
||||
customTextureYellow= textureManager->newTexture2D();
|
||||
customTextureYellow->getPixmap()->init(1, 1, 3);
|
||||
customTextureYellow->getPixmap()->setPixel(0, 0, Vec3f(1.f, 1.f, 0.f));
|
||||
|
||||
//green
|
||||
customTextureGreen= textureManager->newTexture2D();
|
||||
customTextureGreen->getPixmap()->init(1, 1, 3);
|
||||
customTextureGreen->getPixmap()->setPixel(0, 0, Vec3f(0.f, 0.5f, 0.f));
|
||||
|
||||
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glFrontFace(GL_CW);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GREATER, 0.5f);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
|
||||
Vec4f diffuse= Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Vec4f ambient= Vec4f(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
Vec4f specular= Vec4f(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
|
||||
glLightfv(GL_LIGHT0,GL_AMBIENT, ambient.ptr());
|
||||
glLightfv(GL_LIGHT0,GL_DIFFUSE, diffuse.ptr());
|
||||
glLightfv(GL_LIGHT0,GL_SPECULAR, specular.ptr());
|
||||
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
|
||||
assertGl();
|
||||
}
|
||||
|
||||
void Renderer::reset(int w, int h, PlayerColor playerColor){
|
||||
assertGl();
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glViewport(0, 0, w, h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(60.0f, static_cast<float>(w)/h, 1.0f, 200.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0, -1.5, -5);
|
||||
|
||||
Texture2D *customTexture;
|
||||
switch(playerColor){
|
||||
case pcRed:
|
||||
customTexture= customTextureRed;
|
||||
break;
|
||||
case pcBlue:
|
||||
customTexture= customTextureBlue;
|
||||
break;
|
||||
case pcYellow:
|
||||
customTexture= customTextureYellow;
|
||||
break;
|
||||
case pcGreen:
|
||||
customTexture= customTextureGreen;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
meshCallbackTeamColor.setTeamTexture(customTexture);
|
||||
|
||||
if(wireframe){
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_LIGHT0);
|
||||
}
|
||||
else{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
||||
assertGl();
|
||||
}
|
||||
|
||||
void Renderer::renderGrid(){
|
||||
if(grid){
|
||||
|
||||
float i;
|
||||
|
||||
assertGl();
|
||||
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
for(i=-10.0f; i<=10.0f; i+=1.0f){
|
||||
glVertex3f(i, 0.0f, 10.0f);
|
||||
glVertex3f(i, 0.0f, -10.0f);
|
||||
}
|
||||
for(i=-10.0f; i<=10.0f; i+=1.0f){
|
||||
glVertex3f(10.f, 0.0f, i);
|
||||
glVertex3f(-10.f, 0.0f, i);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glPopAttrib();
|
||||
|
||||
assertGl();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::toggleNormals(){
|
||||
normals= normals? false: true;
|
||||
}
|
||||
|
||||
void Renderer::toggleWireframe(){
|
||||
wireframe= wireframe? false: true;
|
||||
}
|
||||
|
||||
void Renderer::toggleGrid(){
|
||||
grid= grid? false: true;
|
||||
}
|
||||
|
||||
void Renderer::loadTheModel(Model *model, string file){
|
||||
model->setTextureManager(textureManager);
|
||||
model->loadG3d(file);
|
||||
textureManager->init();
|
||||
}
|
||||
|
||||
void Renderer::renderTheModel(Model *model, float f){
|
||||
if(model != NULL){
|
||||
modelRenderer->begin(true, true, !wireframe, &meshCallbackTeamColor);
|
||||
model->updateInterpolationData(f, true);
|
||||
modelRenderer->render(model);
|
||||
|
||||
if(normals){
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
modelRenderer->renderNormalsOnly(model);
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
modelRenderer->end();
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,92 @@
|
|||
#ifndef _SHADER_G3DVIEWER_RENDERER_H_
|
||||
#define _SHADER_G3DVIEWER_RENDERER_H_
|
||||
|
||||
#include "model_renderer.h"
|
||||
#include "texture_manager.h"
|
||||
#include "model.h"
|
||||
#include "texture.h"
|
||||
|
||||
using Shared::Graphics::ModelRenderer;
|
||||
using Shared::Graphics::TextureManager;
|
||||
using Shared::Graphics::Model;
|
||||
using Shared::Graphics::Texture2D;
|
||||
|
||||
#include "model_renderer.h"
|
||||
|
||||
using Shared::Graphics::MeshCallback;
|
||||
using Shared::Graphics::Mesh;
|
||||
using Shared::Graphics::Texture;
|
||||
|
||||
namespace Shared{ namespace G3dViewer{
|
||||
|
||||
// ===============================================
|
||||
// class MeshCallbackTeamColor
|
||||
// ===============================================
|
||||
|
||||
class MeshCallbackTeamColor: public MeshCallback{
|
||||
private:
|
||||
const Texture *teamTexture;
|
||||
|
||||
public:
|
||||
void setTeamTexture(const Texture *teamTexture) {this->teamTexture= teamTexture;}
|
||||
virtual void execute(const Mesh *mesh);
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class Renderer
|
||||
// ===============================
|
||||
|
||||
class Renderer{
|
||||
public:
|
||||
static const int windowX= 100;
|
||||
static const int windowY= 100;
|
||||
static const int windowW= 640;
|
||||
static const int windowH= 480;
|
||||
|
||||
public:
|
||||
enum PlayerColor{
|
||||
pcRed,
|
||||
pcBlue,
|
||||
pcYellow,
|
||||
pcGreen
|
||||
};
|
||||
|
||||
private:
|
||||
bool wireframe;
|
||||
bool normals;
|
||||
bool grid;
|
||||
|
||||
ModelRenderer *modelRenderer;
|
||||
TextureManager *textureManager;
|
||||
Texture2D *customTextureRed;
|
||||
Texture2D *customTextureBlue;
|
||||
Texture2D *customTextureYellow;
|
||||
Texture2D *customTextureGreen;
|
||||
MeshCallbackTeamColor meshCallbackTeamColor;
|
||||
|
||||
Renderer();
|
||||
|
||||
public:
|
||||
~Renderer();
|
||||
static Renderer *getInstance();
|
||||
|
||||
void init();
|
||||
void reset(int w, int h, PlayerColor playerColor);
|
||||
void transform(float rotX, float rotY, float zoom);
|
||||
void renderGrid();
|
||||
|
||||
bool getNormals() const {return normals;}
|
||||
bool getWireframe() const {return wireframe;}
|
||||
bool getGrid() const {return grid;}
|
||||
|
||||
void toggleNormals();
|
||||
void toggleWireframe();
|
||||
void toggleGrid();
|
||||
|
||||
void loadTheModel(Model *model, string file);
|
||||
void renderTheModel(Model *model, float f);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,482 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "ai.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "ai_interface.h"
|
||||
#include "ai_rule.h"
|
||||
#include "unit_type.h"
|
||||
#include "unit.h"
|
||||
#include "program.h"
|
||||
#include "config.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class ProduceTask
|
||||
// =====================================================
|
||||
|
||||
ProduceTask::ProduceTask(UnitClass unitClass){
|
||||
taskClass= tcProduce;
|
||||
this->unitClass= unitClass;
|
||||
unitType= NULL;
|
||||
resourceType= NULL;
|
||||
}
|
||||
|
||||
ProduceTask::ProduceTask(const UnitType *unitType){
|
||||
taskClass= tcProduce;
|
||||
this->unitType= unitType;
|
||||
resourceType= NULL;
|
||||
}
|
||||
|
||||
ProduceTask::ProduceTask(const ResourceType *resourceType){
|
||||
taskClass= tcProduce;
|
||||
unitType= NULL;
|
||||
this->resourceType= resourceType;
|
||||
}
|
||||
|
||||
string ProduceTask::toString() const{
|
||||
string str= "Produce ";
|
||||
if(unitType!=NULL){
|
||||
str+= unitType->getName();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class BuildTask
|
||||
// =====================================================
|
||||
|
||||
BuildTask::BuildTask(const UnitType *unitType){
|
||||
taskClass= tcBuild;
|
||||
this->unitType= unitType;
|
||||
resourceType= NULL;
|
||||
forcePos= false;
|
||||
}
|
||||
|
||||
BuildTask::BuildTask(const ResourceType *resourceType){
|
||||
taskClass= tcBuild;
|
||||
unitType= NULL;
|
||||
this->resourceType= resourceType;
|
||||
forcePos= false;
|
||||
}
|
||||
|
||||
BuildTask::BuildTask(const UnitType *unitType, const Vec2i &pos){
|
||||
taskClass= tcBuild;
|
||||
this->unitType= unitType;
|
||||
resourceType= NULL;
|
||||
forcePos= true;
|
||||
this->pos= pos;
|
||||
}
|
||||
|
||||
string BuildTask::toString() const{
|
||||
string str= "Build ";
|
||||
if(unitType!=NULL){
|
||||
str+= unitType->getName();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class UpgradeTask
|
||||
// =====================================================
|
||||
|
||||
UpgradeTask::UpgradeTask(const UpgradeType *upgradeType){
|
||||
taskClass= tcUpgrade;
|
||||
this->upgradeType= upgradeType;
|
||||
}
|
||||
|
||||
string UpgradeTask::toString() const{
|
||||
string str= "Build ";
|
||||
if(upgradeType!=NULL){
|
||||
str+= upgradeType->getName();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Ai
|
||||
// =====================================================
|
||||
|
||||
void Ai::init(AiInterface *aiInterface){
|
||||
this->aiInterface= aiInterface;
|
||||
startLoc= random.randRange(0, aiInterface->getMapMaxPlayers()-1);
|
||||
upgradeCount= 0;
|
||||
minWarriors= minMinWarriors;
|
||||
randomMinWarriorsReached= false;
|
||||
//add ai rules
|
||||
aiRules.resize(14);
|
||||
aiRules[0]= new AiRuleWorkerHarvest(this);
|
||||
aiRules[1]= new AiRuleRefreshHarvester(this);
|
||||
aiRules[2]= new AiRuleScoutPatrol(this);
|
||||
aiRules[3]= new AiRuleReturnBase(this);
|
||||
aiRules[4]= new AiRuleMassiveAttack(this);
|
||||
aiRules[5]= new AiRuleAddTasks(this);
|
||||
aiRules[6]= new AiRuleProduceResourceProducer(this);
|
||||
aiRules[7]= new AiRuleBuildOneFarm(this);
|
||||
aiRules[8]= new AiRuleProduce(this);
|
||||
aiRules[9]= new AiRuleBuild(this);
|
||||
aiRules[10]= new AiRuleUpgrade(this);
|
||||
aiRules[11]= new AiRuleExpand(this);
|
||||
aiRules[12]= new AiRuleRepair(this);
|
||||
aiRules[13]= new AiRuleRepair(this);
|
||||
}
|
||||
|
||||
Ai::~Ai(){
|
||||
deleteValues(tasks.begin(), tasks.end());
|
||||
deleteValues(aiRules.begin(), aiRules.end());
|
||||
}
|
||||
|
||||
void Ai::update(){
|
||||
//process ai rules
|
||||
for(AiRules::iterator it= aiRules.begin(); it!=aiRules.end(); ++it){
|
||||
if((aiInterface->getTimer() % ((*it)->getTestInterval()*GameConstants::updateFps/1000))==0){
|
||||
if((*it)->test()){
|
||||
aiInterface->printLog(3, intToStr(1000*aiInterface->getTimer()/GameConstants::updateFps) + ": Executing rule: " + (*it)->getName() + '\n');
|
||||
(*it)->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== state requests ====================
|
||||
|
||||
int Ai::getCountOfType(const UnitType *ut){
|
||||
int count= 0;
|
||||
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
|
||||
if(ut == aiInterface->getMyUnit(i)->getType()){
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int Ai::getCountOfClass(UnitClass uc){
|
||||
int count= 0;
|
||||
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
|
||||
if(aiInterface->getMyUnit(i)->getType()->isOfClass(uc)){
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
float Ai::getRatioOfClass(UnitClass uc){
|
||||
if(aiInterface->getMyUnitCount()==0){
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
return static_cast<float>(getCountOfClass(uc))/aiInterface->getMyUnitCount();
|
||||
}
|
||||
}
|
||||
|
||||
const ResourceType *Ai::getNeededResource(){
|
||||
|
||||
int amount= -1;
|
||||
const ResourceType *neededResource= NULL;
|
||||
const TechTree *tt= aiInterface->getTechTree();
|
||||
|
||||
for(int i=0; i<tt->getResourceTypeCount(); ++i){
|
||||
const ResourceType *rt= tt->getResourceType(i);
|
||||
const Resource *r= aiInterface->getResource(rt);
|
||||
if(rt->getClass()!=rcStatic && rt->getClass()!=rcConsumable && (r->getAmount()<amount || amount==-1)){
|
||||
amount= r->getAmount();
|
||||
neededResource= rt;
|
||||
}
|
||||
}
|
||||
|
||||
return neededResource;
|
||||
}
|
||||
|
||||
bool Ai::beingAttacked(Vec2i &pos, Field &field, int radius){
|
||||
int count= aiInterface->onSightUnitCount();
|
||||
const Unit *unit;
|
||||
|
||||
for(int i=0; i<count; ++i){
|
||||
unit= aiInterface->getOnSightUnit(i);
|
||||
if(!aiInterface->isAlly(unit) && unit->isAlive()){
|
||||
pos= unit->getPos();
|
||||
field= unit->getCurrField();
|
||||
if(pos.dist(aiInterface->getHomeLocation())<radius){
|
||||
aiInterface->printLog(2, "Being attacked at pos "+intToStr(pos.x)+","+intToStr(pos.y)+"\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Ai::isStableBase(){
|
||||
|
||||
if(getCountOfClass(ucWarrior)>minWarriors){
|
||||
aiInterface->printLog(4, "Base is stable\n");
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
aiInterface->printLog(4, "Base is not stable\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, bool idleOnly){
|
||||
vector<int> units;
|
||||
|
||||
*unitIndex= -1;
|
||||
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
|
||||
const Unit *unit= aiInterface->getMyUnit(i);
|
||||
if(unit->getType()->hasCommandClass(ability)){
|
||||
if(!idleOnly || !unit->anyCommand() || unit->getCurrCommand()->getCommandType()->getClass()==ccStop){
|
||||
units.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(units.empty()){
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
*unitIndex= units[random.randRange(0, units.size()-1)];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, CommandClass currentCommand){
|
||||
vector<int> units;
|
||||
|
||||
*unitIndex= -1;
|
||||
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
|
||||
const Unit *unit= aiInterface->getMyUnit(i);
|
||||
if(unit->getType()->hasCommandClass(ability)){
|
||||
if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass()==currentCommand){
|
||||
units.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(units.empty()){
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
*unitIndex= units[random.randRange(0, units.size()-1)];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Ai::findPosForBuilding(const UnitType* building, const Vec2i &searchPos, Vec2i &outPos){
|
||||
|
||||
const int spacing= 1;
|
||||
|
||||
for(int currRadius=0; currRadius<maxBuildRadius; ++currRadius){
|
||||
for(int i=searchPos.x-currRadius; i<searchPos.x+currRadius; ++i){
|
||||
for(int j=searchPos.y-currRadius; j<searchPos.y+currRadius; ++j){
|
||||
outPos= Vec2i(i, j);
|
||||
if(aiInterface->isFreeCells(outPos-Vec2i(spacing), building->getSize()+spacing*2, fLand)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ==================== tasks ====================
|
||||
|
||||
void Ai::addTask(const Task *task){
|
||||
tasks.push_back(task);
|
||||
aiInterface->printLog(2, "Task added: " + task->toString());
|
||||
}
|
||||
|
||||
void Ai::addPriorityTask(const Task *task){
|
||||
deleteValues(tasks.begin(), tasks.end());
|
||||
tasks.clear();
|
||||
|
||||
tasks.push_back(task);
|
||||
aiInterface->printLog(2, "Priority Task added: " + task->toString());
|
||||
}
|
||||
|
||||
bool Ai::anyTask(){
|
||||
return !tasks.empty();
|
||||
}
|
||||
|
||||
const Task *Ai::getTask() const{
|
||||
if(tasks.empty()){
|
||||
return NULL;
|
||||
}
|
||||
else{
|
||||
return tasks.front();
|
||||
}
|
||||
}
|
||||
|
||||
void Ai::removeTask(const Task *task){
|
||||
aiInterface->printLog(2, "Task removed: " + task->toString());
|
||||
tasks.remove(task);
|
||||
delete task;
|
||||
}
|
||||
|
||||
void Ai::retryTask(const Task *task){
|
||||
tasks.remove(task);
|
||||
tasks.push_back(task);
|
||||
}
|
||||
// ==================== expansions ====================
|
||||
|
||||
void Ai::addExpansion(const Vec2i &pos){
|
||||
|
||||
//check if there is a nearby expansion
|
||||
for(Positions::iterator it= expansionPositions.begin(); it!=expansionPositions.end(); ++it){
|
||||
if((*it).dist(pos)<villageRadius){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//add expansion
|
||||
expansionPositions.push_front(pos);
|
||||
|
||||
//remove expansion if queue is list is full
|
||||
if(expansionPositions.size()>maxExpansions){
|
||||
expansionPositions.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
Vec2i Ai::getRandomHomePosition(){
|
||||
|
||||
if(expansionPositions.empty() || random.randRange(0, 1) == 0){
|
||||
return aiInterface->getHomeLocation();
|
||||
}
|
||||
|
||||
return expansionPositions[random.randRange(0, expansionPositions.size()-1)];
|
||||
}
|
||||
|
||||
// ==================== actions ====================
|
||||
|
||||
void Ai::sendScoutPatrol(){
|
||||
Vec2i pos;
|
||||
int unit;
|
||||
|
||||
startLoc= (startLoc+1) % aiInterface->getMapMaxPlayers();
|
||||
pos= aiInterface->getStartLocation(startLoc);
|
||||
|
||||
if(aiInterface->getFactionIndex()!=startLoc){
|
||||
if(findAbleUnit(&unit, ccAttack, false)){
|
||||
aiInterface->giveCommand(unit, ccAttack, pos);
|
||||
aiInterface->printLog(2, "Scout patrol sent to: " + intToStr(pos.x)+","+intToStr(pos.y)+"\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Ai::massiveAttack(const Vec2i &pos, Field field, bool ultraAttack){
|
||||
int producerWarriorCount=0;
|
||||
int maxProducerWarriors=random.randRange(1,11);
|
||||
for(int i=0; i<aiInterface->getMyUnitCount(); ++i){
|
||||
bool isWarrior;
|
||||
const Unit *unit= aiInterface->getMyUnit(i);
|
||||
const AttackCommandType *act= unit->getType()->getFirstAttackCommand(field);
|
||||
if(act!=NULL && unit->getType()->hasCommandClass(ccProduce))
|
||||
{
|
||||
producerWarriorCount++;
|
||||
}
|
||||
|
||||
if(aiInterface->getControlType()==ctCpuMega)
|
||||
{
|
||||
if(producerWarriorCount>maxProducerWarriors)
|
||||
{
|
||||
if(
|
||||
unit->getCommandSize()>0 &&
|
||||
unit->getCurrCommand()->getCommandType()!=NULL && (
|
||||
unit->getCurrCommand()->getCommandType()->getClass()==ccBuild ||
|
||||
unit->getCurrCommand()->getCommandType()->getClass()==ccMorph ||
|
||||
unit->getCurrCommand()->getCommandType()->getClass()==ccProduce
|
||||
)
|
||||
)
|
||||
{
|
||||
isWarrior=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
isWarrior=!unit->getType()->hasCommandClass(ccHarvest);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isWarrior= !unit->getType()->hasCommandClass(ccHarvest) && !unit->getType()->hasCommandClass(ccProduce);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isWarrior= !unit->getType()->hasCommandClass(ccHarvest) && !unit->getType()->hasCommandClass(ccProduce);
|
||||
}
|
||||
|
||||
|
||||
bool alreadyAttacking= unit->getCurrSkill()->getClass()==scAttack;
|
||||
if(!alreadyAttacking && act!=NULL && (ultraAttack || isWarrior)){
|
||||
aiInterface->giveCommand(i, act, pos);
|
||||
}
|
||||
}
|
||||
|
||||
if(aiInterface->getControlType()==ctCpuEasy)
|
||||
{
|
||||
minWarriors+= 1;
|
||||
}
|
||||
else if(aiInterface->getControlType()==ctCpuMega)
|
||||
{
|
||||
minWarriors+= 3;
|
||||
if(minWarriors>maxMinWarriors-1 || randomMinWarriorsReached)
|
||||
{
|
||||
randomMinWarriorsReached=true;
|
||||
minWarriors=random.randRange(maxMinWarriors-10, maxMinWarriors*2);
|
||||
}
|
||||
}
|
||||
else if(minWarriors<maxMinWarriors){
|
||||
minWarriors+= 3;
|
||||
}
|
||||
aiInterface->printLog(2, "Massive attack to pos: "+ intToStr(pos.x)+", "+intToStr(pos.y)+"\n");
|
||||
}
|
||||
|
||||
void Ai::returnBase(int unitIndex){
|
||||
Vec2i pos;
|
||||
CommandResult r;
|
||||
int fi;
|
||||
|
||||
fi= aiInterface->getFactionIndex();
|
||||
pos= Vec2i(
|
||||
random.randRange(-villageRadius, villageRadius), random.randRange(-villageRadius, villageRadius)) +
|
||||
getRandomHomePosition();
|
||||
r= aiInterface->giveCommand(unitIndex, ccMove, pos);
|
||||
|
||||
//aiInterface->printLog(1, "Order return to base pos:" + intToStr(pos.x)+", "+intToStr(pos.y)+": "+rrToStr(r)+"\n");
|
||||
}
|
||||
|
||||
void Ai::harvest(int unitIndex){
|
||||
|
||||
const ResourceType *rt= getNeededResource();
|
||||
|
||||
if(rt!=NULL){
|
||||
const HarvestCommandType *hct= aiInterface->getMyUnit(unitIndex)->getType()->getFirstHarvestCommand(rt);
|
||||
Vec2i resPos;
|
||||
if(hct!=NULL && aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), resPos)){
|
||||
resPos= resPos+Vec2i(random.randRange(-2, 2), random.randRange(-2, 2));
|
||||
aiInterface->giveCommand(unitIndex, hct, resPos);
|
||||
//aiInterface->printLog(4, "Order harvest pos:" + intToStr(resPos.x)+", "+intToStr(resPos.y)+": "+rrToStr(r)+"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,189 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_AI_H_
|
||||
#define _GLEST_GAME_AI_H_
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
#include "world.h"
|
||||
#include "commander.h"
|
||||
#include "command.h"
|
||||
#include "random.h"
|
||||
|
||||
using std::deque;
|
||||
using std::vector;
|
||||
using std::list;
|
||||
using Shared::Util::Random;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class AiInterface;
|
||||
class AiRule;
|
||||
|
||||
// =====================================================
|
||||
// class Task
|
||||
//
|
||||
/// An action that has to be performed by the IA
|
||||
// =====================================================
|
||||
|
||||
enum TaskClass{
|
||||
tcProduce,
|
||||
tcBuild,
|
||||
tcUpgrade
|
||||
};
|
||||
|
||||
class Task{
|
||||
protected:
|
||||
TaskClass taskClass;
|
||||
|
||||
public:
|
||||
virtual ~Task(){}
|
||||
TaskClass getClass() const {return taskClass;}
|
||||
virtual string toString() const= 0;
|
||||
};
|
||||
|
||||
// ==================== ProduceTask ====================
|
||||
|
||||
class ProduceTask: public Task{
|
||||
private:
|
||||
UnitClass unitClass;
|
||||
const UnitType *unitType;
|
||||
const ResourceType *resourceType;
|
||||
|
||||
public:
|
||||
ProduceTask(UnitClass unitClass);
|
||||
ProduceTask(const UnitType *unitType);
|
||||
ProduceTask(const ResourceType *resourceType);
|
||||
|
||||
UnitClass getUnitClass() const {return unitClass;}
|
||||
const UnitType *getUnitType() const {return unitType;}
|
||||
const ResourceType *getResourceType() const {return resourceType;}
|
||||
virtual string toString() const;
|
||||
};
|
||||
|
||||
// ==================== BuildTask ====================
|
||||
|
||||
class BuildTask: public Task{
|
||||
private:
|
||||
const UnitType *unitType;
|
||||
const ResourceType *resourceType;
|
||||
bool forcePos;
|
||||
Vec2i pos;
|
||||
|
||||
public:
|
||||
BuildTask(const UnitType *unitType= NULL);
|
||||
BuildTask(const ResourceType *resourceType);
|
||||
BuildTask(const UnitType *unitType, const Vec2i &pos);
|
||||
|
||||
const UnitType *getUnitType() const {return unitType;}
|
||||
const ResourceType *getResourceType() const {return resourceType;}
|
||||
bool getForcePos() const {return forcePos;}
|
||||
Vec2i getPos() const {return pos;}
|
||||
virtual string toString() const;
|
||||
};
|
||||
|
||||
// ==================== UpgradeTask ====================
|
||||
|
||||
class UpgradeTask: public Task{
|
||||
private:
|
||||
const UpgradeType *upgradeType;
|
||||
|
||||
public:
|
||||
UpgradeTask(const UpgradeType *upgradeType= NULL);
|
||||
const UpgradeType *getUpgradeType() const {return upgradeType;}
|
||||
virtual string toString() const;
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class AI
|
||||
//
|
||||
/// Main AI class
|
||||
// ===============================
|
||||
|
||||
class Ai{
|
||||
private:
|
||||
static const int harvesterPercent= 30;
|
||||
static const int maxBuildRadius= 40;
|
||||
static const int minMinWarriors= 7;
|
||||
static const int maxMinWarriors= 20;
|
||||
static const int minStaticResources= 10;
|
||||
static const int minConsumableResources= 20;
|
||||
static const int maxExpansions= 2;
|
||||
static const int villageRadius= 15;
|
||||
|
||||
public:
|
||||
enum ResourceUsage{
|
||||
ruHarvester,
|
||||
ruWarrior,
|
||||
ruBuilding,
|
||||
ruUpgrade
|
||||
};
|
||||
|
||||
private:
|
||||
typedef vector<AiRule*> AiRules;
|
||||
typedef list<const Task*> Tasks;
|
||||
typedef deque<Vec2i> Positions;
|
||||
|
||||
private:
|
||||
AiInterface *aiInterface;
|
||||
AiRules aiRules;
|
||||
int startLoc;
|
||||
bool randomMinWarriorsReached;
|
||||
int upgradeCount;
|
||||
Tasks tasks;
|
||||
Positions expansionPositions;
|
||||
Random random;
|
||||
|
||||
public:
|
||||
int minWarriors;
|
||||
~Ai();
|
||||
void init(AiInterface *aiInterface);
|
||||
void update();
|
||||
|
||||
//state requests
|
||||
AiInterface *getAiInterface() const {return aiInterface;}
|
||||
Random* getRandom() {return &random;}
|
||||
int getCountOfType(const UnitType *ut);
|
||||
|
||||
int getCountOfClass(UnitClass uc);
|
||||
float getRatioOfClass(UnitClass uc);
|
||||
|
||||
const ResourceType *getNeededResource();
|
||||
bool isStableBase();
|
||||
bool findPosForBuilding(const UnitType* building, const Vec2i &searchPos, Vec2i &pos);
|
||||
bool findAbleUnit(int *unitIndex, CommandClass ability, bool idleOnly);
|
||||
bool findAbleUnit(int *unitIndex, CommandClass ability, CommandClass currentCommand);
|
||||
bool beingAttacked(Vec2i &pos, Field &field, int radius);
|
||||
|
||||
//tasks
|
||||
void addTask(const Task *task);
|
||||
void addPriorityTask(const Task *task);
|
||||
bool anyTask();
|
||||
const Task *getTask() const;
|
||||
void removeTask(const Task *task);
|
||||
void retryTask(const Task *task);
|
||||
|
||||
//expansions
|
||||
void addExpansion(const Vec2i &pos);
|
||||
Vec2i getRandomHomePosition();
|
||||
|
||||
//actions
|
||||
void sendScoutPatrol();
|
||||
void massiveAttack(const Vec2i &pos, Field field, bool ultraAttack= false);
|
||||
void returnBase(int unitIndex);
|
||||
void harvest(int unitIndex);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,238 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "ai_interface.h"
|
||||
|
||||
#include "ai.h"
|
||||
#include "command_type.h"
|
||||
#include "faction.h"
|
||||
#include "unit.h"
|
||||
#include "unit_type.h"
|
||||
#include "object.h"
|
||||
#include "game.h"
|
||||
#include "config.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Graphics;
|
||||
|
||||
// =====================================================
|
||||
// class AiInterface
|
||||
// =====================================================
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
AiInterface::AiInterface(Game &game, int factionIndex, int teamIndex){
|
||||
this->world= game.getWorld();
|
||||
this->commander= game.getCommander();
|
||||
this->console= game.getConsole();
|
||||
|
||||
this->factionIndex= factionIndex;
|
||||
this->teamIndex= teamIndex;
|
||||
timer= 0;
|
||||
|
||||
//init ai
|
||||
ai.init(this);
|
||||
|
||||
//config
|
||||
logLevel= Config::getInstance().getInt("AiLog");
|
||||
redir= Config::getInstance().getBool("AiRedir");
|
||||
|
||||
//clear log file
|
||||
if(logLevel>0){
|
||||
FILE *f= fopen(getLogFilename().c_str(), "wt");
|
||||
if(f==NULL){
|
||||
throw runtime_error("Can't open file: "+getLogFilename());
|
||||
}
|
||||
fprintf(f, "%s", "Glest AI log file\n\n");
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== main ====================
|
||||
|
||||
void AiInterface::update(){
|
||||
timer++;
|
||||
ai.update();
|
||||
}
|
||||
|
||||
// ==================== misc ====================
|
||||
|
||||
void AiInterface::printLog(int logLevel, const string &s){
|
||||
if(this->logLevel>=logLevel){
|
||||
string logString= "(" + intToStr(factionIndex) + ") " + s;
|
||||
|
||||
//print log to file
|
||||
FILE *f= fopen(getLogFilename().c_str(), "at");
|
||||
if(f==NULL){
|
||||
throw runtime_error("Can't open file: "+getLogFilename());
|
||||
}
|
||||
fprintf(f, "%s\n", logString.c_str());
|
||||
fclose(f);
|
||||
|
||||
//redirect to console
|
||||
if(redir) {
|
||||
console->addLine(logString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== interaction ====================
|
||||
|
||||
CommandResult AiInterface::giveCommand(int unitIndex, CommandClass commandClass, const Vec2i &pos){
|
||||
Command *c= new Command (world->getFaction(factionIndex)->getUnit(unitIndex)->getType()->getFirstCtOfClass(commandClass), pos);
|
||||
return world->getFaction(factionIndex)->getUnit(unitIndex)->giveCommand(c);
|
||||
}
|
||||
|
||||
CommandResult AiInterface::giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos){
|
||||
return world->getFaction(factionIndex)->getUnit(unitIndex)->giveCommand(new Command(commandType, pos));
|
||||
}
|
||||
|
||||
CommandResult AiInterface::giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos, const UnitType *ut){
|
||||
return world->getFaction(factionIndex)->getUnit(unitIndex)->giveCommand(new Command(commandType, pos, ut));
|
||||
}
|
||||
|
||||
CommandResult AiInterface::giveCommand(int unitIndex, const CommandType *commandType, Unit *u){
|
||||
return world->getFaction(factionIndex)->getUnit(unitIndex)->giveCommand(new Command(commandType, u));
|
||||
}
|
||||
|
||||
// ==================== get data ====================
|
||||
|
||||
int AiInterface::getMapMaxPlayers(){
|
||||
return world->getMaxPlayers();
|
||||
}
|
||||
|
||||
Vec2i AiInterface::getHomeLocation(){
|
||||
return world->getMap()->getStartLocation(world->getFaction(factionIndex)->getStartLocationIndex());
|
||||
}
|
||||
|
||||
Vec2i AiInterface::getStartLocation(int loactionIndex){
|
||||
return world->getMap()->getStartLocation(loactionIndex);
|
||||
}
|
||||
|
||||
int AiInterface::getFactionCount(){
|
||||
return world->getFactionCount();
|
||||
}
|
||||
|
||||
int AiInterface::getMyUnitCount() const{
|
||||
return world->getFaction(factionIndex)->getUnitCount();
|
||||
}
|
||||
|
||||
int AiInterface::getMyUpgradeCount() const{
|
||||
return world->getFaction(factionIndex)->getUpgradeManager()->getUpgradeCount();
|
||||
}
|
||||
|
||||
int AiInterface::onSightUnitCount(){
|
||||
int count=0;
|
||||
Map *map= world->getMap();
|
||||
for(int i=0; i<world->getFactionCount(); ++i){
|
||||
for(int j=0; j<world->getFaction(i)->getUnitCount(); ++j){
|
||||
SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(world->getFaction(i)->getUnit(j)->getPos()));
|
||||
if(sc->isVisible(teamIndex)){
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
const Resource *AiInterface::getResource(const ResourceType *rt){
|
||||
return world->getFaction(factionIndex)->getResource(rt);
|
||||
}
|
||||
|
||||
const Unit *AiInterface::getMyUnit(int unitIndex){
|
||||
return world->getFaction(factionIndex)->getUnit(unitIndex);
|
||||
}
|
||||
|
||||
const Unit *AiInterface::getOnSightUnit(int unitIndex){
|
||||
|
||||
int count=0;
|
||||
Map *map= world->getMap();
|
||||
|
||||
for(int i=0; i<world->getFactionCount(); ++i){
|
||||
for(int j=0; j<world->getFaction(i)->getUnitCount(); ++j){
|
||||
Unit *u= world->getFaction(i)->getUnit(j);
|
||||
if(map->getSurfaceCell(Map::toSurfCoords(u->getPos()))->isVisible(teamIndex)){
|
||||
if(count==unitIndex){
|
||||
return u;
|
||||
}
|
||||
else{
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FactionType * AiInterface::getMyFactionType(){
|
||||
return world->getFaction(factionIndex)->getType();
|
||||
}
|
||||
|
||||
const ControlType AiInterface::getControlType(){
|
||||
return world->getFaction(factionIndex)->getControlType();
|
||||
}
|
||||
|
||||
const TechTree *AiInterface::getTechTree(){
|
||||
return world->getTechTree();
|
||||
}
|
||||
|
||||
bool AiInterface::getNearestSightedResource(const ResourceType *rt, const Vec2i &pos, Vec2i &resultPos){
|
||||
float tmpDist;
|
||||
|
||||
float nearestDist= infinity;
|
||||
bool anyResource= false;
|
||||
|
||||
const Map *map= world->getMap();
|
||||
|
||||
for(int i=0; i<map->getW(); ++i){
|
||||
for(int j=0; j<map->getH(); ++j){
|
||||
Vec2i surfPos= Map::toSurfCoords(Vec2i(i, j));
|
||||
|
||||
//if explored cell
|
||||
if(map->getSurfaceCell(surfPos)->isExplored(teamIndex)){
|
||||
Resource *r= map->getSurfaceCell(surfPos)->getResource();
|
||||
|
||||
//if resource cell
|
||||
if(r!=NULL && r->getType()==rt){
|
||||
tmpDist= pos.dist(Vec2i(i, j));
|
||||
if(tmpDist<nearestDist){
|
||||
anyResource= true;
|
||||
nearestDist= tmpDist;
|
||||
resultPos= Vec2i(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return anyResource;
|
||||
}
|
||||
|
||||
bool AiInterface::isAlly(const Unit *unit) const{
|
||||
return world->getFaction(factionIndex)->isAlly(unit->getFaction());
|
||||
}
|
||||
bool AiInterface::reqsOk(const RequirableType *rt){
|
||||
return world->getFaction(factionIndex)->reqsOk(rt);
|
||||
}
|
||||
|
||||
bool AiInterface::reqsOk(const CommandType *ct){
|
||||
return world->getFaction(factionIndex)->reqsOk(ct);
|
||||
}
|
||||
|
||||
bool AiInterface::checkCosts(const ProducibleType *pt){
|
||||
return world->getFaction(factionIndex)->checkCosts(pt);
|
||||
}
|
||||
|
||||
bool AiInterface::isFreeCells(const Vec2i &pos, int size, Field field){
|
||||
return world->getMap()->isFreeCells(pos, size, field);
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,93 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_AIINTERFACE_H_
|
||||
#define _GLEST_GAME_AIINTERFACE_H_
|
||||
|
||||
#include "world.h"
|
||||
#include "commander.h"
|
||||
#include "command.h"
|
||||
#include "conversion.h"
|
||||
#include "ai.h"
|
||||
|
||||
using Shared::Util::intToStr;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class AiInterface
|
||||
//
|
||||
/// The AI will interact with the game through this interface
|
||||
// =====================================================
|
||||
|
||||
class AiInterface{
|
||||
private:
|
||||
World *world;
|
||||
Commander *commander;
|
||||
Console *console;
|
||||
Ai ai;
|
||||
|
||||
int timer;
|
||||
int factionIndex;
|
||||
int teamIndex;
|
||||
|
||||
//config
|
||||
bool redir;
|
||||
int logLevel;
|
||||
|
||||
public:
|
||||
AiInterface(Game &game, int factionIndex, int teamIndex);
|
||||
|
||||
//main
|
||||
void update();
|
||||
|
||||
//get
|
||||
int getTimer() const {return timer;}
|
||||
int getFactionIndex() const {return factionIndex;}
|
||||
|
||||
//misc
|
||||
void printLog(int logLevel, const string &s);
|
||||
|
||||
//interact
|
||||
CommandResult giveCommand(int unitIndex, CommandClass commandClass, const Vec2i &pos=Vec2i(0));
|
||||
CommandResult giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType);
|
||||
CommandResult giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos);
|
||||
CommandResult giveCommand(int unitIndex, const CommandType *commandType, Unit *u= NULL);
|
||||
|
||||
//get data
|
||||
const ControlType getControlType();
|
||||
int getMapMaxPlayers();
|
||||
Vec2i getHomeLocation();
|
||||
Vec2i getStartLocation(int locationIndex);
|
||||
int getFactionCount();
|
||||
int getMyUnitCount() const;
|
||||
int getMyUpgradeCount() const;
|
||||
int onSightUnitCount();
|
||||
const Resource *getResource(const ResourceType *rt);
|
||||
const Unit *getMyUnit(int unitIndex);
|
||||
const Unit *getOnSightUnit(int unitIndex);
|
||||
const FactionType *getMyFactionType();
|
||||
const TechTree *getTechTree();
|
||||
bool getNearestSightedResource(const ResourceType *rt, const Vec2i &pos, Vec2i &resultPos);
|
||||
bool isAlly(const Unit *unit) const;
|
||||
bool isAlly(int factionIndex) const;
|
||||
bool reqsOk(const RequirableType *rt);
|
||||
bool reqsOk(const CommandType *ct);
|
||||
bool checkCosts(const ProducibleType *pt);
|
||||
bool isFreeCells(const Vec2i &pos, int size, Field field);
|
||||
|
||||
private:
|
||||
string getLogFilename() const {return "ai"+intToStr(factionIndex)+".log";}
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,314 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_AIRULE_H_
|
||||
#define _GLEST_GAME_AIRULE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "vec.h"
|
||||
#include "skill_type.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
using Shared::Graphics::Vec2i;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class Ai;
|
||||
class Unit;
|
||||
class UnitType;
|
||||
class ProduceTask;
|
||||
class BuildTask;
|
||||
class UpgradeTask;
|
||||
class ResourceType;
|
||||
|
||||
// =====================================================
|
||||
// class AiRule
|
||||
//
|
||||
/// An action that the AI will perform periodically
|
||||
/// if the test succeeds
|
||||
// =====================================================
|
||||
|
||||
class AiRule{
|
||||
protected:
|
||||
Ai *ai;
|
||||
|
||||
public:
|
||||
AiRule(Ai *ai);
|
||||
virtual ~AiRule() {}
|
||||
|
||||
virtual int getTestInterval() const= 0; //in milliseconds
|
||||
virtual string getName() const= 0;
|
||||
|
||||
virtual bool test()= 0;
|
||||
virtual void execute()= 0;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleWorkerHarvest
|
||||
// =====================================================
|
||||
|
||||
class AiRuleWorkerHarvest: public AiRule{
|
||||
private:
|
||||
int stoppedWorkerIndex;
|
||||
|
||||
public:
|
||||
AiRuleWorkerHarvest(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 2000;}
|
||||
virtual string getName() const {return "Worker stopped => Order worker to harvest";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleRefreshHarvester
|
||||
// =====================================================
|
||||
|
||||
class AiRuleRefreshHarvester: public AiRule{
|
||||
private:
|
||||
int workerIndex;
|
||||
|
||||
public:
|
||||
AiRuleRefreshHarvester(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 20000;}
|
||||
virtual string getName() const {return "Worker reasigned to needed resource";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleScoutPatrol
|
||||
// =====================================================
|
||||
|
||||
class AiRuleScoutPatrol: public AiRule{
|
||||
public:
|
||||
AiRuleScoutPatrol(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 10000;}
|
||||
virtual string getName() const {return "Base is stable => Send scout patrol";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleRepair
|
||||
// =====================================================
|
||||
|
||||
class AiRuleRepair: public AiRule{
|
||||
private:
|
||||
int damagedUnitIndex;
|
||||
|
||||
public:
|
||||
AiRuleRepair(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 10000;}
|
||||
virtual string getName() const {return "Building Damaged => Repair";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleReturnBase
|
||||
// =====================================================
|
||||
|
||||
class AiRuleReturnBase: public AiRule{
|
||||
private:
|
||||
int stoppedUnitIndex;
|
||||
public:
|
||||
AiRuleReturnBase(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 5000;}
|
||||
virtual string getName() const {return "Stopped unit => Order return base";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleMassiveAttack
|
||||
// =====================================================
|
||||
|
||||
class AiRuleMassiveAttack: public AiRule{
|
||||
private:
|
||||
static const int baseRadius= 25;
|
||||
|
||||
private:
|
||||
Vec2i attackPos;
|
||||
Field field;
|
||||
bool ultraAttack;
|
||||
|
||||
public:
|
||||
AiRuleMassiveAttack(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 1000;}
|
||||
virtual string getName() const {return "Unit under attack => Order massive attack";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleAddTasks
|
||||
// =====================================================
|
||||
|
||||
class AiRuleAddTasks: public AiRule{
|
||||
public:
|
||||
AiRuleAddTasks(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 5000;}
|
||||
virtual string getName() const {return "Tasks empty => Add tasks";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleBuildOneFarm
|
||||
// =====================================================
|
||||
|
||||
class AiRuleBuildOneFarm: public AiRule{
|
||||
private:
|
||||
const UnitType *farm;
|
||||
|
||||
public:
|
||||
AiRuleBuildOneFarm(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 10000;}
|
||||
virtual string getName() const {return "No farms => Build one";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleProduceResourceProducer
|
||||
// =====================================================
|
||||
|
||||
class AiRuleProduceResourceProducer: public AiRule{
|
||||
private:
|
||||
static const int minStaticResources= 20;
|
||||
static const int longInterval= 60000;
|
||||
static const int shortInterval= 5000;
|
||||
const ResourceType *rt;
|
||||
int interval;
|
||||
|
||||
public:
|
||||
AiRuleProduceResourceProducer(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return interval;}
|
||||
virtual string getName() const {return "No resources => Build Resource Producer";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleProduce
|
||||
// =====================================================
|
||||
|
||||
class AiRuleProduce: public AiRule{
|
||||
private:
|
||||
const ProduceTask *produceTask;
|
||||
|
||||
public:
|
||||
AiRuleProduce(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 2000;}
|
||||
virtual string getName() const {return "Performing produce task";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
|
||||
private:
|
||||
void produceGeneric(const ProduceTask *pt);
|
||||
void produceSpecific(const ProduceTask *pt);
|
||||
};
|
||||
// =====================================================
|
||||
// class AiRuleBuild
|
||||
// =====================================================
|
||||
|
||||
class AiRuleBuild: public AiRule{
|
||||
private:
|
||||
const BuildTask *buildTask;
|
||||
|
||||
public:
|
||||
AiRuleBuild(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 2000;}
|
||||
virtual string getName() const {return "Performing build task";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
|
||||
private:
|
||||
void buildGeneric(const BuildTask *bt);
|
||||
void buildSpecific(const BuildTask *bt);
|
||||
void buildBestBuilding(const vector<const UnitType*> &buildings);
|
||||
|
||||
bool isDefensive(const UnitType *building);
|
||||
bool isResourceProducer(const UnitType *building);
|
||||
bool isWarriorProducer(const UnitType *building);
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleUpgrade
|
||||
// =====================================================
|
||||
|
||||
class AiRuleUpgrade: public AiRule{
|
||||
private:
|
||||
const UpgradeTask *upgradeTask;
|
||||
|
||||
public:
|
||||
AiRuleUpgrade(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 2000;}
|
||||
virtual string getName() const {return "Performing upgrade task";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
|
||||
private:
|
||||
void upgradeSpecific(const UpgradeTask *upgt);
|
||||
void upgradeGeneric(const UpgradeTask *upgt);
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class AiRuleExpand
|
||||
// =====================================================
|
||||
|
||||
class AiRuleExpand: public AiRule{
|
||||
private:
|
||||
static const int expandDistance= 30;
|
||||
|
||||
private:
|
||||
Vec2i expandPos;
|
||||
const UnitType *storeType;
|
||||
|
||||
public:
|
||||
AiRuleExpand(Ai *ai);
|
||||
|
||||
virtual int getTestInterval() const {return 30000;}
|
||||
virtual string getName() const {return "Expanding";}
|
||||
|
||||
virtual bool test();
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,304 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "path_finder.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include "config.h"
|
||||
#include "map.h"
|
||||
#include "unit.h"
|
||||
#include "unit_type.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class PathFinder
|
||||
// =====================================================
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
const int PathFinder::maxFreeSearchRadius= 10;
|
||||
const int PathFinder::pathFindNodesMax= 400;
|
||||
const int PathFinder::pathFindRefresh= 10;
|
||||
|
||||
|
||||
PathFinder::PathFinder(){
|
||||
nodePool= NULL;
|
||||
}
|
||||
|
||||
PathFinder::PathFinder(const Map *map){
|
||||
init(map);
|
||||
nodePool= NULL;
|
||||
}
|
||||
|
||||
void PathFinder::init(const Map *map){
|
||||
nodePool= new Node[pathFindNodesMax];
|
||||
this->map= map;
|
||||
}
|
||||
|
||||
PathFinder::~PathFinder(){
|
||||
delete [] nodePool;
|
||||
}
|
||||
|
||||
PathFinder::TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos){
|
||||
|
||||
//route cache
|
||||
UnitPath *path= unit->getPath();
|
||||
if(finalPos==unit->getPos()){
|
||||
//if arrived
|
||||
unit->setCurrSkill(scStop);
|
||||
return tsArrived;
|
||||
}
|
||||
else if(!path->isEmpty()){
|
||||
//route cache
|
||||
Vec2i pos= path->pop();
|
||||
if(map->canMove(unit, unit->getPos(), pos)){
|
||||
unit->setTargetPos(pos);
|
||||
return tsOnTheWay;
|
||||
}
|
||||
}
|
||||
|
||||
//route cache miss
|
||||
TravelState ts= aStar(unit, finalPos);
|
||||
|
||||
//post actions
|
||||
switch(ts){
|
||||
case tsBlocked:
|
||||
case tsArrived:
|
||||
unit->setCurrSkill(scStop);
|
||||
break;
|
||||
case tsOnTheWay:
|
||||
Vec2i pos= path->pop();
|
||||
if(map->canMove(unit, unit->getPos(), pos)){
|
||||
unit->setTargetPos(pos);
|
||||
}
|
||||
else{
|
||||
unit->setCurrSkill(scStop);
|
||||
return tsBlocked;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
//route a unit using A* algorithm
|
||||
PathFinder::TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
|
||||
|
||||
nodePoolCount= 0;
|
||||
const Vec2i finalPos= computeNearestFreePos(unit, targetPos);
|
||||
|
||||
//if arrived
|
||||
if(finalPos==unit->getPos()){
|
||||
return tsArrived;
|
||||
}
|
||||
|
||||
//path find algorithm
|
||||
|
||||
//a) push starting pos into openNodes
|
||||
Node *firstNode= newNode();
|
||||
assert(firstNode!=NULL);;
|
||||
firstNode->next= NULL;
|
||||
firstNode->prev= NULL;
|
||||
firstNode->pos= unit->getPos();
|
||||
firstNode->heuristic= heuristic(unit->getPos(), finalPos);
|
||||
firstNode->exploredCell= true;
|
||||
openNodes.push_back(firstNode);
|
||||
|
||||
//b) loop
|
||||
bool pathFound= true;
|
||||
bool nodeLimitReached= false;
|
||||
Node *node= NULL;
|
||||
|
||||
while(!nodeLimitReached){
|
||||
|
||||
//b1) is open nodes is empty => failed to find the path
|
||||
if(openNodes.empty()){
|
||||
pathFound= false;
|
||||
break;
|
||||
}
|
||||
|
||||
//b2) get the minimum heuristic node
|
||||
Nodes::iterator it = minHeuristic();
|
||||
node= *it;
|
||||
|
||||
//b3) if minHeuristic is the finalNode, or the path is no more explored => path was found
|
||||
if(node->pos==finalPos || !node->exploredCell){
|
||||
pathFound= true;
|
||||
break;
|
||||
}
|
||||
|
||||
//b4) move this node from closedNodes to openNodes
|
||||
//add all succesors that are not in closedNodes or openNodes to openNodes
|
||||
closedNodes.push_back(node);
|
||||
openNodes.erase(it);
|
||||
for(int i=-1; i<=1 && !nodeLimitReached; ++i){
|
||||
for(int j=-1; j<=1 && !nodeLimitReached; ++j){
|
||||
Vec2i sucPos= node->pos + Vec2i(i, j);
|
||||
if(!openPos(sucPos) && map->aproxCanMove(unit, node->pos, sucPos)){
|
||||
//if node is not open and canMove then generate another node
|
||||
Node *sucNode= newNode();
|
||||
if(sucNode!=NULL){
|
||||
sucNode->pos= sucPos;
|
||||
sucNode->heuristic= heuristic(sucNode->pos, finalPos);
|
||||
sucNode->prev= node;
|
||||
sucNode->next= NULL;
|
||||
sucNode->exploredCell= map->getSurfaceCell(Map::toSurfCoords(sucPos))->isExplored(unit->getTeam());
|
||||
openNodes.push_back(sucNode);
|
||||
}
|
||||
else{
|
||||
nodeLimitReached= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}//while
|
||||
|
||||
Node *lastNode= node;
|
||||
|
||||
//if consumed all nodes find best node (to avoid strage behaviour)
|
||||
if(nodeLimitReached){
|
||||
for(Nodes::iterator it= closedNodes.begin(); it!=closedNodes.end(); ++it){
|
||||
if((*it)->heuristic < lastNode->heuristic){
|
||||
lastNode= *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check results of path finding
|
||||
TravelState ts;
|
||||
UnitPath *path= unit->getPath();
|
||||
if(pathFound==false || lastNode==firstNode){
|
||||
//blocked
|
||||
ts= tsBlocked;
|
||||
path->incBlockCount();
|
||||
}
|
||||
else {
|
||||
//on the way
|
||||
ts= tsOnTheWay;
|
||||
|
||||
//build next pointers
|
||||
Node *currNode= lastNode;
|
||||
while(currNode->prev!=NULL){
|
||||
currNode->prev->next= currNode;
|
||||
currNode= currNode->prev;
|
||||
}
|
||||
//store path
|
||||
path->clear();
|
||||
|
||||
currNode= firstNode;
|
||||
for(int i=0; currNode->next!=NULL && i<pathFindRefresh; currNode= currNode->next, i++){
|
||||
path->push(currNode->next->pos);
|
||||
}
|
||||
}
|
||||
|
||||
//clean nodes
|
||||
openNodes.clear();
|
||||
closedNodes.clear();
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
PathFinder::Node *PathFinder::newNode(){
|
||||
if(nodePoolCount<pathFindNodesMax){
|
||||
Node *node= &nodePool[nodePoolCount];
|
||||
nodePoolCount++;
|
||||
return node;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Vec2i PathFinder::computeNearestFreePos(const Unit *unit, const Vec2i &finalPos){
|
||||
|
||||
//unit data
|
||||
Vec2i unitPos= unit->getPos();
|
||||
int size= unit->getType()->getSize();
|
||||
Field field= unit->getCurrField();
|
||||
int teamIndex= unit->getTeam();
|
||||
|
||||
//if finalPos is free return it
|
||||
if(map->isAproxFreeCells(finalPos, size, field, teamIndex)){
|
||||
return finalPos;
|
||||
}
|
||||
|
||||
//find nearest pos
|
||||
Vec2i nearestPos= unitPos;
|
||||
float nearestDist= unitPos.dist(finalPos);
|
||||
for(int i= -maxFreeSearchRadius; i<=maxFreeSearchRadius; ++i){
|
||||
for(int j= -maxFreeSearchRadius; j<=maxFreeSearchRadius; ++j){
|
||||
Vec2i currPos= finalPos + Vec2i(i, j);
|
||||
if(map->isAproxFreeCells(currPos, size, field, teamIndex)){
|
||||
float dist= currPos.dist(finalPos);
|
||||
|
||||
//if nearer from finalPos
|
||||
if(dist<nearestDist){
|
||||
nearestPos= currPos;
|
||||
nearestDist= dist;
|
||||
}
|
||||
//if the distance is the same compare distance to unit
|
||||
else if(dist==nearestDist){
|
||||
if(currPos.dist(unitPos)<nearestPos.dist(unitPos)){
|
||||
nearestPos= currPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nearestPos;
|
||||
}
|
||||
|
||||
float PathFinder::heuristic(const Vec2i &pos, const Vec2i &finalPos){
|
||||
return pos.dist(finalPos);
|
||||
}
|
||||
|
||||
//returns an iterator to the lowest heuristic node
|
||||
PathFinder::Nodes::iterator PathFinder::minHeuristic(){
|
||||
|
||||
Nodes::iterator minNodeIt= openNodes.begin();
|
||||
|
||||
assert(!openNodes.empty());
|
||||
|
||||
for(Nodes::iterator it= openNodes.begin(); it!=openNodes.end(); ++it){
|
||||
if((*it)->heuristic < (*minNodeIt)->heuristic){
|
||||
minNodeIt= it;
|
||||
}
|
||||
}
|
||||
|
||||
return minNodeIt;
|
||||
}
|
||||
|
||||
bool PathFinder::openPos(const Vec2i &sucPos){
|
||||
|
||||
for(Nodes::reverse_iterator it= closedNodes.rbegin(); it!=closedNodes.rend(); ++it){
|
||||
if(sucPos==(*it)->pos){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//use reverse iterator to find a node faster
|
||||
for(Nodes::reverse_iterator it= openNodes.rbegin(); it!=openNodes.rend(); ++it){
|
||||
if(sucPos==(*it)->pos){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}} //end namespace
|
|
@ -0,0 +1,79 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_PATHFINDER_H_
|
||||
#define _GLEST_GAME_PATHFINDER_H_
|
||||
|
||||
#include "vec.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using std::vector;
|
||||
using Shared::Graphics::Vec2i;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class Map;
|
||||
class Unit;
|
||||
|
||||
// =====================================================
|
||||
// class PathFinder
|
||||
//
|
||||
/// Finds paths for units using a modification of the A* algorithm
|
||||
// =====================================================
|
||||
|
||||
class PathFinder{
|
||||
public:
|
||||
enum TravelState{
|
||||
tsArrived,
|
||||
tsOnTheWay,
|
||||
tsBlocked
|
||||
};
|
||||
struct Node{
|
||||
Vec2i pos;
|
||||
Node *next;
|
||||
Node *prev;
|
||||
float heuristic;
|
||||
bool exploredCell;
|
||||
};
|
||||
typedef vector<Node*> Nodes;
|
||||
|
||||
public:
|
||||
static const int maxFreeSearchRadius;
|
||||
static const int pathFindNodesMax;
|
||||
static const int pathFindRefresh;
|
||||
|
||||
private:
|
||||
Nodes openNodes;
|
||||
Nodes closedNodes;
|
||||
Node *nodePool;
|
||||
int nodePoolCount;
|
||||
const Map *map;
|
||||
|
||||
public:
|
||||
PathFinder();
|
||||
PathFinder(const Map *map);
|
||||
~PathFinder();
|
||||
void init(const Map *map);
|
||||
TravelState findPath(Unit *unit, const Vec2i &finalPos);
|
||||
|
||||
private:
|
||||
TravelState aStar(Unit *unit, const Vec2i &finalPos);
|
||||
Node *newNode();
|
||||
Vec2i computeNearestFreePos(const Unit *unit, const Vec2i &targetPos);
|
||||
float heuristic(const Vec2i &pos, const Vec2i &finalPos);
|
||||
Nodes::iterator minHeuristic();
|
||||
bool openPos(const Vec2i &sucPos);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,82 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2009 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "auto_test.h"
|
||||
|
||||
#include "program.h"
|
||||
#include "main_menu.h"
|
||||
#include "menu_state_new_game.h"
|
||||
#include "menu_state_scenario.h"
|
||||
#include "game.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class AutoTest
|
||||
// =====================================================
|
||||
|
||||
const time_t AutoTest::invalidTime = -1;
|
||||
const time_t AutoTest::gameTime = 60*20;
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
AutoTest::AutoTest(){
|
||||
gameStartTime = invalidTime;
|
||||
random.init(time(NULL));
|
||||
}
|
||||
|
||||
AutoTest & AutoTest::getInstance(){
|
||||
static AutoTest autoTest;
|
||||
return autoTest;
|
||||
}
|
||||
|
||||
void AutoTest::updateIntro(Program *program){
|
||||
program->setState(new MainMenu(program));
|
||||
}
|
||||
|
||||
void AutoTest::updateRoot(Program *program, MainMenu *mainMenu){
|
||||
mainMenu->setState(new MenuStateNewGame(program, mainMenu));
|
||||
}
|
||||
|
||||
void AutoTest::updateNewGame(Program *program, MainMenu *mainMenu){
|
||||
mainMenu->setState(new MenuStateScenario(program, mainMenu, "scenarios"));
|
||||
}
|
||||
|
||||
void AutoTest::updateScenario(MenuStateScenario *menuStateScenario){
|
||||
gameStartTime = invalidTime;
|
||||
|
||||
int scenarioIndex = random.randRange(0, menuStateScenario->getScenarioCount()-1);
|
||||
menuStateScenario->setScenario(scenarioIndex);
|
||||
|
||||
menuStateScenario->launchGame();
|
||||
}
|
||||
|
||||
void AutoTest::updateGame(Game *game){
|
||||
|
||||
// record start time
|
||||
if(gameStartTime==invalidTime)
|
||||
{
|
||||
gameStartTime = time(NULL);
|
||||
}
|
||||
|
||||
// quit if we've espend enough time in the game
|
||||
if(time(NULL)-gameStartTime>gameTime){
|
||||
game->quitGame();
|
||||
}
|
||||
}
|
||||
|
||||
void AutoTest::updateBattleEnd(Program *program){
|
||||
program->setState(new MainMenu(program));
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,57 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2009 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _SHARED_UTIL_AUTO_TEST_H_
|
||||
#define _SHARED_UTIL_AUTO_TEST_H_
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "random.h"
|
||||
|
||||
using Shared::Util::Random;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class Program;
|
||||
class MainMenu;
|
||||
class MenuStateScenario;
|
||||
class Game;
|
||||
|
||||
// =====================================================
|
||||
// class AutoTest
|
||||
//
|
||||
/// Interface to write log files
|
||||
// =====================================================
|
||||
|
||||
class AutoTest{
|
||||
private:
|
||||
int gameStartTime;
|
||||
Random random;
|
||||
|
||||
private:
|
||||
static const time_t invalidTime;
|
||||
static const time_t gameTime;
|
||||
|
||||
public:
|
||||
static AutoTest & getInstance();
|
||||
AutoTest();
|
||||
|
||||
void updateIntro(Program *program);
|
||||
void updateRoot(Program *program, MainMenu *mainMenu);
|
||||
void updateNewGame(Program *program, MainMenu *mainMenu);
|
||||
void updateScenario(MenuStateScenario *menuStateScenario);
|
||||
void updateGame(Game *game);
|
||||
void updateBattleEnd(Program *program);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,248 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "components.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#include "metrics.h"
|
||||
#include "core_data.h"
|
||||
#include "platform_util.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class GraphicComponent
|
||||
// =====================================================
|
||||
|
||||
float GraphicComponent::anim= 0.f;
|
||||
float GraphicComponent::fade= 0.f;
|
||||
const float GraphicComponent::animSpeed= 0.02f;
|
||||
const float GraphicComponent::fadeSpeed= 0.01f;
|
||||
|
||||
GraphicComponent::GraphicComponent(){
|
||||
enabled= true;
|
||||
}
|
||||
|
||||
void GraphicComponent::init(int x, int y, int w, int h){
|
||||
this->x= x;
|
||||
this->y= y;
|
||||
this->w= w;
|
||||
this->h= h;
|
||||
font= CoreData::getInstance().getMenuFontNormal();
|
||||
enabled= true;
|
||||
}
|
||||
|
||||
bool GraphicComponent::mouseMove(int x, int y){
|
||||
return
|
||||
x > this->x &&
|
||||
y > this->y &&
|
||||
x < this->x + w &&
|
||||
y < this->y + h;
|
||||
}
|
||||
|
||||
bool GraphicComponent::mouseClick(int x, int y){
|
||||
return mouseMove(x, y);
|
||||
}
|
||||
|
||||
void GraphicComponent::update(){
|
||||
fade+= fadeSpeed;
|
||||
anim+= animSpeed;
|
||||
if(fade>1.f) fade= 1.f;
|
||||
if(anim>1.f) anim= 0.f;
|
||||
}
|
||||
|
||||
void GraphicComponent::resetFade(){
|
||||
fade= 0.f;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class GraphicLabel
|
||||
// =====================================================
|
||||
|
||||
const int GraphicLabel::defH= 20;
|
||||
const int GraphicLabel::defW= 70;
|
||||
|
||||
void GraphicLabel::init(int x, int y, int w, int h, bool centered){
|
||||
GraphicComponent::init(x, y, w, h);
|
||||
this->centered= centered;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class GraphicButton
|
||||
// =====================================================
|
||||
|
||||
const int GraphicButton::defH= 22;
|
||||
const int GraphicButton::defW= 90;
|
||||
|
||||
void GraphicButton::init(int x, int y, int w, int h){
|
||||
GraphicComponent::init(x, y, w, h);
|
||||
lighted= false;
|
||||
}
|
||||
|
||||
bool GraphicButton::mouseMove(int x, int y){
|
||||
bool b= GraphicComponent::mouseMove(x, y);
|
||||
lighted= b;
|
||||
return b;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class GraphicListBox
|
||||
// =====================================================
|
||||
|
||||
const int GraphicListBox::defH= 22;
|
||||
const int GraphicListBox::defW= 140;
|
||||
|
||||
void GraphicListBox::init(int x, int y, int w, int h){
|
||||
GraphicComponent::init(x, y, w, h);
|
||||
|
||||
graphButton1.init(x, y, 22, h);
|
||||
graphButton2.init(x+w-22, y, 22, h);
|
||||
graphButton1.setText("<");
|
||||
graphButton2.setText(">");
|
||||
selectedItemIndex=-1;
|
||||
}
|
||||
|
||||
//queryes
|
||||
void GraphicListBox::pushBackItem(string item){
|
||||
items.push_back(item);
|
||||
setSelectedItemIndex(0);
|
||||
}
|
||||
|
||||
void GraphicListBox::setItems(const vector<string> &items){
|
||||
this->items= items;
|
||||
setSelectedItemIndex(0);
|
||||
}
|
||||
|
||||
void GraphicListBox::setSelectedItemIndex(int index){
|
||||
assert(index>=0 && index<items.size());
|
||||
selectedItemIndex= index;
|
||||
setText(getSelectedItem());
|
||||
}
|
||||
|
||||
void GraphicListBox::setSelectedItem(string item){
|
||||
vector<string>::iterator iter;
|
||||
|
||||
iter= find(items.begin(), items.end(), item);
|
||||
|
||||
if(iter==items.end()){
|
||||
throw runtime_error("Value not found on list box: "+item);
|
||||
}
|
||||
|
||||
setSelectedItemIndex(iter-items.begin());
|
||||
|
||||
}
|
||||
|
||||
bool GraphicListBox::mouseMove(int x, int y){
|
||||
return
|
||||
graphButton1.mouseMove(x, y) ||
|
||||
graphButton2.mouseMove(x, y);
|
||||
}
|
||||
|
||||
bool GraphicListBox::mouseClick(int x, int y){
|
||||
if(!items.empty()){
|
||||
bool b1= graphButton1.mouseClick(x, y);
|
||||
bool b2= graphButton2.mouseClick(x, y);
|
||||
|
||||
if(b1){
|
||||
selectedItemIndex--;
|
||||
if(selectedItemIndex<0){
|
||||
selectedItemIndex=items.size()-1;
|
||||
}
|
||||
}
|
||||
else if(b2){
|
||||
selectedItemIndex++;
|
||||
if(selectedItemIndex>=items.size()){
|
||||
selectedItemIndex=0;
|
||||
}
|
||||
}
|
||||
setText(getSelectedItem());
|
||||
|
||||
return b1 || b2;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class GraphicMessageBox
|
||||
// =====================================================
|
||||
|
||||
const int GraphicMessageBox::defH= 240;
|
||||
const int GraphicMessageBox::defW= 350;
|
||||
|
||||
void GraphicMessageBox::init(const string &button1Str, const string &button2Str){
|
||||
init(button1Str);
|
||||
|
||||
button1.init(x+(w-GraphicButton::defW)/4, y+25);
|
||||
button1.setText(button1Str);
|
||||
button2.init(x+3*(w-GraphicButton::defW)/4, y+25);
|
||||
button2.setText(button2Str);
|
||||
buttonCount= 2;
|
||||
}
|
||||
|
||||
void GraphicMessageBox::init(const string &button1Str){
|
||||
font= CoreData::getInstance().getMenuFontNormal();
|
||||
|
||||
h= defH;
|
||||
w= defW;
|
||||
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
|
||||
x= (metrics.getVirtualW()-w)/2;
|
||||
y= (metrics.getVirtualH()-h)/2;
|
||||
|
||||
button1.init(x+(w-GraphicButton::defW)/2, y+25);
|
||||
button1.setText(button1Str);
|
||||
buttonCount= 1;
|
||||
}
|
||||
|
||||
bool GraphicMessageBox::mouseMove(int x, int y){
|
||||
return button1.mouseMove(x, y) || button2.mouseMove(x, y);
|
||||
}
|
||||
|
||||
bool GraphicMessageBox::mouseClick(int x, int y){
|
||||
bool b1= button1.mouseClick(x, y);
|
||||
bool b2= button2.mouseClick(x, y);
|
||||
if(buttonCount==1){
|
||||
return b1;
|
||||
}
|
||||
else{
|
||||
return b1 ||b2;
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicMessageBox::mouseClick(int x, int y, int &clickedButton){
|
||||
bool b1= button1.mouseClick(x, y);
|
||||
bool b2= button2.mouseClick(x, y);
|
||||
|
||||
if(buttonCount==1){
|
||||
clickedButton= 1;
|
||||
return b1;
|
||||
}
|
||||
else{
|
||||
if(b1){
|
||||
clickedButton= 1;
|
||||
return true;
|
||||
}
|
||||
else if(b2){
|
||||
clickedButton= 2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,182 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_GRAPHCOMPONENT_H_
|
||||
#define _GLEST_GAME_GRAPHCOMPONENT_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "font.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
using Shared::Graphics::Font2D;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// ===========================================================
|
||||
// class GraphicComponent
|
||||
//
|
||||
// OpenGL renderer GUI components
|
||||
// ===========================================================
|
||||
|
||||
class GraphicComponent{
|
||||
public:
|
||||
static const float animSpeed;
|
||||
static const float fadeSpeed;
|
||||
|
||||
protected:
|
||||
int x, y, w, h;
|
||||
string text;
|
||||
const Font2D *font;
|
||||
bool enabled;
|
||||
|
||||
static float anim;
|
||||
static float fade;
|
||||
|
||||
public:
|
||||
GraphicComponent();
|
||||
virtual ~GraphicComponent(){}
|
||||
|
||||
void init(int x, int y, int w, int h);
|
||||
|
||||
int getX() const {return x;}
|
||||
int getY() const {return y;}
|
||||
int getW() const {return w;}
|
||||
int getH() const {return h;}
|
||||
const string &getText() const {return text;}
|
||||
const Font2D *getFont() const {return font;}
|
||||
bool getEnabled() const {return enabled;}
|
||||
|
||||
void setX(int x) {this->x= x;}
|
||||
void setY(int y) {this->y= y;}
|
||||
void setText(const string &text) {this->text= text;}
|
||||
void setFont(const Font2D *font) {this->font= font;}
|
||||
void setEnabled(bool enabled) {this->enabled= enabled;}
|
||||
|
||||
virtual bool mouseMove(int x, int y);
|
||||
virtual bool mouseClick(int x, int y);
|
||||
|
||||
static void update();
|
||||
static void resetFade();
|
||||
static float getAnim() {return anim;}
|
||||
static float getFade() {return fade;}
|
||||
};
|
||||
|
||||
// ===========================================================
|
||||
// class GraphicLabel
|
||||
// ===========================================================
|
||||
|
||||
class GraphicLabel: public GraphicComponent{
|
||||
public:
|
||||
static const int defH;
|
||||
static const int defW;
|
||||
|
||||
private:
|
||||
bool centered;
|
||||
|
||||
public:
|
||||
void init(int x, int y, int w=defW, int h=defH, bool centered= false);
|
||||
|
||||
bool getCentered() const {return centered;}
|
||||
|
||||
void setCentered(bool centered) {this->centered= centered;}
|
||||
};
|
||||
|
||||
// ===========================================================
|
||||
// class GraphicButton
|
||||
// ===========================================================
|
||||
|
||||
class GraphicButton: public GraphicComponent{
|
||||
public:
|
||||
static const int defH;
|
||||
static const int defW;
|
||||
|
||||
private:
|
||||
bool lighted;
|
||||
|
||||
public:
|
||||
void init(int x, int y, int w=defW, int h=defH);
|
||||
|
||||
bool getLighted() const {return lighted;}
|
||||
|
||||
void setLighted(bool lighted) {this->lighted= lighted;}
|
||||
virtual bool mouseMove(int x, int y);
|
||||
};
|
||||
|
||||
// ===========================================================
|
||||
// class GraphicListBox
|
||||
// ===========================================================
|
||||
|
||||
class GraphicListBox: public GraphicComponent{
|
||||
public:
|
||||
static const int defH;
|
||||
static const int defW;
|
||||
|
||||
private:
|
||||
GraphicButton graphButton1, graphButton2;
|
||||
vector<string> items;
|
||||
int selectedItemIndex;
|
||||
|
||||
public:
|
||||
void init(int x, int y, int w=defW, int h=defH);
|
||||
|
||||
int getItemCount() const {return items.size();}
|
||||
int getSelectedItemIndex() const {return selectedItemIndex;}
|
||||
string getSelectedItem() const {return items[selectedItemIndex];}
|
||||
const GraphicButton *getButton1() const {return &graphButton1;}
|
||||
const GraphicButton *getButton2() const {return &graphButton2;}
|
||||
|
||||
void pushBackItem(string item);
|
||||
void setItems(const vector<string> &items);
|
||||
void setSelectedItemIndex(int index);
|
||||
void setSelectedItem(string item);
|
||||
|
||||
virtual bool mouseMove(int x, int y);
|
||||
virtual bool mouseClick(int x, int y);
|
||||
};
|
||||
|
||||
// ===========================================================
|
||||
// class GraphicMessageBox
|
||||
// ===========================================================
|
||||
|
||||
class GraphicMessageBox: public GraphicComponent{
|
||||
public:
|
||||
static const int defH;
|
||||
static const int defW;
|
||||
|
||||
private:
|
||||
GraphicButton button1;
|
||||
GraphicButton button2;
|
||||
int buttonCount;
|
||||
string header;
|
||||
|
||||
public:
|
||||
void init(const string &button1Str, const string &button2Str);
|
||||
void init(const string &button1Str);
|
||||
|
||||
int getButtonCount() const {return buttonCount;}
|
||||
const GraphicButton *getButton1() const {return &button1;}
|
||||
const GraphicButton *getButton2() const {return &button2;}
|
||||
string getHeader() const {return header;}
|
||||
|
||||
void setHeader(string header) {this->header= header;}
|
||||
|
||||
virtual bool mouseMove(int x, int y);
|
||||
virtual bool mouseClick(int x, int y);
|
||||
bool mouseClick(int x, int y, int &clickedButton);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,104 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "game_util.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "lang.h"
|
||||
#include "game_constants.h"
|
||||
#include "config.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
const string mailString= "contact_game@glest.org";
|
||||
const string glestVersionString= "v3.2.3-beta3";
|
||||
|
||||
string getCrashDumpFileName(){
|
||||
return "glest"+glestVersionString+".dmp";
|
||||
}
|
||||
|
||||
string getNetworkVersionString(){
|
||||
return glestVersionString + " - " + string(__DATE__) + " - " + string(__TIME__);
|
||||
}
|
||||
|
||||
string getAboutString1(int i){
|
||||
switch(i){
|
||||
case 0: return "Glest " + glestVersionString + " (" + "Shared Library " + sharedLibVersionString + ")";
|
||||
case 1: return "Built: " + string(__DATE__);
|
||||
case 2: return "Copyright 2001-2009 The Glest Team";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
string getAboutString2(int i){
|
||||
switch(i){
|
||||
case 0: return "Web: http://glest.org";
|
||||
case 1: return "Mail: " + mailString;
|
||||
case 2: return "Irc: irc://irc.freenode.net/glest";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
string getTeammateName(int i){
|
||||
switch(i){
|
||||
case 0: return "Marti<EFBFBD>o Figueroa";
|
||||
case 1: return "Jos<EFBFBD> Luis Gonz<6E>lez";
|
||||
case 2: return "Tucho Fern<72>ndez";
|
||||
case 3: return "Jos<EFBFBD> Zanni";
|
||||
case 4: return "F<EFBFBD>lix Men<65>ndez";
|
||||
case 5: return "Marcos Caruncho";
|
||||
case 6: return "Matthias Braun";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
string getTeammateRole(int i){
|
||||
Lang &l= Lang::getInstance();
|
||||
|
||||
switch(i){
|
||||
case 0: return l.get("Programming");
|
||||
case 1: return l.get("SoundAndMusic");
|
||||
case 2: return l.get("3dAnd2dArt");
|
||||
case 3: return l.get("2dArtAndWeb");
|
||||
case 4: return l.get("Animation");
|
||||
case 5: return l.get("3dArt");
|
||||
case 6: return l.get("LinuxPort");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
string formatString(const string &str){
|
||||
string outStr = str;
|
||||
|
||||
if(!outStr.empty()){
|
||||
outStr[0]= toupper(outStr[0]);
|
||||
}
|
||||
|
||||
bool afterSeparator= false;
|
||||
for(int i= 0; i<str.size(); ++i){
|
||||
if(outStr[i]=='_'){
|
||||
outStr[i]= ' ';
|
||||
}
|
||||
else if(afterSeparator){
|
||||
outStr[i]= toupper(outStr[i]);
|
||||
afterSeparator= false;
|
||||
}
|
||||
if(outStr[i]=='\n' || outStr[i]=='(' || outStr[i]==' '){
|
||||
afterSeparator= true;
|
||||
}
|
||||
}
|
||||
return outStr;
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,40 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_GAMEUTIL_H_
|
||||
#define _GLEST_GAME_GAMEUTIL_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
using std::string;
|
||||
using Shared::Util::sharedLibVersionString;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
extern const string mailString;
|
||||
extern const string glestVersionString;
|
||||
extern const string networkVersionString;
|
||||
|
||||
string getCrashDumpFileName();
|
||||
string getNetworkVersionString();
|
||||
string getAboutString1(int i);
|
||||
string getAboutString2(int i);
|
||||
string getTeammateName(int i);
|
||||
string getTeammateRole(int i);
|
||||
|
||||
string formatString(const string &str);
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,94 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "metrics.h"
|
||||
#include "lang.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Graphics;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Logger
|
||||
// =====================================================
|
||||
|
||||
const int Logger::logLineCount= 15;
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
Logger::Logger(){
|
||||
fileName= "log.txt";
|
||||
}
|
||||
|
||||
Logger & Logger::getInstance(){
|
||||
static Logger logger;
|
||||
return logger;
|
||||
}
|
||||
|
||||
void Logger::add(const string &str, bool renderScreen){
|
||||
FILE *f=fopen(fileName.c_str(), "at+");
|
||||
if(f!=NULL){
|
||||
fprintf(f, "%s\n", str.c_str());
|
||||
fclose(f);
|
||||
}
|
||||
current= str;
|
||||
if(renderScreen){
|
||||
renderLoadingScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::clear(){
|
||||
string s="Log file\n";
|
||||
|
||||
FILE *f= fopen(fileName.c_str(), "wt+");
|
||||
if(f==NULL){
|
||||
throw runtime_error("Error opening log file"+ fileName);
|
||||
}
|
||||
|
||||
fprintf(f, "%s", s.c_str());
|
||||
fprintf(f, "\n");
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
void Logger::renderLoadingScreen(){
|
||||
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
|
||||
renderer.reset2d();
|
||||
renderer.clearBuffers();
|
||||
|
||||
renderer.renderBackground(CoreData::getInstance().getBackgroundTexture());
|
||||
|
||||
renderer.renderText(
|
||||
state, coreData.getMenuFontBig(), Vec3f(1.f),
|
||||
metrics.getVirtualW()/4, 65*metrics.getVirtualH()/100, false);
|
||||
|
||||
renderer.renderText(
|
||||
current, coreData.getMenuFontNormal(), 1.0f,
|
||||
metrics.getVirtualW()/4,
|
||||
62*metrics.getVirtualH()/100, false);
|
||||
|
||||
renderer.swapBuffers();
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,60 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _SHARED_UTIL_LOGGER_H_
|
||||
#define _SHARED_UTIL_LOGGER_H_
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
|
||||
using std::string;
|
||||
using std::deque;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Logger
|
||||
//
|
||||
/// Interface to write log files
|
||||
// =====================================================
|
||||
|
||||
class Logger{
|
||||
private:
|
||||
static const int logLineCount;
|
||||
|
||||
private:
|
||||
typedef deque<string> Strings;
|
||||
|
||||
private:
|
||||
string fileName;
|
||||
string state;
|
||||
string subtitle;
|
||||
string current;
|
||||
|
||||
private:
|
||||
Logger();
|
||||
|
||||
public:
|
||||
static Logger & getInstance();
|
||||
|
||||
void setFile(const string &fileName) {this->fileName= fileName;}
|
||||
void setState(const string &state) {this->state= state;}
|
||||
void setSubtitle(const string &subtitle) {this->subtitle= subtitle;}
|
||||
|
||||
void add(const string &str, bool renderScreen= false);
|
||||
void renderLoadingScreen();
|
||||
|
||||
void clear();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,103 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "chat_manager.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "console.h"
|
||||
#include "network_manager.h"
|
||||
#include "lang.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class ChatManager
|
||||
// =====================================================
|
||||
|
||||
const int ChatManager::maxTextLenght= 64;
|
||||
|
||||
ChatManager::ChatManager(){
|
||||
console= NULL;
|
||||
editEnabled= false;
|
||||
teamMode= false;
|
||||
thisTeamIndex= -1;
|
||||
}
|
||||
|
||||
void ChatManager::init(Console* console, int thisTeamIndex){
|
||||
this->console= console;
|
||||
this->thisTeamIndex= thisTeamIndex;
|
||||
}
|
||||
|
||||
void ChatManager::keyDown(char key){
|
||||
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
//toggle team mode
|
||||
if(!editEnabled && key=='H'){
|
||||
if(teamMode){
|
||||
teamMode= false;
|
||||
console->addLine(lang.get("ChatMode") + ": " + lang.get("All"));
|
||||
}
|
||||
else{
|
||||
teamMode= true;
|
||||
console->addLine(lang.get("ChatMode") + ": " + lang.get("Team"));
|
||||
}
|
||||
}
|
||||
|
||||
if(key==vkReturn){
|
||||
if(editEnabled){
|
||||
GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
|
||||
|
||||
editEnabled= false;
|
||||
if(!text.empty()){
|
||||
console->addLine(gameNetworkInterface->getHostName() + ": " + text);
|
||||
gameNetworkInterface->sendTextMessage(text, teamMode? thisTeamIndex: -1);
|
||||
}
|
||||
}
|
||||
else{
|
||||
editEnabled= true;
|
||||
text.clear();
|
||||
}
|
||||
}
|
||||
else if(key==vkBack){
|
||||
if(!text.empty()){
|
||||
text.erase(text.end() -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatManager::keyPress(char c){
|
||||
if(editEnabled && text.size()<maxTextLenght){
|
||||
//space is the first meaningful code
|
||||
if(c>=' '){
|
||||
text+= c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatManager::updateNetwork(){
|
||||
GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
|
||||
string text;
|
||||
string sender;
|
||||
|
||||
if(!gameNetworkInterface->getChatText().empty()){
|
||||
int teamIndex= gameNetworkInterface->getChatTeamIndex();
|
||||
|
||||
if(teamIndex==-1 || teamIndex==thisTeamIndex){
|
||||
console->addLine(gameNetworkInterface->getChatSender()+": "+gameNetworkInterface->getChatText(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,53 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_CHATMANAGER_H_
|
||||
#define _GLEST_GAME_CHATMANAGER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class Console;
|
||||
|
||||
// =====================================================
|
||||
// class ChatManager
|
||||
// =====================================================
|
||||
|
||||
class ChatManager{
|
||||
private:
|
||||
static const int maxTextLenght;
|
||||
|
||||
private:
|
||||
bool editEnabled;
|
||||
bool teamMode;
|
||||
Console* console;
|
||||
string text;
|
||||
int thisTeamIndex;
|
||||
|
||||
public:
|
||||
ChatManager();
|
||||
void init(Console* console, int thisTeamIndex);
|
||||
|
||||
void keyDown(char key);
|
||||
void keyPress(char c);
|
||||
void updateNetwork();
|
||||
|
||||
bool getEditEnabled() const {return editEnabled;}
|
||||
bool getTeamMode() const {return teamMode;}
|
||||
string getText() const {return text;}
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,310 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "commander.h"
|
||||
|
||||
#include "world.h"
|
||||
#include "unit.h"
|
||||
#include "conversion.h"
|
||||
#include "upgrade.h"
|
||||
#include "command.h"
|
||||
#include "command_type.h"
|
||||
#include "network_manager.h"
|
||||
#include "console.h"
|
||||
#include "config.h"
|
||||
#include "platform_util.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Platform;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Commander
|
||||
// =====================================================
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
void Commander::init(World *world){
|
||||
this->world= world;
|
||||
}
|
||||
|
||||
CommandResult Commander::tryGiveCommand(const Unit* unit, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType) const{
|
||||
NetworkCommand networkCommand(nctGiveCommand, unit->getId(), commandType->getId(), pos, unitType->getId());
|
||||
return pushNetworkCommand(&networkCommand);
|
||||
}
|
||||
|
||||
CommandResult Commander::tryGiveCommand(const Selection *selection, CommandClass commandClass, const Vec2i &pos, const Unit *targetUnit) const{
|
||||
|
||||
if(!selection->isEmpty()){
|
||||
Vec2i refPos, currPos;
|
||||
CommandResultContainer results;
|
||||
|
||||
refPos= computeRefPos(selection);
|
||||
|
||||
//give orders to all selected units
|
||||
for(int i=0; i<selection->getCount(); ++i){
|
||||
const Unit *unit= selection->getUnit(i);
|
||||
const CommandType *ct= unit->getType()->getFirstCtOfClass(commandClass);
|
||||
if(ct!=NULL){
|
||||
int targetId= targetUnit==NULL? Unit::invalidId: targetUnit->getId();
|
||||
int unitId= selection->getUnit(i)->getId();
|
||||
Vec2i currPos= computeDestPos(refPos, selection->getUnit(i)->getPos(), pos);
|
||||
NetworkCommand networkCommand(nctGiveCommand, unitId, ct->getId(), currPos, -1, targetId);
|
||||
|
||||
//every unit is ordered to a different pos
|
||||
CommandResult result= pushNetworkCommand(&networkCommand);
|
||||
results.push_back(result);
|
||||
}
|
||||
else{
|
||||
results.push_back(crFailUndefined);
|
||||
}
|
||||
}
|
||||
return computeResult(results);
|
||||
}
|
||||
else{
|
||||
return crFailUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
CommandResult Commander::tryGiveCommand(const Selection *selection, const CommandType *commandType, const Vec2i &pos, const Unit *targetUnit) const{
|
||||
if(!selection->isEmpty() && commandType!=NULL){
|
||||
Vec2i refPos;
|
||||
CommandResultContainer results;
|
||||
|
||||
refPos= computeRefPos(selection);
|
||||
|
||||
//give orders to all selected units
|
||||
for(int i=0; i<selection->getCount(); ++i){
|
||||
int targetId= targetUnit==NULL? Unit::invalidId: targetUnit->getId();
|
||||
int unitId= selection->getUnit(i)->getId();
|
||||
Vec2i currPos= computeDestPos(refPos, selection->getUnit(i)->getPos(), pos);
|
||||
NetworkCommand networkCommand(nctGiveCommand, unitId, commandType->getId(), currPos, -1, targetId);
|
||||
|
||||
//every unit is ordered to a different position
|
||||
CommandResult result= pushNetworkCommand(&networkCommand);
|
||||
results.push_back(result);
|
||||
}
|
||||
|
||||
return computeResult(results);
|
||||
}
|
||||
else{
|
||||
return crFailUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
//auto command
|
||||
CommandResult Commander::tryGiveCommand(const Selection *selection, const Vec2i &pos, const Unit *targetUnit) const{
|
||||
if(!selection->isEmpty()){
|
||||
|
||||
Vec2i refPos, currPos;
|
||||
CommandResultContainer results;
|
||||
|
||||
//give orders to all selected units
|
||||
refPos= computeRefPos(selection);
|
||||
for(int i=0; i<selection->getCount(); ++i){
|
||||
|
||||
//every unit is ordered to a different pos
|
||||
currPos= computeDestPos(refPos, selection->getUnit(i)->getPos(), pos);
|
||||
|
||||
//get command type
|
||||
const CommandType *commandType= selection->getUnit(i)->computeCommandType(pos, targetUnit);
|
||||
|
||||
//give commands
|
||||
if(commandType!=NULL){
|
||||
int targetId= targetUnit==NULL? Unit::invalidId: targetUnit->getId();
|
||||
int unitId= selection->getUnit(i)->getId();
|
||||
NetworkCommand networkCommand(nctGiveCommand, unitId, commandType->getId(), currPos, -1, targetId);
|
||||
|
||||
CommandResult result= pushNetworkCommand(&networkCommand);
|
||||
results.push_back(result);
|
||||
}
|
||||
else{
|
||||
results.push_back(crFailUndefined);
|
||||
}
|
||||
}
|
||||
return computeResult(results);
|
||||
}
|
||||
else{
|
||||
return crFailUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
CommandResult Commander::tryCancelCommand(const Selection *selection) const{
|
||||
|
||||
for(int i=0; i<selection->getCount(); ++i){
|
||||
NetworkCommand command(nctCancelCommand, selection->getUnit(i)->getId());
|
||||
pushNetworkCommand(&command);
|
||||
}
|
||||
|
||||
return crSuccess;
|
||||
}
|
||||
|
||||
void Commander::trySetMeetingPoint(const Unit* unit, const Vec2i &pos)const{
|
||||
NetworkCommand command(nctSetMeetingPoint, unit->getId(), -1, pos);
|
||||
pushNetworkCommand(&command);
|
||||
}
|
||||
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
Vec2i Commander::computeRefPos(const Selection *selection) const{
|
||||
Vec2i total= Vec2i(0);
|
||||
for(int i=0; i<selection->getCount(); ++i){
|
||||
total= total+selection->getUnit(i)->getPos();
|
||||
}
|
||||
|
||||
return Vec2i(total.x/ selection->getCount(), total.y/ selection->getCount());
|
||||
}
|
||||
|
||||
Vec2i Commander::computeDestPos(const Vec2i &refUnitPos, const Vec2i &unitPos, const Vec2i &commandPos) const{
|
||||
Vec2i pos;
|
||||
Vec2i posDiff= unitPos-refUnitPos;
|
||||
|
||||
if(abs(posDiff.x)>=3){
|
||||
posDiff.x= posDiff.x % 3;
|
||||
}
|
||||
|
||||
if(abs(posDiff.y)>=3){
|
||||
posDiff.y= posDiff.y % 3;
|
||||
}
|
||||
|
||||
pos= commandPos+posDiff;
|
||||
world->getMap()->clampPos(pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
CommandResult Commander::computeResult(const CommandResultContainer &results) const{
|
||||
switch(results.size()){
|
||||
case 0:
|
||||
return crFailUndefined;
|
||||
case 1:
|
||||
return results.front();
|
||||
default:
|
||||
for(int i=0; i<results.size(); ++i){
|
||||
if(results[i]!=crSuccess){
|
||||
return crSomeFailed;
|
||||
}
|
||||
}
|
||||
return crSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
CommandResult Commander::pushNetworkCommand(const NetworkCommand* networkCommand) const{
|
||||
GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
|
||||
const Unit* unit= world->findUnitById(networkCommand->getUnitId());
|
||||
CommandResult cr= crSuccess;
|
||||
|
||||
//validate unit
|
||||
if(unit==NULL){
|
||||
throw runtime_error("Command refers to non existant unit. Game out of synch.");
|
||||
}
|
||||
|
||||
//add the command to the interface
|
||||
gameNetworkInterface->requestCommand(networkCommand);
|
||||
|
||||
//calculate the result of the command
|
||||
if(networkCommand->getNetworkCommandType()==nctGiveCommand){
|
||||
Command* command= buildCommand(networkCommand);
|
||||
cr= unit->checkCommand(command);
|
||||
delete command;
|
||||
}
|
||||
return cr;
|
||||
}
|
||||
|
||||
void Commander::updateNetwork(){
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
|
||||
//chech that this is a keyframe
|
||||
if( !networkManager.isNetworkGame() || (world->getFrameCount() % GameConstants::networkFramePeriod)==0){
|
||||
|
||||
GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
|
||||
|
||||
//update the keyframe
|
||||
gameNetworkInterface->updateKeyframe(world->getFrameCount());
|
||||
|
||||
//give pending commands
|
||||
for(int i= 0; i < gameNetworkInterface->getPendingCommandCount(); ++i){
|
||||
giveNetworkCommand(gameNetworkInterface->getPendingCommand(i));
|
||||
}
|
||||
gameNetworkInterface->clearPendingCommands();
|
||||
}
|
||||
}
|
||||
|
||||
void Commander::giveNetworkCommand(const NetworkCommand* networkCommand) const{
|
||||
|
||||
Unit* unit= world->findUnitById(networkCommand->getUnitId());
|
||||
|
||||
//exec ute command, if unit is still alive
|
||||
if(unit!=NULL){
|
||||
switch(networkCommand->getNetworkCommandType()){
|
||||
case nctGiveCommand:{
|
||||
assert(networkCommand->getCommandTypeId()!=CommandType::invalidId);
|
||||
Command* command= buildCommand(networkCommand);
|
||||
unit->giveCommand(command);
|
||||
}
|
||||
break;
|
||||
case nctCancelCommand:
|
||||
unit->cancelCommand();
|
||||
break;
|
||||
case nctSetMeetingPoint:
|
||||
unit->setMeetingPos(networkCommand->getPosition());
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Command* Commander::buildCommand(const NetworkCommand* networkCommand) const{
|
||||
assert(networkCommand->getNetworkCommandType()==nctGiveCommand);
|
||||
|
||||
Unit* target= NULL;
|
||||
const CommandType* ct= NULL;
|
||||
const Unit* unit= world->findUnitById(networkCommand->getUnitId());
|
||||
const UnitType* unitType= world->findUnitTypeById(unit->getFaction()->getType(), networkCommand->getUnitTypeId());
|
||||
|
||||
//validate unit
|
||||
if(unit==NULL){
|
||||
throw runtime_error("Can not find unit with id: " + intToStr(networkCommand->getUnitId()) + ". Game out of synch.");
|
||||
}
|
||||
|
||||
ct= unit->getType()->findCommandTypeById(networkCommand->getCommandTypeId());
|
||||
|
||||
//validate command type
|
||||
if(ct==NULL){
|
||||
throw runtime_error("Can not find command type with id: " + intToStr(networkCommand->getCommandTypeId()) + " in unit: " + unit->getType()->getName() + ". Game out of synch.");
|
||||
}
|
||||
|
||||
//get target, the target might be dead due to lag, cope with it
|
||||
if(networkCommand->getTargetId()!=Unit::invalidId){
|
||||
target= world->findUnitById(networkCommand->getTargetId());
|
||||
}
|
||||
|
||||
//create command
|
||||
Command *command= NULL;
|
||||
if(unitType!=NULL){
|
||||
command= new Command(ct, networkCommand->getPosition(), unitType);
|
||||
}
|
||||
else if(target==NULL){
|
||||
command= new Command(ct, networkCommand->getPosition());
|
||||
}
|
||||
else{
|
||||
command= new Command(ct, target);
|
||||
}
|
||||
|
||||
//issue command
|
||||
return command;
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,68 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_COMMANDER_H_
|
||||
#define _GLEST_GAME_COMMANDER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "vec.h"
|
||||
#include "selection.h"
|
||||
#include "command_type.h"
|
||||
|
||||
using std::vector;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Graphics::Vec2i;
|
||||
|
||||
class World;
|
||||
class Unit;
|
||||
class Command;
|
||||
class CommandType;
|
||||
class NetworkCommand;
|
||||
|
||||
// =====================================================
|
||||
// class Commander
|
||||
//
|
||||
/// Gives commands to the units
|
||||
// =====================================================
|
||||
|
||||
class Commander{
|
||||
private:
|
||||
typedef vector<CommandResult> CommandResultContainer;
|
||||
|
||||
private:
|
||||
World *world;
|
||||
|
||||
public:
|
||||
void init(World *world);
|
||||
void updateNetwork();
|
||||
|
||||
CommandResult tryGiveCommand(const Unit* unit, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType) const;
|
||||
CommandResult tryGiveCommand(const Selection *selection, CommandClass commandClass, const Vec2i &pos= Vec2i(0), const Unit *targetUnit= NULL) const;
|
||||
CommandResult tryGiveCommand(const Selection *selection, const CommandType *commandType, const Vec2i &pos= Vec2i(0), const Unit *targetUnit= NULL) const;
|
||||
CommandResult tryGiveCommand(const Selection *selection, const Vec2i &pos, const Unit *targetUnit= NULL) const;
|
||||
CommandResult tryCancelCommand(const Selection *selection) const;
|
||||
void trySetMeetingPoint(const Unit* unit, const Vec2i &pos) const;
|
||||
CommandResult pushNetworkCommand(const NetworkCommand* networkCommand) const;
|
||||
|
||||
private:
|
||||
Vec2i computeRefPos(const Selection *selection) const;
|
||||
Vec2i computeDestPos(const Vec2i &refUnitPos, const Vec2i &unitPos, const Vec2i &commandPos) const;
|
||||
CommandResult computeResult(const CommandResultContainer &results) const;
|
||||
void giveNetworkCommand(const NetworkCommand* networkCommand) const;
|
||||
Command* buildCommand(const NetworkCommand* networkCommand) const;
|
||||
};
|
||||
|
||||
}} //end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,65 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "console.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "config.h"
|
||||
#include "program.h"
|
||||
#include "game_constants.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Console
|
||||
// =====================================================
|
||||
|
||||
Console::Console(){
|
||||
//config
|
||||
maxLines= Config::getInstance().getInt("ConsoleMaxLines");
|
||||
timeout= Config::getInstance().getInt("ConsoleTimeout");
|
||||
|
||||
timeElapsed= 0.0f;
|
||||
}
|
||||
|
||||
void Console::addStdMessage(const string &s){
|
||||
addLine(Lang::getInstance().get(s));
|
||||
}
|
||||
|
||||
void Console::addLine(string line, bool playSound){
|
||||
if(playSound){
|
||||
SoundRenderer::getInstance().playFx(CoreData::getInstance().getClickSoundA());
|
||||
}
|
||||
lines.insert(lines.begin(), StringTimePair(line, timeElapsed));
|
||||
if(lines.size()>maxLines){
|
||||
lines.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void Console::update(){
|
||||
timeElapsed+= 1.f/GameConstants::updateFps;
|
||||
|
||||
if(!lines.empty()){
|
||||
if(lines.back().second<timeElapsed-timeout){
|
||||
lines.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Console::isEmpty(){
|
||||
return lines.empty();
|
||||
}
|
||||
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,66 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_CONSOLE_H_
|
||||
#define _GLEST_GAME_CONSOLE_H_
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Console
|
||||
//
|
||||
// In-game console that shows various types of messages
|
||||
// =====================================================
|
||||
|
||||
class Console{
|
||||
private:
|
||||
static const int consoleLines= 5;
|
||||
|
||||
public:
|
||||
typedef pair<string, float> StringTimePair;
|
||||
typedef vector<StringTimePair> Lines;
|
||||
typedef Lines::const_iterator LineIterator;
|
||||
|
||||
private:
|
||||
float timeElapsed;
|
||||
Lines lines;
|
||||
|
||||
//this should be deleted from here someday
|
||||
bool won, lost;
|
||||
|
||||
//config
|
||||
int maxLines;
|
||||
float timeout;
|
||||
|
||||
public:
|
||||
Console();
|
||||
|
||||
int getLineCount() const {return lines.size();}
|
||||
string getLine(int i) const {return lines[i].first;}
|
||||
|
||||
|
||||
void addStdMessage(const string &s);
|
||||
void addLine(string line, bool playSound= false);
|
||||
void update();
|
||||
bool isEmpty();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,883 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "game.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "renderer.h"
|
||||
#include "particle_renderer.h"
|
||||
#include "commander.h"
|
||||
#include "battle_end.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "profiler.h"
|
||||
#include "core_data.h"
|
||||
#include "metrics.h"
|
||||
#include "faction.h"
|
||||
#include "network_manager.h"
|
||||
#include "checksum.h"
|
||||
#include "auto_test.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Platform;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Game
|
||||
// =====================================================
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
Game::Game(Program *program, const GameSettings *gameSettings):
|
||||
ProgramState(program)
|
||||
{
|
||||
this->gameSettings= *gameSettings;
|
||||
|
||||
mouseX=0;
|
||||
mouseY=0;
|
||||
mouse2d= 0;
|
||||
loadingText="";
|
||||
weatherParticleSystem= NULL;
|
||||
updateFps=0;
|
||||
renderFps=0;
|
||||
lastUpdateFps=0;
|
||||
lastRenderFps=0;
|
||||
paused= false;
|
||||
gameOver= false;
|
||||
renderNetworkStatus= false;
|
||||
speed= sNormal;
|
||||
}
|
||||
|
||||
Game::~Game(){
|
||||
Logger &logger= Logger::getInstance();
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
logger.setState(Lang::getInstance().get("Deleting"));
|
||||
logger.add("Game", true);
|
||||
|
||||
renderer.endGame();
|
||||
SoundRenderer::getInstance().stopAllSounds();
|
||||
|
||||
deleteValues(aiInterfaces.begin(), aiInterfaces.end());
|
||||
|
||||
gui.end(); //selection must be cleared before deleting units
|
||||
world.end(); //must die before selection because of referencers
|
||||
}
|
||||
|
||||
|
||||
// ==================== init and load ====================
|
||||
|
||||
void Game::load(){
|
||||
Logger &logger= Logger::getInstance();
|
||||
string mapName= gameSettings.getMap();
|
||||
string tilesetName= gameSettings.getTileset();
|
||||
string techName= gameSettings.getTech();
|
||||
string scenarioName= gameSettings.getScenario();
|
||||
|
||||
logger.setState(Lang::getInstance().get("Loading"));
|
||||
|
||||
if(scenarioName.empty()){
|
||||
logger.setSubtitle(formatString(mapName)+" - "+formatString(tilesetName)+" - "+formatString(techName));
|
||||
}
|
||||
else{
|
||||
logger.setSubtitle(formatString(scenarioName));
|
||||
}
|
||||
|
||||
//tileset
|
||||
world.loadTileset("tilesets/"+tilesetName, &checksum);
|
||||
|
||||
set<string> factions;
|
||||
for ( int i=0; i < gameSettings.getFactionCount(); ++i ) {
|
||||
factions.insert(gameSettings.getFactionTypeName(i));
|
||||
}
|
||||
|
||||
//tech, load before map because of resources
|
||||
world.loadTech("techs/"+techName, factions, &checksum);
|
||||
|
||||
//map
|
||||
world.loadMap(Map::getMapPath(mapName), &checksum);
|
||||
|
||||
//scenario
|
||||
if(!scenarioName.empty()){
|
||||
Lang::getInstance().loadScenarioStrings(gameSettings.getScenarioDir(), scenarioName);
|
||||
world.loadScenario(Scenario::getScenarioPath(gameSettings.getScenarioDir(), scenarioName), &checksum);
|
||||
}
|
||||
}
|
||||
|
||||
void Game::init(){
|
||||
Lang &lang= Lang::getInstance();
|
||||
Logger &logger= Logger::getInstance();
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
Map *map= world.getMap();
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
|
||||
logger.setState(lang.get("Initializing"));
|
||||
|
||||
//mesage box
|
||||
mainMessageBox.init(lang.get("Yes"), lang.get("No"));
|
||||
mainMessageBox.setEnabled(false);
|
||||
|
||||
//check forog war
|
||||
if(!Config::getInstance().getBool("FogOfWar") && networkManager.isNetworkGame() ){
|
||||
throw runtime_error("Can not play online games with for of war disabled");
|
||||
}
|
||||
|
||||
//init world, and place camera
|
||||
commander.init(&world);
|
||||
world.init(this, gameSettings.getDefaultUnits());
|
||||
gui.init(this);
|
||||
chatManager.init(&console, world.getThisTeamIndex());
|
||||
const Vec2i &v= map->getStartLocation(world.getThisFaction()->getStartLocationIndex());
|
||||
gameCamera.init(map->getW(), map->getH());
|
||||
gameCamera.setPos(Vec2f(v.x, v.y));
|
||||
scriptManager.init(&world, &gameCamera);
|
||||
|
||||
//create IAs
|
||||
aiInterfaces.resize(world.getFactionCount());
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
Faction *faction= world.getFaction(i);
|
||||
if(faction->getCpuControl()){
|
||||
aiInterfaces[i]= new AiInterface(*this, i, faction->getTeam());
|
||||
logger.add("Creating AI for faction " + intToStr(i), true);
|
||||
}
|
||||
else{
|
||||
aiInterfaces[i]= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//wheather particle systems
|
||||
if(world.getTileset()->getWeather() == wRainy){
|
||||
logger.add("Creating rain particle system", true);
|
||||
weatherParticleSystem= new RainParticleSystem();
|
||||
weatherParticleSystem->setSpeed(12.f/GameConstants::updateFps);
|
||||
weatherParticleSystem->setPos(gameCamera.getPos());
|
||||
renderer.manageParticleSystem(weatherParticleSystem, rsGame);
|
||||
}
|
||||
else if(world.getTileset()->getWeather() == wSnowy){
|
||||
logger.add("Creating snow particle system", true);
|
||||
weatherParticleSystem= new SnowParticleSystem(1200);
|
||||
weatherParticleSystem->setSpeed(1.5f/GameConstants::updateFps);
|
||||
weatherParticleSystem->setPos(gameCamera.getPos());
|
||||
weatherParticleSystem->setTexture(coreData.getSnowTexture());
|
||||
renderer.manageParticleSystem(weatherParticleSystem, rsGame);
|
||||
}
|
||||
|
||||
//init renderer state
|
||||
logger.add("Initializing renderer", true);
|
||||
renderer.initGame(this);
|
||||
|
||||
//sounds
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
|
||||
Tileset *tileset= world.getTileset();
|
||||
AmbientSounds *ambientSounds= tileset->getAmbientSounds();
|
||||
|
||||
//rain
|
||||
if(tileset->getWeather()==wRainy && ambientSounds->isEnabledRain()){
|
||||
logger.add("Starting ambient stream", true);
|
||||
soundRenderer.playAmbient(ambientSounds->getRain());
|
||||
}
|
||||
|
||||
//snow
|
||||
if(tileset->getWeather()==wSnowy && ambientSounds->isEnabledSnow()){
|
||||
logger.add("Starting ambient stream", true);
|
||||
soundRenderer.playAmbient(ambientSounds->getSnow());
|
||||
}
|
||||
|
||||
logger.add("Waiting for network", true);
|
||||
networkManager.getGameNetworkInterface()->waitUntilReady(&checksum);
|
||||
|
||||
logger.add("Starting music stream", true);
|
||||
StrSound *gameMusic= world.getThisFaction()->getType()->getMusic();
|
||||
soundRenderer.playMusic(gameMusic);
|
||||
|
||||
logger.add("Launching game");
|
||||
}
|
||||
|
||||
|
||||
// ==================== update ====================
|
||||
|
||||
//update
|
||||
void Game::update(){
|
||||
|
||||
// a) Updates non dependant on speed
|
||||
|
||||
//misc
|
||||
updateFps++;
|
||||
mouse2d= (mouse2d+1) % Renderer::maxMouse2dAnim;
|
||||
|
||||
//console
|
||||
console.update();
|
||||
|
||||
// b) Updates depandant on speed
|
||||
|
||||
int updateLoops= getUpdateLoops();
|
||||
|
||||
//update
|
||||
for(int i=0; i<updateLoops; ++i){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
//AiInterface
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
if(world.getFaction(i)->getCpuControl() && scriptManager.getPlayerModifiers(i)->getAiEnabled()){
|
||||
aiInterfaces[i]->update();
|
||||
}
|
||||
}
|
||||
|
||||
//World
|
||||
world.update();
|
||||
|
||||
// Commander
|
||||
commander.updateNetwork();
|
||||
|
||||
//Gui
|
||||
gui.update();
|
||||
|
||||
//Particle systems
|
||||
if(weatherParticleSystem != NULL){
|
||||
weatherParticleSystem->setPos(gameCamera.getPos());
|
||||
}
|
||||
renderer.updateParticleManager(rsGame);
|
||||
}
|
||||
|
||||
//call the chat manager
|
||||
chatManager.updateNetwork();
|
||||
|
||||
//check for quiting status
|
||||
if(NetworkManager::getInstance().getGameNetworkInterface()->getQuit()){
|
||||
quitGame();
|
||||
}
|
||||
|
||||
//update auto test
|
||||
if(Config::getInstance().getBool("AutoTest")){
|
||||
AutoTest::getInstance().updateGame(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Game::updateCamera(){
|
||||
gameCamera.update();
|
||||
}
|
||||
|
||||
|
||||
// ==================== render ====================
|
||||
|
||||
//render
|
||||
void Game::render(){
|
||||
renderFps++;
|
||||
render3d();
|
||||
render2d();
|
||||
Renderer::getInstance().swapBuffers();
|
||||
}
|
||||
|
||||
// ==================== tick ====================
|
||||
|
||||
void Game::tick(){
|
||||
lastUpdateFps= updateFps;
|
||||
lastRenderFps= renderFps;
|
||||
updateFps= 0;
|
||||
renderFps= 0;
|
||||
|
||||
//Win/lose check
|
||||
checkWinner();
|
||||
gui.tick();
|
||||
}
|
||||
|
||||
|
||||
// ==================== events ====================
|
||||
|
||||
void Game::mouseDownLeft(int x, int y){
|
||||
|
||||
Map *map= world.getMap();
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
bool messageBoxClick= false;
|
||||
|
||||
//scrip message box, only if the exit box is not enabled
|
||||
if(!mainMessageBox.getEnabled() && scriptManager.getMessageBox()->getEnabled()){
|
||||
int button= 1;
|
||||
if(scriptManager.getMessageBox()->mouseClick(x, y, button)){
|
||||
scriptManager.onMessageBoxOk();
|
||||
messageBoxClick= true;
|
||||
}
|
||||
}
|
||||
|
||||
//minimap panel
|
||||
if(!messageBoxClick){
|
||||
if(metrics.isInMinimap(x, y) && !gui.isSelectingPos()){
|
||||
|
||||
int xm= x - metrics.getMinimapX();
|
||||
int ym= y - metrics.getMinimapY();
|
||||
int xCell= static_cast<int>(xm * (static_cast<float>(map->getW()) / metrics.getMinimapW()));
|
||||
int yCell= static_cast<int>(map->getH() - ym * (static_cast<float>(map->getH()) / metrics.getMinimapH()));
|
||||
|
||||
if(map->isInside(xCell, yCell)){
|
||||
if(!gui.isSelectingPos()){
|
||||
gameCamera.setPos(Vec2f(static_cast<float>(xCell), static_cast<float>(yCell)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//display panel
|
||||
else if(metrics.isInDisplay(x, y) && !gui.isSelectingPos()){
|
||||
int xd= x - metrics.getDisplayX();
|
||||
int yd= y - metrics.getDisplayY();
|
||||
if(gui.mouseValid(xd, yd)){
|
||||
gui.mouseDownLeftDisplay(xd, yd);
|
||||
}
|
||||
else{
|
||||
gui.mouseDownLeftGraphics(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
//graphics panel
|
||||
else{
|
||||
gui.mouseDownLeftGraphics(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
//exit message box, has to be the last thing to do in this function
|
||||
if(mainMessageBox.getEnabled()){
|
||||
int button= 1;
|
||||
if(mainMessageBox.mouseClick(x, y, button)){
|
||||
if(button==1){
|
||||
networkManager.getGameNetworkInterface()->quitGame();
|
||||
quitGame();
|
||||
}
|
||||
else{
|
||||
//close message box
|
||||
mainMessageBox.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::mouseDownRight(int x, int y){
|
||||
gui.mouseDownRightGraphics(x, y);
|
||||
}
|
||||
|
||||
void Game::mouseUpLeft(int x, int y){
|
||||
gui.mouseUpLeftGraphics(x, y);
|
||||
}
|
||||
|
||||
void Game::mouseDoubleClickLeft(int x, int y){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
|
||||
//display panel
|
||||
if(metrics.isInDisplay(x, y) && !gui.isSelectingPos()){
|
||||
int xd= x - metrics.getDisplayX();
|
||||
int yd= y - metrics.getDisplayY();
|
||||
if(gui.mouseValid(xd, yd)){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//graphics panel
|
||||
gui.mouseDoubleClickLeftGraphics(x, y);
|
||||
}
|
||||
|
||||
void Game::mouseMove(int x, int y, const MouseState *ms){
|
||||
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
|
||||
mouseX= x;
|
||||
mouseY= y;
|
||||
|
||||
//main window
|
||||
if(y<10){
|
||||
gameCamera.setMoveZ(-1);
|
||||
}
|
||||
else if(y> metrics.getVirtualH()-10){
|
||||
gameCamera.setMoveZ(1);
|
||||
}
|
||||
else{
|
||||
gameCamera.stopMoveZ();
|
||||
}
|
||||
|
||||
if(x<10){
|
||||
gameCamera.setMoveX(-1);
|
||||
}
|
||||
else if(x> metrics.getVirtualW()-10){
|
||||
gameCamera.setMoveX(1);
|
||||
}
|
||||
else{
|
||||
gameCamera.stopMoveX();
|
||||
}
|
||||
|
||||
if(mainMessageBox.getEnabled()){
|
||||
mainMessageBox.mouseMove(x, y);
|
||||
}
|
||||
|
||||
if(scriptManager.getMessageBox()->getEnabled()){
|
||||
scriptManager.getMessageBox()->mouseMove(x, y);
|
||||
}
|
||||
|
||||
//graphics
|
||||
gui.mouseMoveGraphics(x, y);
|
||||
|
||||
//display
|
||||
if(metrics.isInDisplay(x, y) && !gui.isSelecting() && !gui.isSelectingPos()){
|
||||
if(!gui.isSelectingPos()){
|
||||
gui.mouseMoveDisplay(x - metrics.getDisplayX(), y - metrics.getDisplayY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::keyDown(char key){
|
||||
|
||||
Lang &lang= Lang::getInstance();
|
||||
bool speedChangesAllowed= !NetworkManager::getInstance().isNetworkGame();
|
||||
|
||||
//send ley to the chat manager
|
||||
chatManager.keyDown(key);
|
||||
|
||||
if(!chatManager.getEditEnabled()){
|
||||
|
||||
if(key=='N'){
|
||||
renderNetworkStatus= true;
|
||||
}
|
||||
else if(key=='E'){
|
||||
for(int i=0; i<100; ++i){
|
||||
string path= "screens/screen" + intToStr(i) + ".tga";
|
||||
|
||||
FILE *f= fopen(path.c_str(), "rb");
|
||||
if(f==NULL){
|
||||
Renderer::getInstance().saveScreen(path);
|
||||
break;
|
||||
}
|
||||
else{
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//move camera left
|
||||
else if(key==vkLeft){
|
||||
gameCamera.setMoveX(-1);
|
||||
}
|
||||
|
||||
//move camera right
|
||||
else if(key==vkRight){
|
||||
gameCamera.setMoveX(1);
|
||||
}
|
||||
|
||||
//move camera up
|
||||
else if(key==vkUp){
|
||||
gameCamera.setMoveZ(1);
|
||||
}
|
||||
|
||||
//move camera down
|
||||
else if(key==vkDown){
|
||||
gameCamera.setMoveZ(-1);
|
||||
}
|
||||
|
||||
//change camera mode
|
||||
else if(key=='F'){
|
||||
gameCamera.switchState();
|
||||
string stateString= gameCamera.getState()==GameCamera::sGame? lang.get("GameCamera"): lang.get("FreeCamera");
|
||||
console.addLine(lang.get("CameraModeSet")+" "+ stateString);
|
||||
}
|
||||
|
||||
//pause
|
||||
else if(key=='P'){
|
||||
if(speedChangesAllowed){
|
||||
if(paused){
|
||||
console.addLine(lang.get("GameResumed"));
|
||||
paused= false;
|
||||
}
|
||||
else{
|
||||
console.addLine(lang.get("GamePaused"));
|
||||
paused= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//increment speed
|
||||
else if(key==vkAdd){
|
||||
if(speedChangesAllowed){
|
||||
incSpeed();
|
||||
}
|
||||
}
|
||||
|
||||
//decrement speed
|
||||
else if(key==vkSubtract){
|
||||
if(speedChangesAllowed){
|
||||
decSpeed();
|
||||
}
|
||||
}
|
||||
|
||||
//exit
|
||||
else if(key==vkEscape){
|
||||
showMessageBox(lang.get("ExitGame?"), "", true);
|
||||
}
|
||||
|
||||
//group
|
||||
else if(key>='0' && key<'0'+Selection::maxGroups){
|
||||
gui.groupKey(key-'0');
|
||||
}
|
||||
|
||||
//hotkeys
|
||||
if(gameCamera.getState()==GameCamera::sGame){
|
||||
gui.hotKey(key);
|
||||
}
|
||||
else{
|
||||
//rotate camera leftt
|
||||
if(key=='A'){
|
||||
gameCamera.setRotate(-1);
|
||||
}
|
||||
|
||||
//rotate camera right
|
||||
else if(key=='D'){
|
||||
gameCamera.setRotate(1);
|
||||
}
|
||||
|
||||
//camera up
|
||||
else if(key=='S'){
|
||||
gameCamera.setMoveY(1);
|
||||
}
|
||||
|
||||
//camera down
|
||||
else if(key=='W'){
|
||||
gameCamera.setMoveY(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::keyUp(char key){
|
||||
|
||||
if(!chatManager.getEditEnabled()){
|
||||
switch(key){
|
||||
case 'N':
|
||||
renderNetworkStatus= false;
|
||||
break;
|
||||
case 'A':
|
||||
case 'D':
|
||||
gameCamera.setRotate(0);
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
case 'S':
|
||||
gameCamera.stopMoveY();
|
||||
break;
|
||||
|
||||
case vkUp:
|
||||
case vkDown:
|
||||
gameCamera.stopMoveZ();
|
||||
break;
|
||||
|
||||
case vkLeft:
|
||||
case vkRight:
|
||||
gameCamera.stopMoveX();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::keyPress(char c){
|
||||
chatManager.keyPress(c);
|
||||
}
|
||||
|
||||
void Game::quitGame(){
|
||||
program->setState(new BattleEnd(program, world.getStats()));
|
||||
}
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
// ==================== render ====================
|
||||
|
||||
void Game::render3d(){
|
||||
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
//init
|
||||
renderer.reset3d();
|
||||
renderer.computeVisibleQuad();
|
||||
renderer.loadGameCameraMatrix();
|
||||
renderer.setupLighting();
|
||||
|
||||
//shadow map
|
||||
renderer.renderShadowsToTexture();
|
||||
|
||||
//clear buffers
|
||||
renderer.clearBuffers();
|
||||
|
||||
//surface
|
||||
renderer.renderSurface();
|
||||
|
||||
//selection circles
|
||||
renderer.renderSelectionEffects();
|
||||
|
||||
//units
|
||||
renderer.renderUnits();
|
||||
|
||||
//objects
|
||||
renderer.renderObjects();
|
||||
|
||||
//water
|
||||
renderer.renderWater();
|
||||
renderer.renderWaterEffects();
|
||||
|
||||
//particles
|
||||
renderer.renderParticleManager(rsGame);
|
||||
|
||||
//mouse 3d
|
||||
renderer.renderMouse3d();
|
||||
}
|
||||
|
||||
void Game::render2d(){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
Config &config= Config::getInstance();
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
|
||||
//init
|
||||
renderer.reset2d();
|
||||
|
||||
//display
|
||||
renderer.renderDisplay();
|
||||
|
||||
//minimap
|
||||
if(!config.getBool("PhotoMode")){
|
||||
renderer.renderMinimap();
|
||||
}
|
||||
|
||||
//selection
|
||||
renderer.renderSelectionQuad();
|
||||
|
||||
//exit message box
|
||||
if(mainMessageBox.getEnabled()){
|
||||
renderer.renderMessageBox(&mainMessageBox);
|
||||
}
|
||||
|
||||
//script message box
|
||||
if(!mainMessageBox.getEnabled() && scriptManager.getMessageBoxEnabled()){
|
||||
renderer.renderMessageBox(scriptManager.getMessageBox());
|
||||
}
|
||||
|
||||
//script display text
|
||||
if(!scriptManager.getDisplayText().empty() && !scriptManager.getMessageBoxEnabled()){
|
||||
renderer.renderText(
|
||||
scriptManager.getDisplayText(), coreData.getMenuFontNormal(),
|
||||
Vec3f(1.0f), 200, 680, false);
|
||||
}
|
||||
|
||||
|
||||
renderer.renderChatManager(&chatManager);
|
||||
|
||||
//debug info
|
||||
if(config.getBool("DebugMode")){
|
||||
string str;
|
||||
|
||||
str+= "MouseXY: " + intToStr(mouseX) + "," + intToStr(mouseY)+"\n";
|
||||
str+= "PosObjWord: " + intToStr(gui.getPosObjWorld().x) + "," + intToStr(gui.getPosObjWorld().y)+"\n";
|
||||
str+= "Render FPS: "+intToStr(lastRenderFps)+"\n";
|
||||
str+= "Update FPS: "+intToStr(lastUpdateFps)+"\n";
|
||||
str+= "GameCamera pos: "+floatToStr(gameCamera.getPos().x)+","+floatToStr(gameCamera.getPos().y)+","+floatToStr(gameCamera.getPos().z)+"\n";
|
||||
str+= "Time: "+floatToStr(world.getTimeFlow()->getTime())+"\n";
|
||||
str+= "Triangle count: "+intToStr(renderer.getTriangleCount())+"\n";
|
||||
str+= "Vertex count: "+intToStr(renderer.getPointCount())+"\n";
|
||||
str+= "Frame count:"+intToStr(world.getFrameCount())+"\n";
|
||||
|
||||
//visible quad
|
||||
Quad2i visibleQuad= renderer.getVisibleQuad();
|
||||
|
||||
str+= "Visible quad: ";
|
||||
for(int i= 0; i<4; ++i){
|
||||
str+= "(" + intToStr(visibleQuad.p[i].x) + "," +intToStr(visibleQuad.p[i].y) + ") ";
|
||||
}
|
||||
str+= "\n";
|
||||
str+= "Visible quad area: " + floatToStr(visibleQuad.area()) +"\n";
|
||||
|
||||
// resources
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
str+= "Player "+intToStr(i)+" res: ";
|
||||
for(int j=0; j<world.getTechTree()->getResourceTypeCount(); ++j){
|
||||
str+= intToStr(world.getFaction(i)->getResource(j)->getAmount());
|
||||
str+=" ";
|
||||
}
|
||||
str+="\n";
|
||||
}
|
||||
|
||||
renderer.renderText(
|
||||
str, coreData.getMenuFontNormal(),
|
||||
Vec3f(1.0f), 10, 500, false);
|
||||
}
|
||||
|
||||
//network status
|
||||
if(renderNetworkStatus){
|
||||
renderer.renderText(
|
||||
NetworkManager::getInstance().getGameNetworkInterface()->getNetworkStatus(),
|
||||
coreData.getMenuFontNormal(),
|
||||
Vec3f(1.0f), 20, 500, false);
|
||||
}
|
||||
|
||||
//resource info
|
||||
if(!config.getBool("PhotoMode")){
|
||||
renderer.renderResourceStatus();
|
||||
renderer.renderConsole(&console);
|
||||
}
|
||||
|
||||
//2d mouse
|
||||
renderer.renderMouse2d(mouseX, mouseY, mouse2d, gui.isSelectingPos()? 1.f: 0.f);
|
||||
}
|
||||
|
||||
|
||||
// ==================== misc ====================
|
||||
|
||||
void Game::checkWinner(){
|
||||
if(!gameOver){
|
||||
if(gameSettings.getDefaultVictoryConditions()){
|
||||
checkWinnerStandard();
|
||||
}
|
||||
else
|
||||
{
|
||||
checkWinnerScripted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::checkWinnerStandard(){
|
||||
//lose
|
||||
bool lose= false;
|
||||
if(!hasBuilding(world.getThisFaction())){
|
||||
lose= true;
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
if(!world.getFaction(i)->isAlly(world.getThisFaction())){
|
||||
world.getStats()->setVictorious(i);
|
||||
}
|
||||
}
|
||||
gameOver= true;
|
||||
showLoseMessageBox();
|
||||
}
|
||||
|
||||
//win
|
||||
if(!lose){
|
||||
bool win= true;
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
if(i!=world.getThisFactionIndex()){
|
||||
if(hasBuilding(world.getFaction(i)) && !world.getFaction(i)->isAlly(world.getThisFaction())){
|
||||
win= false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if win
|
||||
if(win){
|
||||
for(int i=0; i< world.getFactionCount(); ++i){
|
||||
if(world.getFaction(i)->isAlly(world.getThisFaction())){
|
||||
world.getStats()->setVictorious(i);
|
||||
}
|
||||
}
|
||||
gameOver= true;
|
||||
showWinMessageBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::checkWinnerScripted(){
|
||||
if(scriptManager.getGameOver()){
|
||||
gameOver= true;
|
||||
for(int i= 0; i<world.getFactionCount(); ++i){
|
||||
if(scriptManager.getPlayerModifiers(i)->getWinner()){
|
||||
world.getStats()->setVictorious(i);
|
||||
}
|
||||
}
|
||||
if(scriptManager.getPlayerModifiers(world.getThisFactionIndex())->getWinner()){
|
||||
showWinMessageBox();
|
||||
}
|
||||
else{
|
||||
showLoseMessageBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Game::hasBuilding(const Faction *faction){
|
||||
for(int i=0; i<faction->getUnitCount(); ++i){
|
||||
if(faction->getUnit(i)->getType()->hasSkillClass(scBeBuilt)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Game::incSpeed(){
|
||||
Lang &lang= Lang::getInstance();
|
||||
switch(speed){
|
||||
case sSlow:
|
||||
speed= sNormal;
|
||||
console.addLine(lang.get("GameSpeedSet")+" "+lang.get("Normal"));
|
||||
break;
|
||||
case sNormal:
|
||||
speed= sFast;
|
||||
console.addLine(lang.get("GameSpeedSet")+" "+lang.get("Fast"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::decSpeed(){
|
||||
Lang &lang= Lang::getInstance();
|
||||
switch(speed){
|
||||
case sNormal:
|
||||
speed= sSlow;
|
||||
console.addLine(lang.get("GameSpeedSet")+" "+lang.get("Slow"));
|
||||
break;
|
||||
case sFast:
|
||||
speed= sNormal;
|
||||
console.addLine(lang.get("GameSpeedSet")+" "+lang.get("Normal"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int Game::getUpdateLoops(){
|
||||
if(paused){
|
||||
return 0;
|
||||
}
|
||||
else if(speed==sFast){
|
||||
return Config::getInstance().getInt("FastSpeedLoops");
|
||||
}
|
||||
else if(speed==sSlow){
|
||||
return updateFps % 2 == 0? 1: 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Game::showLoseMessageBox(){
|
||||
Lang &lang= Lang::getInstance();
|
||||
showMessageBox(lang.get("YouLose")+", "+lang.get("ExitGame?"), lang.get("BattleOver"), false);
|
||||
}
|
||||
|
||||
void Game::showWinMessageBox(){
|
||||
Lang &lang= Lang::getInstance();
|
||||
showMessageBox(lang.get("YouWin")+", "+lang.get("ExitGame?"), lang.get("BattleOver"), false);
|
||||
}
|
||||
|
||||
void Game::showMessageBox(const string &text, const string &header, bool toggle){
|
||||
if(!toggle){
|
||||
mainMessageBox.setEnabled(false);
|
||||
}
|
||||
|
||||
if(!mainMessageBox.getEnabled()){
|
||||
mainMessageBox.setText(text);
|
||||
mainMessageBox.setHeader(header);
|
||||
mainMessageBox.setEnabled(true);
|
||||
}
|
||||
else{
|
||||
mainMessageBox.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,135 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_GAME_H_
|
||||
#define _GLEST_GAME_GAME_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "gui.h"
|
||||
#include "game_camera.h"
|
||||
#include "world.h"
|
||||
#include "ai_interface.h"
|
||||
#include "program.h"
|
||||
#include "chat_manager.h"
|
||||
#include "script_manager.h"
|
||||
#include "game_settings.h"
|
||||
|
||||
using std::vector;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class GraphicMessageBox;
|
||||
|
||||
// =====================================================
|
||||
// class Game
|
||||
//
|
||||
// Main game class
|
||||
// =====================================================
|
||||
|
||||
class Game: public ProgramState{
|
||||
public:
|
||||
enum Speed{
|
||||
sFast,
|
||||
sNormal,
|
||||
sSlow
|
||||
};
|
||||
|
||||
private:
|
||||
typedef vector<Ai*> Ais;
|
||||
typedef vector<AiInterface*> AiInterfaces;
|
||||
|
||||
private:
|
||||
//main data
|
||||
World world;
|
||||
AiInterfaces aiInterfaces;
|
||||
Gui gui;
|
||||
GameCamera gameCamera;
|
||||
Commander commander;
|
||||
Console console;
|
||||
ChatManager chatManager;
|
||||
ScriptManager scriptManager;
|
||||
|
||||
//misc
|
||||
Checksum checksum;
|
||||
string loadingText;
|
||||
int mouse2d;
|
||||
int mouseX, mouseY; //coords win32Api
|
||||
int updateFps, lastUpdateFps;
|
||||
int renderFps, lastRenderFps;
|
||||
bool paused;
|
||||
bool gameOver;
|
||||
bool renderNetworkStatus;
|
||||
Speed speed;
|
||||
GraphicMessageBox mainMessageBox;
|
||||
|
||||
//misc ptr
|
||||
ParticleSystem *weatherParticleSystem;
|
||||
GameSettings gameSettings;
|
||||
|
||||
public:
|
||||
Game(Program *program, const GameSettings *gameSettings);
|
||||
~Game();
|
||||
|
||||
//get
|
||||
GameSettings *getGameSettings() {return &gameSettings;}
|
||||
|
||||
const GameCamera *getGameCamera() const {return &gameCamera;}
|
||||
GameCamera *getGameCamera() {return &gameCamera;}
|
||||
const Commander *getCommander() const {return &commander;}
|
||||
Gui *getGui() {return &gui;}
|
||||
const Gui *getGui() const {return &gui;}
|
||||
Commander *getCommander() {return &commander;}
|
||||
Console *getConsole() {return &console;}
|
||||
ScriptManager *getScriptManager() {return &scriptManager;}
|
||||
World *getWorld() {return &world;}
|
||||
const World *getWorld() const {return &world;}
|
||||
|
||||
//init
|
||||
virtual void load();
|
||||
virtual void init();
|
||||
virtual void update();
|
||||
virtual void updateCamera();
|
||||
virtual void render();
|
||||
virtual void tick();
|
||||
|
||||
//event managing
|
||||
virtual void keyDown(char key);
|
||||
virtual void keyUp(char key);
|
||||
virtual void keyPress(char c);
|
||||
virtual void mouseDownLeft(int x, int y);
|
||||
virtual void mouseDownRight(int x, int y);
|
||||
virtual void mouseUpLeft(int x, int y);
|
||||
virtual void mouseDoubleClickLeft(int x, int y);
|
||||
virtual void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
|
||||
void quitGame();
|
||||
private:
|
||||
//render
|
||||
void render3d();
|
||||
void render2d();
|
||||
|
||||
//misc
|
||||
void checkWinner();
|
||||
void checkWinnerStandard();
|
||||
void checkWinnerScripted();
|
||||
bool hasBuilding(const Faction *faction);
|
||||
void incSpeed();
|
||||
void decSpeed();
|
||||
int getUpdateLoops();
|
||||
void showLoseMessageBox();
|
||||
void showWinMessageBox();
|
||||
void showMessageBox(const string &text, const string &header, bool toggle);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,235 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "game_camera.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "game_constants.h"
|
||||
#include "metrics.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Graphics;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class GameCamera
|
||||
// =====================================================
|
||||
|
||||
// ================== PUBLIC =====================
|
||||
|
||||
const float GameCamera::startingVAng= -60.f;
|
||||
const float GameCamera::startingHAng= 0.f;
|
||||
const float GameCamera::maxHeight= 20.f;
|
||||
const float GameCamera::minHeight= 10.f;
|
||||
const float GameCamera::transitionSpeed= 0.01f;
|
||||
const float GameCamera::centerOffsetZ= 8.0f;
|
||||
|
||||
// ================= Constructor =================
|
||||
|
||||
GameCamera::GameCamera(){
|
||||
this->pos= Vec3f(0.f, maxHeight, 0.f);
|
||||
state= sGame;
|
||||
|
||||
//config
|
||||
speed= 15.f / GameConstants::cameraFps;
|
||||
clampBounds= !Config::getInstance().getBool("PhotoMode");
|
||||
|
||||
vAng= startingVAng;
|
||||
hAng= startingHAng;
|
||||
rotate=0;
|
||||
stateTransition= 1.f;
|
||||
|
||||
move= Vec3f(0.f);
|
||||
stopMove= Vec3b(false);
|
||||
}
|
||||
|
||||
void GameCamera::init(int limitX, int limitY){
|
||||
this->limitX= limitX;
|
||||
this->limitY= limitY;
|
||||
}
|
||||
|
||||
// ==================== Misc =====================
|
||||
|
||||
void GameCamera::setPos(Vec2f pos){
|
||||
this->pos= Vec3f(pos.x, this->pos.y, pos.y);
|
||||
clampPosXZ(0.0f, limitX, 0.0f, limitY);
|
||||
}
|
||||
|
||||
void GameCamera::update(){
|
||||
|
||||
//move speed XYZ
|
||||
if(stopMove.x){
|
||||
move.x *= 0.9f;
|
||||
}
|
||||
if(stopMove.y){
|
||||
move.y *= 0.9f;
|
||||
}
|
||||
if(stopMove.z){
|
||||
move.z *= 0.9f;
|
||||
}
|
||||
|
||||
//move XZ
|
||||
if(move.z!=0){
|
||||
moveForwardH(speed*move.z);
|
||||
}
|
||||
if(move.x!=0){
|
||||
moveSideH(speed*move.x);
|
||||
}
|
||||
|
||||
//free state
|
||||
if(state==sFree){
|
||||
if(fabs(rotate) == 1){
|
||||
rotateHV(speed*5*rotate, 0);
|
||||
}
|
||||
if(move.y>0){
|
||||
moveUp(speed * move.y);
|
||||
if(clampBounds && pos.y<maxHeight){
|
||||
rotateHV(0.f, -speed * 1.7f * move.y);
|
||||
}
|
||||
}
|
||||
if(move.y<0){
|
||||
moveUp(speed * move.y);
|
||||
if(clampBounds && pos.y>minHeight){
|
||||
rotateHV(0.f, -speed * 1.7f * move.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//game state
|
||||
else if(stateTransition<1.f){
|
||||
if(lastHAng<180){
|
||||
hAng= lastHAng + (stateTransition)*(startingHAng-lastHAng);
|
||||
}
|
||||
else{
|
||||
hAng= lastHAng + (stateTransition)*(startingHAng+360-lastHAng);
|
||||
}
|
||||
vAng= lastVAng*(1.f-stateTransition)+startingVAng*stateTransition;
|
||||
pos.y= lastPos.y+maxHeight*stateTransition;
|
||||
stateTransition+= transitionSpeed;
|
||||
}
|
||||
|
||||
if(clampBounds){
|
||||
clampPosXYZ(0.0f, limitX, minHeight, maxHeight, 0.0f, limitY);
|
||||
}
|
||||
}
|
||||
|
||||
Quad2i GameCamera::computeVisibleQuad() const{
|
||||
float aspectRatio = Metrics::getInstance().getAspectRatio();
|
||||
Vec2i v= Vec2i(static_cast<int>(pos.x), static_cast<int>(pos.z));
|
||||
|
||||
//free state
|
||||
if(state==sFree || stateTransition<1.f){
|
||||
const float nearDist= 20.f;
|
||||
const float farDist= 90.f;
|
||||
const float fov= 65.0f * aspectRatio * 0.5f;
|
||||
const float dist= 20.f;
|
||||
|
||||
Vec2f v(sin(degToRad(180-hAng)), cos(degToRad(180-hAng)));
|
||||
Vec2f v1(sin(degToRad(180-hAng-fov)), cos(degToRad(180-hAng-fov)));
|
||||
Vec2f v2(sin(degToRad(180-hAng+fov)), cos(degToRad(180-hAng+fov)));
|
||||
v.normalize();
|
||||
v1.normalize();
|
||||
v2.normalize();
|
||||
|
||||
Vec2f p= Vec2f(pos.x, pos.z)-v*dist;
|
||||
Vec2i p1(static_cast<int>(p.x+v1.x*nearDist), static_cast<int>(p.y+v1.y*nearDist));
|
||||
Vec2i p2(static_cast<int>(p.x+v1.x*farDist), static_cast<int>(p.y+v1.y*farDist));
|
||||
Vec2i p3(static_cast<int>(p.x+v2.x*nearDist), static_cast<int>(p.y+v2.y*nearDist));
|
||||
Vec2i p4(static_cast<int>(p.x+v2.x*farDist), static_cast<int>(p.y+v2.y*farDist));
|
||||
|
||||
if(hAng>=135 && hAng<=225){
|
||||
return Quad2i(p1, p2, p3, p4);
|
||||
}
|
||||
if(hAng>=45 && hAng<=135){
|
||||
return Quad2i(p3, p1, p4, p2);
|
||||
}
|
||||
if(hAng>=225 && hAng<=315) {
|
||||
return Quad2i(p2, p4, p1, p3);
|
||||
}
|
||||
return Quad2i(p4, p3, p2, p1);
|
||||
|
||||
}
|
||||
|
||||
//game state
|
||||
else{
|
||||
static const int widthNear= 19 * aspectRatio;
|
||||
static const int widthFar= 23 * aspectRatio;
|
||||
static const int near= 5;
|
||||
static const int far= 40;
|
||||
|
||||
return Quad2i(
|
||||
Vec2i(v.x-widthNear, v.y-far),
|
||||
Vec2i(v.x-widthFar, v.y+near),
|
||||
Vec2i(v.x+widthNear, v.y-far),
|
||||
Vec2i(v.x+widthFar, v.y+near));
|
||||
}
|
||||
}
|
||||
|
||||
void GameCamera::switchState(){
|
||||
if(state==sGame){
|
||||
state= sFree;
|
||||
}
|
||||
else{
|
||||
state= sGame;
|
||||
stateTransition= 0.f;
|
||||
lastHAng= hAng;
|
||||
lastVAng= vAng;
|
||||
lastPos= pos;
|
||||
}
|
||||
}
|
||||
|
||||
void GameCamera::centerXZ(float x, float z){
|
||||
pos.x= x;
|
||||
pos.z= z+centerOffsetZ;
|
||||
}
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
void GameCamera::clampPosXZ(float x1, float x2, float z1, float z2){
|
||||
if(pos.x<x1) pos.x= static_cast<float>(x1);
|
||||
if(pos.z<z1) pos.z= static_cast<float>(z1);
|
||||
if(pos.x>x2) pos.x= static_cast<float>(x2);
|
||||
if(pos.z>z2) pos.z= static_cast<float>(z2);
|
||||
}
|
||||
|
||||
void GameCamera::clampPosXYZ(float x1, float x2, float y1, float y2, float z1, float z2){
|
||||
if(pos.x<x1) pos.x= x1;
|
||||
if(pos.y<y1) pos.y= y1;
|
||||
if(pos.z<z1) pos.z= z1;
|
||||
if(pos.x>x2) pos.x= x2;
|
||||
if(pos.y>y2) pos.y= y2;
|
||||
if(pos.z>z2) pos.z= z2;
|
||||
}
|
||||
|
||||
void GameCamera::rotateHV(float h, float v){
|
||||
vAng+=v;
|
||||
hAng+=h;
|
||||
if(hAng>360.f) hAng-=360.f;
|
||||
if(hAng<0.f) hAng+=360.f;
|
||||
}
|
||||
|
||||
//move camera forwad but never change heightFactor
|
||||
void GameCamera::moveForwardH(float d){
|
||||
pos=pos + Vec3f(sin(degToRad(hAng)), 0.f, -cos(degToRad(hAng))) * d;
|
||||
}
|
||||
|
||||
//move camera to a side but never change heightFactor
|
||||
void GameCamera::moveSideH(float d){
|
||||
pos=pos + Vec3f(sin(degToRad(hAng+90)), 0.f, -cos(degToRad(hAng+90))) * d;
|
||||
|
||||
}
|
||||
|
||||
void GameCamera::moveUp(float d){
|
||||
pos.y+= d;
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,114 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_GAMECAMERA_H_
|
||||
#define _GLEST_GAME_GAMECAMERA_H_
|
||||
|
||||
#include "vec.h"
|
||||
#include "math_util.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Graphics::Quad2i;
|
||||
using Shared::Graphics::Vec3f;
|
||||
using Shared::Graphics::Vec3b;
|
||||
using Shared::Graphics::Vec2f;
|
||||
|
||||
class Config;
|
||||
|
||||
// =====================================================
|
||||
// class GameCamera
|
||||
//
|
||||
/// A basic camera that holds information about the game view
|
||||
// =====================================================
|
||||
|
||||
class GameCamera{
|
||||
public:
|
||||
static const float startingVAng;
|
||||
static const float startingHAng;
|
||||
static const float maxHeight;
|
||||
static const float minHeight;
|
||||
static const float transitionSpeed;
|
||||
static const float centerOffsetZ;
|
||||
|
||||
public:
|
||||
enum State{
|
||||
sGame,
|
||||
sFree
|
||||
};
|
||||
|
||||
private:
|
||||
Vec3f pos;
|
||||
Vec3f lastPos;
|
||||
|
||||
float hAng; //YZ plane positive -Z axis
|
||||
float vAng; //XZ plane positive +Z axis
|
||||
float lastHAng;
|
||||
float lastVAng;
|
||||
|
||||
float rotate;
|
||||
|
||||
Vec3f move;
|
||||
Vec3b stopMove;
|
||||
|
||||
float stateTransition;
|
||||
State state;
|
||||
|
||||
int limitX;
|
||||
int limitY;
|
||||
|
||||
|
||||
//config
|
||||
float speed;
|
||||
bool clampBounds;
|
||||
|
||||
public:
|
||||
GameCamera();
|
||||
|
||||
void init(int limitX, int limitY);
|
||||
|
||||
//get
|
||||
float getHAng() const {return hAng;};
|
||||
float getVAng() const {return vAng;}
|
||||
State getState() const {return state;}
|
||||
const Vec3f &getPos() const {return pos;}
|
||||
|
||||
//set
|
||||
void setRotate(int rotate) {this->rotate= rotate;}
|
||||
void setPos(Vec2f pos);
|
||||
|
||||
void setMoveX(float f) {this->stopMove.x= false; this->move.x= f;}
|
||||
void setMoveY(float f) {this->stopMove.y= false; this->move.y= f;}
|
||||
void setMoveZ(float f) {this->stopMove.z= false; this->move.z= f;}
|
||||
|
||||
void stopMoveX() {this->stopMove.x= true;}
|
||||
void stopMoveY() {this->stopMove.y= true;}
|
||||
void stopMoveZ() {this->stopMove.z= true;}
|
||||
|
||||
//other
|
||||
void update();
|
||||
Quad2i computeVisibleQuad() const;
|
||||
void switchState();
|
||||
|
||||
void centerXZ(float x, float z);
|
||||
|
||||
private:
|
||||
void clampPosXYZ(float x1, float x2, float y1, float y2, float z1, float z2);
|
||||
void clampPosXZ(float x1, float x2, float z1, float z2);
|
||||
void rotateHV(float h, float v);
|
||||
void moveForwardH(float dist);
|
||||
void moveSideH(float dist);
|
||||
void moveUp(float dist);
|
||||
};
|
||||
|
||||
}} //end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_GAMECONSTANTS_H_
|
||||
#define _GLEST_GAME_GAMECONSTANTS_H_
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class GameConstants
|
||||
// =====================================================
|
||||
|
||||
enum ControlType{
|
||||
ctClosed,
|
||||
ctCpuEasy,
|
||||
ctCpu,
|
||||
ctCpuUltra,
|
||||
ctCpuMega,
|
||||
ctNetwork,
|
||||
ctHuman
|
||||
};
|
||||
|
||||
class GameConstants{
|
||||
public:
|
||||
static const int maxPlayers= 4;
|
||||
static const int serverPort= 61357;
|
||||
static const int updateFps= 40;
|
||||
static const int cameraFps= 100;
|
||||
static const int networkFramePeriod= 10;
|
||||
static const int networkExtraLatency= 200;
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,88 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_GAMESETTINGS_H_
|
||||
#define _GLEST_GAME_GAMESETTINGS_H_
|
||||
|
||||
#include "game_constants.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class GameSettings
|
||||
// =====================================================
|
||||
|
||||
class GameSettings{
|
||||
private:
|
||||
string description;
|
||||
string map;
|
||||
string tileset;
|
||||
string tech;
|
||||
string scenario;
|
||||
string scenarioDir;
|
||||
string factionTypeNames[GameConstants::maxPlayers]; //faction names
|
||||
|
||||
ControlType factionControls[GameConstants::maxPlayers];
|
||||
|
||||
int thisFactionIndex;
|
||||
int factionCount;
|
||||
int teams[GameConstants::maxPlayers];
|
||||
int startLocationIndex[GameConstants::maxPlayers];
|
||||
|
||||
bool defaultUnits;
|
||||
bool defaultResources;
|
||||
bool defaultVictoryConditions;
|
||||
|
||||
public:
|
||||
//get
|
||||
const string &getDescription() const {return description;}
|
||||
const string &getMap() const {return map;}
|
||||
const string &getTileset() const {return tileset;}
|
||||
const string &getTech() const {return tech;}
|
||||
const string &getScenario() const {return scenario;}
|
||||
const string &getScenarioDir() const {return scenarioDir;}
|
||||
const string &getFactionTypeName(int factionIndex) const {return factionTypeNames[factionIndex];}
|
||||
ControlType getFactionControl(int factionIndex) const {return factionControls[factionIndex];}
|
||||
|
||||
int getThisFactionIndex() const {return thisFactionIndex;}
|
||||
int getFactionCount() const {return factionCount;}
|
||||
int getTeam(int factionIndex) const {return teams[factionIndex];}
|
||||
int getStartLocationIndex(int factionIndex) const {return startLocationIndex[factionIndex];}
|
||||
|
||||
bool getDefaultUnits() const {return defaultUnits;}
|
||||
bool getDefaultResources() const {return defaultResources;}
|
||||
bool getDefaultVictoryConditions() const {return defaultVictoryConditions;}
|
||||
|
||||
//set
|
||||
void setDescription(const string& description) {this->description= description;}
|
||||
void setMap(const string& map) {this->map= map;}
|
||||
void setTileset(const string& tileset) {this->tileset= tileset;}
|
||||
void setTech(const string& tech) {this->tech= tech;}
|
||||
void setScenario(const string& scenario) {this->scenario= scenario;}
|
||||
void setScenarioDir(const string& scenarioDir) {this->scenarioDir= scenarioDir;}
|
||||
|
||||
void setFactionTypeName(int factionIndex, const string& factionTypeName) {this->factionTypeNames[factionIndex]= factionTypeName;}
|
||||
|
||||
void setFactionControl(int factionIndex, ControlType controller) {this->factionControls[factionIndex]= controller;}
|
||||
|
||||
void setThisFactionIndex(int thisFactionIndex) {this->thisFactionIndex= thisFactionIndex;}
|
||||
void setFactionCount(int factionCount) {this->factionCount= factionCount;}
|
||||
void setTeam(int factionIndex, int team) {this->teams[factionIndex]= team;}
|
||||
void setStartLocationIndex(int factionIndex, int startLocationIndex) {this->startLocationIndex[factionIndex]= startLocationIndex;}
|
||||
|
||||
void setDefaultUnits(bool defaultUnits) {this->defaultUnits= defaultUnits;}
|
||||
void setDefaultResources(bool defaultResources) {this->defaultResources= defaultResources;}
|
||||
void setDefaultVictoryConditions(bool defaultVictoryConditions) {this->defaultVictoryConditions= defaultVictoryConditions;}
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,400 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "script_manager.h"
|
||||
|
||||
#include "world.h"
|
||||
#include "lang.h"
|
||||
#include "game_camera.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Lua;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class PlayerModifiers
|
||||
// =====================================================
|
||||
|
||||
PlayerModifiers::PlayerModifiers(){
|
||||
winner= false;
|
||||
aiEnabled= true;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class ScriptManager
|
||||
// =====================================================
|
||||
|
||||
ScriptManager* ScriptManager::thisScriptManager= NULL;
|
||||
const int ScriptManager::messageWrapCount= 30;
|
||||
const int ScriptManager::displayTextWrapCount= 64;
|
||||
|
||||
void ScriptManager::init(World* world, GameCamera *gameCamera){
|
||||
const Scenario* scenario= world->getScenario();
|
||||
|
||||
this->world= world;
|
||||
this->gameCamera= gameCamera;
|
||||
|
||||
//set static instance
|
||||
thisScriptManager= this;
|
||||
|
||||
//register functions
|
||||
luaScript.registerFunction(showMessage, "showMessage");
|
||||
luaScript.registerFunction(setDisplayText, "setDisplayText");
|
||||
luaScript.registerFunction(clearDisplayText, "clearDisplayText");
|
||||
luaScript.registerFunction(setCameraPosition, "setCameraPosition");
|
||||
luaScript.registerFunction(createUnit, "createUnit");
|
||||
luaScript.registerFunction(giveResource, "giveResource");
|
||||
luaScript.registerFunction(givePositionCommand, "givePositionCommand");
|
||||
luaScript.registerFunction(giveProductionCommand, "giveProductionCommand");
|
||||
luaScript.registerFunction(giveUpgradeCommand, "giveUpgradeCommand");
|
||||
luaScript.registerFunction(disableAi, "disableAi");
|
||||
luaScript.registerFunction(setPlayerAsWinner, "setPlayerAsWinner");
|
||||
luaScript.registerFunction(endGame, "endGame");
|
||||
|
||||
luaScript.registerFunction(getStartLocation, "startLocation");
|
||||
luaScript.registerFunction(getUnitPosition, "unitPosition");
|
||||
luaScript.registerFunction(getUnitFaction, "unitFaction");
|
||||
luaScript.registerFunction(getResourceAmount, "resourceAmount");
|
||||
luaScript.registerFunction(getLastCreatedUnitName, "lastCreatedUnitName");
|
||||
luaScript.registerFunction(getLastCreatedUnitId, "lastCreatedUnit");
|
||||
luaScript.registerFunction(getLastDeadUnitName, "lastDeadUnitName");
|
||||
luaScript.registerFunction(getLastDeadUnitId, "lastDeadUnit");
|
||||
luaScript.registerFunction(getUnitCount, "unitCount");
|
||||
luaScript.registerFunction(getUnitCountOfType, "unitCountOfType");
|
||||
|
||||
|
||||
//load code
|
||||
for(int i= 0; i<scenario->getScriptCount(); ++i){
|
||||
const Script* script= scenario->getScript(i);
|
||||
luaScript.loadCode("function " + script->getName() + "()" + script->getCode() + "end\n", script->getName());
|
||||
}
|
||||
|
||||
//setup message box
|
||||
messageBox.init( Lang::getInstance().get("Ok") );
|
||||
messageBox.setEnabled(false);
|
||||
|
||||
//last created unit
|
||||
lastCreatedUnitId= -1;
|
||||
lastDeadUnitId= -1;
|
||||
gameOver= false;
|
||||
|
||||
//call startup function
|
||||
luaScript.beginCall("startup");
|
||||
luaScript.endCall();
|
||||
}
|
||||
|
||||
// ========================== events ===============================================
|
||||
|
||||
void ScriptManager::onMessageBoxOk(){
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
if(!messageQueue.empty()){
|
||||
messageQueue.pop();
|
||||
if(!messageQueue.empty()){
|
||||
messageBox.setText(wrapString(lang.getScenarioString(messageQueue.front().getText()), messageWrapCount));
|
||||
messageBox.setHeader(lang.getScenarioString(messageQueue.front().getHeader()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptManager::onResourceHarvested(){
|
||||
luaScript.beginCall("resourceHarvested");
|
||||
luaScript.endCall();
|
||||
}
|
||||
|
||||
void ScriptManager::onUnitCreated(const Unit* unit){
|
||||
lastCreatedUnitName= unit->getType()->getName();
|
||||
lastCreatedUnitId= unit->getId();
|
||||
luaScript.beginCall("unitCreated");
|
||||
luaScript.endCall();
|
||||
luaScript.beginCall("unitCreatedOfType_"+unit->getType()->getName());
|
||||
luaScript.endCall();
|
||||
}
|
||||
|
||||
void ScriptManager::onUnitDied(const Unit* unit){
|
||||
lastDeadUnitName= unit->getType()->getName();
|
||||
lastDeadUnitId= unit->getId();
|
||||
luaScript.beginCall("unitDied");
|
||||
luaScript.endCall();
|
||||
}
|
||||
|
||||
// ========================== lua wrappers ===============================================
|
||||
|
||||
string ScriptManager::wrapString(const string &str, int wrapCount){
|
||||
|
||||
string returnString;
|
||||
|
||||
int letterCount= 0;
|
||||
for(int i= 0; i<str.size(); ++i){
|
||||
if(letterCount>wrapCount && str[i]==' '){
|
||||
returnString+= '\n';
|
||||
letterCount= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
returnString+= str[i];
|
||||
}
|
||||
++letterCount;
|
||||
}
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
void ScriptManager::showMessage(const string &text, const string &header){
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
messageQueue.push(ScriptManagerMessage(text, header));
|
||||
messageBox.setEnabled(true);
|
||||
messageBox.setText(wrapString(lang.getScenarioString(messageQueue.front().getText()), messageWrapCount));
|
||||
messageBox.setHeader(lang.getScenarioString(messageQueue.front().getHeader()));
|
||||
}
|
||||
|
||||
void ScriptManager::clearDisplayText(){
|
||||
displayText= "";
|
||||
}
|
||||
|
||||
void ScriptManager::setDisplayText(const string &text){
|
||||
displayText= wrapString(Lang::getInstance().getScenarioString(text), displayTextWrapCount);
|
||||
}
|
||||
|
||||
void ScriptManager::setCameraPosition(const Vec2i &pos){
|
||||
gameCamera->centerXZ(pos.x, pos.y);
|
||||
}
|
||||
|
||||
void ScriptManager::createUnit(const string &unitName, int factionIndex, Vec2i pos){
|
||||
world->createUnit(unitName, factionIndex, pos);
|
||||
}
|
||||
|
||||
void ScriptManager::giveResource(const string &resourceName, int factionIndex, int amount){
|
||||
world->giveResource(resourceName, factionIndex, amount);
|
||||
}
|
||||
|
||||
void ScriptManager::givePositionCommand(int unitId, const string &commandName, const Vec2i &pos){
|
||||
world->givePositionCommand(unitId, commandName, pos);
|
||||
}
|
||||
|
||||
void ScriptManager::giveProductionCommand(int unitId, const string &producedName){
|
||||
world->giveProductionCommand(unitId, producedName);
|
||||
}
|
||||
|
||||
void ScriptManager::giveUpgradeCommand(int unitId, const string &producedName){
|
||||
world->giveUpgradeCommand(unitId, producedName);
|
||||
}
|
||||
|
||||
void ScriptManager::disableAi(int factionIndex){
|
||||
if(factionIndex<GameConstants::maxPlayers){
|
||||
playerModifiers[factionIndex].disableAi();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptManager::setPlayerAsWinner(int factionIndex){
|
||||
if(factionIndex<GameConstants::maxPlayers){
|
||||
playerModifiers[factionIndex].setAsWinner();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptManager::endGame(){
|
||||
gameOver= true;
|
||||
}
|
||||
|
||||
Vec2i ScriptManager::getStartLocation(int factionIndex){
|
||||
return world->getStartLocation(factionIndex);
|
||||
}
|
||||
|
||||
|
||||
Vec2i ScriptManager::getUnitPosition(int unitId){
|
||||
return world->getUnitPosition(unitId);
|
||||
}
|
||||
|
||||
int ScriptManager::getUnitFaction(int unitId){
|
||||
return world->getUnitFactionIndex(unitId);
|
||||
}
|
||||
|
||||
int ScriptManager::getResourceAmount(const string &resourceName, int factionIndex){
|
||||
return world->getResourceAmount(resourceName, factionIndex);
|
||||
}
|
||||
|
||||
const string &ScriptManager::getLastCreatedUnitName(){
|
||||
return lastCreatedUnitName;
|
||||
}
|
||||
|
||||
int ScriptManager::getLastCreatedUnitId(){
|
||||
return lastCreatedUnitId;
|
||||
}
|
||||
|
||||
const string &ScriptManager::getLastDeadUnitName(){
|
||||
return lastDeadUnitName;
|
||||
}
|
||||
|
||||
int ScriptManager::getLastDeadUnitId(){
|
||||
return lastDeadUnitId;
|
||||
}
|
||||
|
||||
int ScriptManager::getUnitCount(int factionIndex){
|
||||
return world->getUnitCount(factionIndex);
|
||||
}
|
||||
|
||||
int ScriptManager::getUnitCountOfType(int factionIndex, const string &typeName){
|
||||
return world->getUnitCountOfType(factionIndex, typeName);
|
||||
}
|
||||
|
||||
// ========================== lua callbacks ===============================================
|
||||
|
||||
int ScriptManager::showMessage(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->showMessage(luaArguments.getString(-2), luaArguments.getString(-1));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::setDisplayText(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->setDisplayText(luaArguments.getString(-1));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::clearDisplayText(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->clearDisplayText();
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::setCameraPosition(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->setCameraPosition(Vec2i(luaArguments.getVec2i(-1)));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::createUnit(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->createUnit(
|
||||
luaArguments.getString(-3),
|
||||
luaArguments.getInt(-2),
|
||||
luaArguments.getVec2i(-1));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::giveResource(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->giveResource(luaArguments.getString(-3), luaArguments.getInt(-2), luaArguments.getInt(-1));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::givePositionCommand(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->givePositionCommand(
|
||||
luaArguments.getInt(-3),
|
||||
luaArguments.getString(-2),
|
||||
luaArguments.getVec2i(-1));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
|
||||
int ScriptManager::giveProductionCommand(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->giveProductionCommand(
|
||||
luaArguments.getInt(-2),
|
||||
luaArguments.getString(-1));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::giveUpgradeCommand(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->giveUpgradeCommand(
|
||||
luaArguments.getInt(-2),
|
||||
luaArguments.getString(-1));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::disableAi(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->disableAi(luaArguments.getInt(-1));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::setPlayerAsWinner(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->setPlayerAsWinner(luaArguments.getInt(-1));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::endGame(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
thisScriptManager->endGame();
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::getStartLocation(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
Vec2i pos= thisScriptManager->getStartLocation(luaArguments.getInt(-1));
|
||||
luaArguments.returnVec2i(pos);
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::getUnitPosition(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
Vec2i pos= thisScriptManager->getUnitPosition(luaArguments.getInt(-1));
|
||||
luaArguments.returnVec2i(pos);
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::getUnitFaction(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
int factionIndex= thisScriptManager->getUnitFaction(luaArguments.getInt(-1));
|
||||
luaArguments.returnInt(factionIndex);
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::getResourceAmount(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
luaArguments.returnInt(thisScriptManager->getResourceAmount(luaArguments.getString(-2), luaArguments.getInt(-1)));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::getLastCreatedUnitName(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
luaArguments.returnString(thisScriptManager->getLastCreatedUnitName());
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::getLastCreatedUnitId(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
luaArguments.returnInt(thisScriptManager->getLastCreatedUnitId());
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::getLastDeadUnitName(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
luaArguments.returnString(thisScriptManager->getLastDeadUnitName());
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::getLastDeadUnitId(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
luaArguments.returnInt(thisScriptManager->getLastDeadUnitId());
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::getUnitCount(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
luaArguments.returnInt(thisScriptManager->getUnitCount(luaArguments.getInt(-1)));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
int ScriptManager::getUnitCountOfType(LuaHandle* luaHandle){
|
||||
LuaArguments luaArguments(luaHandle);
|
||||
luaArguments.returnInt(thisScriptManager->getUnitCountOfType(luaArguments.getInt(-2), luaArguments.getString(-1)));
|
||||
return luaArguments.getReturnCount();
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,183 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_SCRIPT_MANAGER_H_
|
||||
#define _GLEST_GAME_SCRIPT_MANAGER_H_
|
||||
|
||||
#include <string>
|
||||
#include <queue>
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "vec.h"
|
||||
|
||||
#include "components.h"
|
||||
#include "game_constants.h"
|
||||
|
||||
using std::string;
|
||||
using std::queue;
|
||||
using Shared::Graphics::Vec2i;
|
||||
using Shared::Lua::LuaScript;
|
||||
using Shared::Lua::LuaHandle;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class World;
|
||||
class Unit;
|
||||
class GameCamera;
|
||||
|
||||
// =====================================================
|
||||
// class ScriptManagerMessage
|
||||
// =====================================================
|
||||
|
||||
class ScriptManagerMessage{
|
||||
private:
|
||||
string text;
|
||||
string header;
|
||||
|
||||
public:
|
||||
ScriptManagerMessage(string text, string header) {this->text= text, this->header= header;}
|
||||
const string &getText() const {return text;}
|
||||
const string &getHeader() const {return header;}
|
||||
};
|
||||
|
||||
class PlayerModifiers{
|
||||
public:
|
||||
PlayerModifiers();
|
||||
|
||||
void disableAi() {aiEnabled= false;}
|
||||
void setAsWinner() {winner= true;}
|
||||
|
||||
bool getWinner() const {return winner;}
|
||||
bool getAiEnabled() const {return aiEnabled;}
|
||||
|
||||
private:
|
||||
bool winner;
|
||||
bool aiEnabled;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class ScriptManager
|
||||
// =====================================================
|
||||
|
||||
class ScriptManager{
|
||||
private:
|
||||
typedef queue<ScriptManagerMessage> MessageQueue;
|
||||
|
||||
private:
|
||||
|
||||
//lua
|
||||
string code;
|
||||
LuaScript luaScript;
|
||||
|
||||
//world
|
||||
World *world;
|
||||
GameCamera *gameCamera;
|
||||
|
||||
//misc
|
||||
MessageQueue messageQueue;
|
||||
GraphicMessageBox messageBox;
|
||||
string displayText;
|
||||
|
||||
//last created unit
|
||||
string lastCreatedUnitName;
|
||||
int lastCreatedUnitId;
|
||||
|
||||
//last dead unit
|
||||
string lastDeadUnitName;
|
||||
int lastDeadUnitId;
|
||||
|
||||
// end game state
|
||||
bool gameOver;
|
||||
PlayerModifiers playerModifiers[GameConstants::maxPlayers];
|
||||
|
||||
private:
|
||||
static ScriptManager* thisScriptManager;
|
||||
|
||||
private:
|
||||
static const int messageWrapCount;
|
||||
static const int displayTextWrapCount;
|
||||
|
||||
public:
|
||||
void init(World* world, GameCamera *gameCamera);
|
||||
|
||||
//message box functions
|
||||
bool getMessageBoxEnabled() const {return !messageQueue.empty();}
|
||||
GraphicMessageBox* getMessageBox() {return &messageBox;}
|
||||
string getDisplayText() const {return displayText;}
|
||||
bool getGameOver() const {return gameOver;}
|
||||
const PlayerModifiers *getPlayerModifiers(int factionIndex) const {return &playerModifiers[factionIndex];}
|
||||
|
||||
//events
|
||||
void onMessageBoxOk();
|
||||
void onResourceHarvested();
|
||||
void onUnitCreated(const Unit* unit);
|
||||
void onUnitDied(const Unit* unit);
|
||||
|
||||
private:
|
||||
|
||||
string wrapString(const string &str, int wrapCount);
|
||||
|
||||
//wrappers, commands
|
||||
void showMessage(const string &text, const string &header);
|
||||
void clearDisplayText();
|
||||
void setDisplayText(const string &text);
|
||||
void setCameraPosition(const Vec2i &pos);
|
||||
void createUnit(const string &unitName, int factionIndex, Vec2i pos);
|
||||
void giveResource(const string &resourceName, int factionIndex, int amount);
|
||||
void givePositionCommand(int unitId, const string &producedName, const Vec2i &pos);
|
||||
void giveProductionCommand(int unitId, const string &producedName);
|
||||
void giveUpgradeCommand(int unitId, const string &upgradeName);
|
||||
void disableAi(int factionIndex);
|
||||
void setPlayerAsWinner(int factionIndex);
|
||||
void endGame();
|
||||
|
||||
//wrappers, queries
|
||||
Vec2i getStartLocation(int factionIndex);
|
||||
Vec2i getUnitPosition(int unitId);
|
||||
int getUnitFaction(int unitId);
|
||||
int getResourceAmount(const string &resourceName, int factionIndex);
|
||||
const string &getLastCreatedUnitName();
|
||||
int getLastCreatedUnitId();
|
||||
const string &getLastDeadUnitName();
|
||||
int getLastDeadUnitId();
|
||||
int getUnitCount(int factionIndex);
|
||||
int getUnitCountOfType(int factionIndex, const string &typeName);
|
||||
|
||||
//callbacks, commands
|
||||
static int showMessage(LuaHandle* luaHandle);
|
||||
static int setDisplayText(LuaHandle* luaHandle);
|
||||
static int clearDisplayText(LuaHandle* luaHandle);
|
||||
static int setCameraPosition(LuaHandle* luaHandle);
|
||||
static int createUnit(LuaHandle* luaHandle);
|
||||
static int giveResource(LuaHandle* luaHandle);
|
||||
static int givePositionCommand(LuaHandle* luaHandle);
|
||||
static int giveProductionCommand(LuaHandle* luaHandle);
|
||||
static int giveUpgradeCommand(LuaHandle* luaHandle);
|
||||
static int disableAi(LuaHandle* luaHandle);
|
||||
static int setPlayerAsWinner(LuaHandle* luaHandle);
|
||||
static int endGame(LuaHandle* luaHandle);
|
||||
|
||||
//callbacks, queries
|
||||
static int getStartLocation(LuaHandle* luaHandle);
|
||||
static int getUnitPosition(LuaHandle* luaHandle);
|
||||
static int getUnitFaction(LuaHandle* luaHandle);
|
||||
static int getResourceAmount(LuaHandle* luaHandle);
|
||||
static int getLastCreatedUnitName(LuaHandle* luaHandle);
|
||||
static int getLastCreatedUnitId(LuaHandle* luaHandle);
|
||||
static int getLastDeadUnitName(LuaHandle* luaHandle);
|
||||
static int getLastDeadUnitId(LuaHandle* luaHandle);
|
||||
static int getUnitCount(LuaHandle* luaHandle);
|
||||
static int getUnitCountOfType(LuaHandle* luaHandle);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,54 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "stats.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
PlayerStats::PlayerStats(){
|
||||
victory= false;
|
||||
|
||||
kills= 0;
|
||||
deaths= 0;
|
||||
unitsProduced= 0;
|
||||
resourcesHarvested= 0;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Stats
|
||||
// =====================================================
|
||||
|
||||
void Stats::init(int factionCount, int thisFactionIndex, const string& description){
|
||||
this->thisFactionIndex= thisFactionIndex;
|
||||
this->factionCount= factionCount;
|
||||
this->description= description;
|
||||
}
|
||||
|
||||
void Stats::setVictorious(int playerIndex){
|
||||
playerStats[playerIndex].victory= true;
|
||||
}
|
||||
|
||||
void Stats::kill(int killerFactionIndex, int killedFactionIndex){
|
||||
playerStats[killerFactionIndex].kills++;
|
||||
playerStats[killedFactionIndex].deaths++;
|
||||
}
|
||||
|
||||
void Stats::produce(int producerFactionIndex){
|
||||
playerStats[producerFactionIndex].unitsProduced++;
|
||||
}
|
||||
|
||||
void Stats::harvest(int harvesterFactionIndex, int amount){
|
||||
playerStats[harvesterFactionIndex].resourcesHarvested+= amount;
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,79 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_STATS_H_
|
||||
#define _GLEST_GAME_STATS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "game_constants.h"
|
||||
#include "faction.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
struct PlayerStats{
|
||||
PlayerStats();
|
||||
|
||||
ControlType control;
|
||||
string factionTypeName;
|
||||
int teamIndex;
|
||||
bool victory;
|
||||
int kills;
|
||||
int deaths;
|
||||
int unitsProduced;
|
||||
int resourcesHarvested;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class Stats
|
||||
//
|
||||
/// Player statistics that are shown after the game ends
|
||||
// =====================================================
|
||||
|
||||
class Stats{
|
||||
private:
|
||||
PlayerStats playerStats[GameConstants::maxPlayers];
|
||||
|
||||
string description;
|
||||
int factionCount;
|
||||
int thisFactionIndex;
|
||||
|
||||
public:
|
||||
void init(int factionCount, int thisFactionIndex, const string &description);
|
||||
|
||||
string getDescription() const {return description;}
|
||||
int getThisFactionIndex() const {return thisFactionIndex;}
|
||||
int getFactionCount() const {return factionCount;}
|
||||
|
||||
const string &getFactionTypeName(int factionIndex) const {return playerStats[factionIndex].factionTypeName;}
|
||||
ControlType getControl(int factionIndex) const {return playerStats[factionIndex].control;}
|
||||
bool getVictory(int factionIndex) const {return playerStats[factionIndex].victory;}
|
||||
int getTeam(int factionIndex) const {return playerStats[factionIndex].teamIndex;}
|
||||
int getKills(int factionIndex) const {return playerStats[factionIndex].kills;}
|
||||
int getDeaths(int factionIndex) const {return playerStats[factionIndex].deaths;}
|
||||
int getUnitsProduced(int factionIndex) const {return playerStats[factionIndex].unitsProduced;}
|
||||
int getResourcesHarvested(int factionIndex) const {return playerStats[factionIndex].resourcesHarvested;}
|
||||
|
||||
void setDescription(const string& description) {this->description = description;}
|
||||
void setFactionTypeName(int playerIndex, const string& factionTypeName) {playerStats[playerIndex].factionTypeName= factionTypeName;}
|
||||
void setControl(int playerIndex, ControlType control) {playerStats[playerIndex].control= control;}
|
||||
void setTeam(int playerIndex, int teamIndex) {playerStats[playerIndex].teamIndex= teamIndex;}
|
||||
void setVictorious(int playerIndex);
|
||||
void kill(int killerFactionIndex, int killedFactionIndex);
|
||||
void produce(int producerFactionIndex);
|
||||
void harvest(int harvesterFactionIndex, int amount);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Config
|
||||
// =====================================================
|
||||
|
||||
Config::Config(){
|
||||
properties.load("glest.ini");
|
||||
}
|
||||
|
||||
Config &Config::getInstance(){
|
||||
static Config config;
|
||||
return config;
|
||||
}
|
||||
|
||||
void Config::save(const string &path){
|
||||
properties.save(path);
|
||||
}
|
||||
|
||||
int Config::getInt(const string &key) const{
|
||||
return properties.getInt(key);
|
||||
}
|
||||
|
||||
bool Config::getBool(const string &key) const{
|
||||
return properties.getBool(key);
|
||||
}
|
||||
|
||||
float Config::getFloat(const string &key) const{
|
||||
return properties.getFloat(key);
|
||||
}
|
||||
|
||||
const string &Config::getString(const string &key) const{
|
||||
return properties.getString(key);
|
||||
}
|
||||
|
||||
void Config::setInt(const string &key, int value){
|
||||
properties.setInt(key, value);
|
||||
}
|
||||
|
||||
void Config::setBool(const string &key, bool value){
|
||||
properties.setBool(key, value);
|
||||
}
|
||||
|
||||
void Config::setFloat(const string &key, float value){
|
||||
properties.setFloat(key, value);
|
||||
}
|
||||
|
||||
void Config::setString(const string &key, const string &value){
|
||||
properties.setString(key, value);
|
||||
}
|
||||
|
||||
string Config::toString(){
|
||||
return properties.toString();
|
||||
}
|
||||
|
||||
}}// end namespace
|
|
@ -0,0 +1,53 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_CONFIG_H_
|
||||
#define _GLEST_GAME_CONFIG_H_
|
||||
|
||||
#include "properties.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Util::Properties;
|
||||
|
||||
// =====================================================
|
||||
// class Config
|
||||
//
|
||||
// Game configuration
|
||||
// =====================================================
|
||||
|
||||
class Config{
|
||||
private:
|
||||
Properties properties;
|
||||
|
||||
private:
|
||||
Config();
|
||||
|
||||
public:
|
||||
static Config &getInstance();
|
||||
void save(const string &path="glest.ini");
|
||||
|
||||
int getInt(const string &key) const;
|
||||
bool getBool(const string &key) const;
|
||||
float getFloat(const string &key) const;
|
||||
const string &getString(const string &key) const;
|
||||
|
||||
void setInt(const string &key, int value);
|
||||
void setBool(const string &key, bool value);
|
||||
void setFloat(const string &key, float value);
|
||||
void setString(const string &key, const string &value);
|
||||
|
||||
string toString();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,144 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "core_data.h"
|
||||
|
||||
#include "logger.h"
|
||||
#include "renderer.h"
|
||||
#include "graphics_interface.h"
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Sound;
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class CoreData
|
||||
// =====================================================
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
CoreData &CoreData::getInstance(){
|
||||
static CoreData coreData;
|
||||
return coreData;
|
||||
}
|
||||
|
||||
CoreData::~CoreData(){
|
||||
deleteValues(waterSounds.getSounds().begin(), waterSounds.getSounds().end());
|
||||
}
|
||||
|
||||
void CoreData::load(){
|
||||
const string dir="data/core";
|
||||
Logger::getInstance().add("Core data");
|
||||
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
//textures
|
||||
backgroundTexture= renderer.newTexture2D(rsGlobal);
|
||||
backgroundTexture->setMipmap(false);
|
||||
backgroundTexture->getPixmap()->load(dir+"/menu/textures/back.tga");
|
||||
|
||||
fireTexture= renderer.newTexture2D(rsGlobal);
|
||||
fireTexture->setFormat(Texture::fAlpha);
|
||||
fireTexture->getPixmap()->init(1);
|
||||
fireTexture->getPixmap()->load(dir+"/misc_textures/fire_particle.tga");
|
||||
|
||||
snowTexture= renderer.newTexture2D(rsGlobal);
|
||||
snowTexture->setMipmap(false);
|
||||
snowTexture->setFormat(Texture::fAlpha);
|
||||
snowTexture->getPixmap()->init(1);
|
||||
snowTexture->getPixmap()->load(dir+"/misc_textures/snow_particle.tga");
|
||||
|
||||
customTexture= renderer.newTexture2D(rsGlobal);
|
||||
customTexture->getPixmap()->load("data/core/menu/textures/custom_texture.tga");
|
||||
|
||||
logoTexture= renderer.newTexture2D(rsGlobal);
|
||||
logoTexture->setMipmap(false);
|
||||
logoTexture->getPixmap()->load(dir+"/menu/textures/logo.tga");
|
||||
|
||||
waterSplashTexture= renderer.newTexture2D(rsGlobal);
|
||||
waterSplashTexture->setFormat(Texture::fAlpha);
|
||||
waterSplashTexture->getPixmap()->init(1);
|
||||
waterSplashTexture->getPixmap()->load(dir+"/misc_textures/water_splash.tga");
|
||||
|
||||
buttonSmallTexture= renderer.newTexture2D(rsGlobal);
|
||||
buttonSmallTexture->getPixmap()->load(dir+"/menu/textures/button_small.tga");
|
||||
|
||||
buttonBigTexture= renderer.newTexture2D(rsGlobal);
|
||||
buttonBigTexture->getPixmap()->load(dir+"/menu/textures/button_big.tga");
|
||||
|
||||
//display font
|
||||
Config &config= Config::getInstance();
|
||||
string displayFontName= config.getString("FontDisplay");
|
||||
|
||||
displayFont= renderer.newFont(rsGlobal);
|
||||
displayFont->setType(displayFontName);
|
||||
displayFont->setSize(computeFontSize(15));
|
||||
|
||||
//menu fonts
|
||||
string menuFontName= config.getString("FontMenu");
|
||||
|
||||
menuFontSmall= renderer.newFont(rsGlobal);
|
||||
menuFontSmall->setType(menuFontName);
|
||||
menuFontSmall->setSize(computeFontSize(12));
|
||||
|
||||
menuFontNormal= renderer.newFont(rsGlobal);
|
||||
menuFontNormal->setType(menuFontName);
|
||||
menuFontNormal->setSize(computeFontSize(16));
|
||||
menuFontNormal->setWidth(Font::wBold);
|
||||
|
||||
menuFontBig= renderer.newFont(rsGlobal);
|
||||
menuFontBig->setType(menuFontName);
|
||||
menuFontBig->setSize(computeFontSize(20));
|
||||
|
||||
menuFontVeryBig= renderer.newFont(rsGlobal);
|
||||
menuFontVeryBig->setType(menuFontName);
|
||||
menuFontVeryBig->setSize(computeFontSize(25));
|
||||
|
||||
//console font
|
||||
string consoleFontName= Config::getInstance().getString("FontConsole");
|
||||
|
||||
consoleFont= renderer.newFont(rsGlobal);
|
||||
consoleFont->setType(consoleFontName);
|
||||
consoleFont->setSize(computeFontSize(16));
|
||||
|
||||
//sounds
|
||||
clickSoundA.load(dir+"/menu/sound/click_a.wav");
|
||||
clickSoundB.load(dir+"/menu/sound/click_b.wav");
|
||||
clickSoundC.load(dir+"/menu/sound/click_c.wav");
|
||||
introMusic.open(dir+"/menu/music/intro_music.ogg");
|
||||
introMusic.setNext(&menuMusic);
|
||||
menuMusic.open(dir+"/menu/music/menu_music.ogg");
|
||||
menuMusic.setNext(&menuMusic);
|
||||
waterSounds.resize(6);
|
||||
for(int i=0; i<6; ++i){
|
||||
waterSounds[i]= new StaticSound();
|
||||
waterSounds[i]->load(dir+"/water_sounds/water"+intToStr(i)+".wav");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int CoreData::computeFontSize(int size){
|
||||
int screenH= Config::getInstance().getInt("ScreenHeight");
|
||||
int rs= size*screenH/750;
|
||||
if(rs<12){
|
||||
rs= 12;
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
// ================== PRIVATE ========================
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,98 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_COREDATA_H_
|
||||
#define _GLEST_GAME_COREDATA_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "sound.h"
|
||||
#include "font.h"
|
||||
#include "texture.h"
|
||||
#include "sound_container.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Graphics::Texture2D;
|
||||
using Shared::Graphics::Texture3D;
|
||||
using Shared::Graphics::Font2D;
|
||||
using Shared::Sound::StrSound;
|
||||
using Shared::Sound::StaticSound;
|
||||
|
||||
// =====================================================
|
||||
// class CoreData
|
||||
//
|
||||
/// Data shared ammont all the ProgramStates
|
||||
// =====================================================
|
||||
|
||||
class CoreData{
|
||||
private:
|
||||
StrSound introMusic;
|
||||
StrSound menuMusic;
|
||||
StaticSound clickSoundA;
|
||||
StaticSound clickSoundB;
|
||||
StaticSound clickSoundC;
|
||||
SoundContainer waterSounds;
|
||||
|
||||
Texture2D *logoTexture;
|
||||
Texture2D *backgroundTexture;
|
||||
Texture2D *fireTexture;
|
||||
Texture2D *snowTexture;
|
||||
Texture2D *waterSplashTexture;
|
||||
Texture2D *customTexture;
|
||||
Texture2D *buttonSmallTexture;
|
||||
Texture2D *buttonBigTexture;
|
||||
|
||||
Font2D *displayFont;
|
||||
Font2D *menuFontNormal;
|
||||
Font2D *menuFontSmall;
|
||||
Font2D *menuFontBig;
|
||||
Font2D *menuFontVeryBig;
|
||||
Font2D *consoleFont;
|
||||
|
||||
public:
|
||||
static CoreData &getInstance();
|
||||
~CoreData();
|
||||
|
||||
void load();
|
||||
|
||||
Texture2D *getBackgroundTexture() const {return backgroundTexture;}
|
||||
Texture2D *getFireTexture() const {return fireTexture;}
|
||||
Texture2D *getSnowTexture() const {return snowTexture;}
|
||||
Texture2D *getLogoTexture() const {return logoTexture;}
|
||||
Texture2D *getWaterSplashTexture() const {return waterSplashTexture;}
|
||||
Texture2D *getCustomTexture() const {return customTexture;}
|
||||
Texture2D *getButtonSmallTexture() const {return buttonSmallTexture;}
|
||||
Texture2D *getButtonBigTexture() const {return buttonBigTexture;}
|
||||
|
||||
StrSound *getIntroMusic() {return &introMusic;}
|
||||
StrSound *getMenuMusic() {return &menuMusic;}
|
||||
StaticSound *getClickSoundA() {return &clickSoundA;}
|
||||
StaticSound *getClickSoundB() {return &clickSoundB;}
|
||||
StaticSound *getClickSoundC() {return &clickSoundC;}
|
||||
StaticSound *getWaterSound() {return waterSounds.getRandSound();}
|
||||
|
||||
Font2D *getDisplayFont() const {return displayFont;}
|
||||
Font2D *getMenuFontSmall() const {return menuFontSmall;}
|
||||
Font2D *getMenuFontNormal() const {return menuFontNormal;}
|
||||
Font2D *getMenuFontBig() const {return menuFontBig;}
|
||||
Font2D *getMenuFontVeryBig() const {return menuFontVeryBig;}
|
||||
Font2D *getConsoleFont() const {return consoleFont;}
|
||||
|
||||
private:
|
||||
CoreData(){};
|
||||
|
||||
int computeFontSize(int size);
|
||||
};
|
||||
|
||||
}} //end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,76 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "lang.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Lang
|
||||
// =====================================================
|
||||
|
||||
Lang &Lang::getInstance(){
|
||||
static Lang lang;
|
||||
return lang;
|
||||
}
|
||||
|
||||
void Lang::loadStrings(const string &language){
|
||||
this->language= language;
|
||||
strings.clear();
|
||||
strings.load("data/lang/"+language+".lng");
|
||||
}
|
||||
|
||||
void Lang::loadScenarioStrings(const string &scenarioDir, const string &scenarioName){
|
||||
string path= scenarioDir + "/" + scenarioName + "/" + scenarioName + "_" + language + ".lng";
|
||||
|
||||
scenarioStrings.clear();
|
||||
|
||||
//try to load the current language first
|
||||
if(fileExists(path)){
|
||||
scenarioStrings.load(path);
|
||||
}
|
||||
else{
|
||||
//try english otherwise
|
||||
string path= scenarioDir + "/" +scenarioName + "/" + scenarioName + "_english.lng";
|
||||
if(fileExists(path)){
|
||||
scenarioStrings.load(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string Lang::get(const string &s){
|
||||
try{
|
||||
return strings.getString(s);
|
||||
}
|
||||
catch(exception &){
|
||||
return "???" + s + "???";
|
||||
}
|
||||
}
|
||||
|
||||
string Lang::getScenarioString(const string &s){
|
||||
try{
|
||||
return scenarioStrings.getString(s);
|
||||
}
|
||||
catch(exception &){
|
||||
return "???" + s + "???";
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,46 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_LANG_H_
|
||||
#define _GLEST_GAME_LANG_H_
|
||||
|
||||
#include "properties.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Util::Properties;
|
||||
|
||||
// =====================================================
|
||||
// class Lang
|
||||
//
|
||||
// String table
|
||||
// =====================================================
|
||||
|
||||
class Lang{
|
||||
private:
|
||||
string language;
|
||||
Properties strings;
|
||||
Properties scenarioStrings;
|
||||
|
||||
private:
|
||||
Lang(){};
|
||||
|
||||
public:
|
||||
static Lang &getInstance();
|
||||
void loadStrings(const string &language);
|
||||
void loadScenarioStrings(const string &scenarioDir, const string &scenarioName);
|
||||
string get(const string &s);
|
||||
string getScenarioString(const string &s);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,77 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "metrics.h"
|
||||
|
||||
#include "element_type.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
|
||||
// =====================================================
|
||||
// class Metrics
|
||||
// =====================================================
|
||||
|
||||
Metrics::Metrics(){
|
||||
Config &config= Config::getInstance();
|
||||
|
||||
virtualW= 1000;
|
||||
virtualH= 750;
|
||||
|
||||
screenW= config.getInt("ScreenWidth");
|
||||
screenH= config.getInt("ScreenHeight");
|
||||
|
||||
minimapX= 10;
|
||||
minimapY= 750-128-30+16;
|
||||
minimapW= 128;
|
||||
minimapH= 128;
|
||||
|
||||
displayX= 800;
|
||||
displayY= 250;
|
||||
displayW= 128;
|
||||
displayH= 480;
|
||||
}
|
||||
|
||||
const Metrics &Metrics::getInstance(){
|
||||
static const Metrics metrics;
|
||||
return metrics;
|
||||
}
|
||||
|
||||
float Metrics::getAspectRatio() const{
|
||||
return static_cast<float>(screenW)/screenH;
|
||||
}
|
||||
|
||||
int Metrics::toVirtualX(int w) const{
|
||||
return w*virtualW/screenW;
|
||||
}
|
||||
|
||||
int Metrics::toVirtualY(int h) const{
|
||||
return h*virtualH/screenH;
|
||||
}
|
||||
|
||||
bool Metrics::isInDisplay(int x, int y) const{
|
||||
return
|
||||
x > displayX &&
|
||||
y > displayY &&
|
||||
x < displayX+displayW &&
|
||||
y < displayY+displayH;
|
||||
}
|
||||
|
||||
bool Metrics::isInMinimap(int x, int y) const{
|
||||
return
|
||||
x > minimapX &&
|
||||
y > minimapY &&
|
||||
x < minimapX+minimapW &&
|
||||
y < minimapY+minimapH;
|
||||
}
|
||||
|
||||
}}// end namespace
|
|
@ -0,0 +1,67 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_METRICS_H_
|
||||
#define _GLEST_GAME_METRICS_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Metrics
|
||||
// =====================================================
|
||||
|
||||
class Metrics{
|
||||
private:
|
||||
int virtualW;
|
||||
int virtualH;
|
||||
int screenW;
|
||||
int screenH;
|
||||
int minimapX;
|
||||
int minimapY;
|
||||
int minimapW;
|
||||
int minimapH;
|
||||
int displayX;
|
||||
int displayY;
|
||||
int displayH;
|
||||
int displayW;
|
||||
|
||||
private:
|
||||
Metrics();
|
||||
|
||||
public:
|
||||
static const Metrics &getInstance();
|
||||
|
||||
int getVirtualW() const {return virtualW;}
|
||||
int getVirtualH() const {return virtualH;}
|
||||
int getScreenW() const {return screenW;}
|
||||
int getScreenH() const {return screenH;}
|
||||
int getMinimapX() const {return minimapX;}
|
||||
int getMinimapY() const {return minimapY;}
|
||||
int getMinimapW() const {return minimapW;}
|
||||
int getMinimapH() const {return minimapH;}
|
||||
int getDisplayX() const {return displayX;}
|
||||
int getDisplayY() const {return displayY;}
|
||||
int getDisplayH() const {return displayH;}
|
||||
int getDisplayW() const {return displayW;}
|
||||
float getAspectRatio() const;
|
||||
|
||||
int toVirtualX(int w) const;
|
||||
int toVirtualY(int h) const;
|
||||
|
||||
bool isInDisplay(int x, int y) const;
|
||||
bool isInMinimap(int x, int y) const;
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,240 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "particle_type.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "core_data.h"
|
||||
#include "xml_parser.h"
|
||||
#include "renderer.h"
|
||||
#include "config.h"
|
||||
#include "game_constants.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Xml;
|
||||
using namespace Shared::Graphics;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class ParticleSystemType
|
||||
// =====================================================
|
||||
|
||||
ParticleSystemType::ParticleSystemType(){
|
||||
}
|
||||
|
||||
void ParticleSystemType::load(const XmlNode *particleSystemNode, const string &dir){
|
||||
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
//texture
|
||||
const XmlNode *textureNode= particleSystemNode->getChild("texture");
|
||||
bool textureEnabled= textureNode->getAttribute("value")->getBoolValue();
|
||||
if(textureEnabled){
|
||||
texture= renderer.newTexture2D(rsGame);
|
||||
if(textureNode->getAttribute("luminance")->getBoolValue()){
|
||||
texture->setFormat(Texture::fAlpha);
|
||||
texture->getPixmap()->init(1);
|
||||
}
|
||||
else{
|
||||
texture->getPixmap()->init(4);
|
||||
}
|
||||
texture->load(dir + "/" + textureNode->getAttribute("path")->getRestrictedValue());
|
||||
}
|
||||
else{
|
||||
texture= NULL;
|
||||
}
|
||||
|
||||
//model
|
||||
const XmlNode *modelNode= particleSystemNode->getChild("model");
|
||||
bool modelEnabled= modelNode->getAttribute("value")->getBoolValue();
|
||||
if(modelEnabled){
|
||||
string path= modelNode->getAttribute("path")->getRestrictedValue();
|
||||
model= renderer.newModel(rsGame);
|
||||
model->load(dir + "/" + path);
|
||||
}
|
||||
else{
|
||||
model= NULL;
|
||||
}
|
||||
|
||||
//primitive
|
||||
const XmlNode *primitiveNode= particleSystemNode->getChild("primitive");
|
||||
primitive= primitiveNode->getAttribute("value")->getRestrictedValue();
|
||||
|
||||
//offset
|
||||
const XmlNode *offsetNode= particleSystemNode->getChild("offset");
|
||||
offset.x= offsetNode->getAttribute("x")->getFloatValue();
|
||||
offset.y= offsetNode->getAttribute("y")->getFloatValue();
|
||||
offset.z= offsetNode->getAttribute("z")->getFloatValue();
|
||||
|
||||
//color
|
||||
const XmlNode *colorNode= particleSystemNode->getChild("color");
|
||||
color.x= colorNode->getAttribute("red")->getFloatValue(0.f, 1.0f);
|
||||
color.y= colorNode->getAttribute("green")->getFloatValue(0.f, 1.0f);
|
||||
color.z= colorNode->getAttribute("blue")->getFloatValue(0.f, 1.0f);
|
||||
color.w= colorNode->getAttribute("alpha")->getFloatValue(0.f, 1.0f);
|
||||
|
||||
//color
|
||||
const XmlNode *colorNoEnergyNode= particleSystemNode->getChild("color-no-energy");
|
||||
colorNoEnergy.x= colorNoEnergyNode->getAttribute("red")->getFloatValue(0.f, 1.0f);
|
||||
colorNoEnergy.y= colorNoEnergyNode->getAttribute("green")->getFloatValue(0.f, 1.0f);
|
||||
colorNoEnergy.z= colorNoEnergyNode->getAttribute("blue")->getFloatValue(0.f, 1.0f);
|
||||
colorNoEnergy.w= colorNoEnergyNode->getAttribute("alpha")->getFloatValue(0.f, 1.0f);
|
||||
|
||||
//size
|
||||
const XmlNode *sizeNode= particleSystemNode->getChild("size");
|
||||
size= sizeNode->getAttribute("value")->getFloatValue();
|
||||
|
||||
//sizeNoEnergy
|
||||
const XmlNode *sizeNoEnergyNode= particleSystemNode->getChild("size-no-energy");
|
||||
sizeNoEnergy= sizeNoEnergyNode->getAttribute("value")->getFloatValue();
|
||||
|
||||
//speed
|
||||
const XmlNode *speedNode= particleSystemNode->getChild("speed");
|
||||
speed= speedNode->getAttribute("value")->getFloatValue()/GameConstants::updateFps;
|
||||
|
||||
//gravity
|
||||
const XmlNode *gravityNode= particleSystemNode->getChild("gravity");
|
||||
gravity= gravityNode->getAttribute("value")->getFloatValue()/GameConstants::updateFps;
|
||||
|
||||
//emission rate
|
||||
const XmlNode *emissionRateNode= particleSystemNode->getChild("emission-rate");
|
||||
emissionRate= emissionRateNode->getAttribute("value")->getIntValue();
|
||||
|
||||
//energy max
|
||||
const XmlNode *energyMaxNode= particleSystemNode->getChild("energy-max");
|
||||
energyMax= energyMaxNode->getAttribute("value")->getIntValue();
|
||||
|
||||
//speed
|
||||
const XmlNode *energyVarNode= particleSystemNode->getChild("energy-var");
|
||||
energyVar= energyVarNode->getAttribute("value")->getIntValue();
|
||||
}
|
||||
|
||||
void ParticleSystemType::setValues(AttackParticleSystem *ats){
|
||||
ats->setTexture(texture);
|
||||
ats->setPrimitive(AttackParticleSystem::strToPrimitive(primitive));
|
||||
ats->setOffset(offset);
|
||||
ats->setColor(color);
|
||||
ats->setColorNoEnergy(colorNoEnergy);
|
||||
ats->setSpeed(speed);
|
||||
ats->setGravity(gravity);
|
||||
ats->setParticleSize(size);
|
||||
ats->setSizeNoEnergy(sizeNoEnergy);
|
||||
ats->setEmissionRate(emissionRate);
|
||||
ats->setMaxParticleEnergy(energyMax);
|
||||
ats->setVarParticleEnergy(energyVar);
|
||||
ats->setModel(model);
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// class ParticleSystemTypeProjectile
|
||||
// ===========================================================
|
||||
|
||||
void ParticleSystemTypeProjectile::load(const string &dir, const string &path){
|
||||
|
||||
try{
|
||||
XmlTree xmlTree;
|
||||
xmlTree.load(path);
|
||||
const XmlNode *particleSystemNode= xmlTree.getRootNode();
|
||||
|
||||
ParticleSystemType::load(particleSystemNode, dir);
|
||||
|
||||
//trajectory values
|
||||
const XmlNode *tajectoryNode= particleSystemNode->getChild("trajectory");
|
||||
trajectory= tajectoryNode->getAttribute("type")->getRestrictedValue();
|
||||
|
||||
//trajectory speed
|
||||
const XmlNode *tajectorySpeedNode= tajectoryNode->getChild("speed");
|
||||
trajectorySpeed= tajectorySpeedNode->getAttribute("value")->getFloatValue()/GameConstants::updateFps;
|
||||
|
||||
if(trajectory=="parabolic" || trajectory=="spiral"){
|
||||
//trajectory scale
|
||||
const XmlNode *tajectoryScaleNode= tajectoryNode->getChild("scale");
|
||||
trajectoryScale= tajectoryScaleNode->getAttribute("value")->getFloatValue();
|
||||
}
|
||||
else{
|
||||
trajectoryScale= 1.0f;
|
||||
}
|
||||
|
||||
if(trajectory=="spiral"){
|
||||
//trajectory frequency
|
||||
const XmlNode *tajectoryFrequencyNode= tajectoryNode->getChild("frequency");
|
||||
trajectoryFrequency= tajectoryFrequencyNode->getAttribute("value")->getFloatValue();
|
||||
}
|
||||
else{
|
||||
trajectoryFrequency= 1.0f;
|
||||
}
|
||||
}
|
||||
catch(const exception &e){
|
||||
throw runtime_error("Error loading ParticleSystem: "+ path + "\n" +e.what());
|
||||
}
|
||||
}
|
||||
|
||||
ProjectileParticleSystem *ParticleSystemTypeProjectile::create(){
|
||||
ProjectileParticleSystem *ps= new ProjectileParticleSystem();
|
||||
|
||||
ParticleSystemType::setValues(ps);
|
||||
|
||||
ps->setTrajectory(ProjectileParticleSystem::strToTrajectory(trajectory));
|
||||
ps->setTrajectorySpeed(trajectorySpeed);
|
||||
ps->setTrajectoryScale(trajectoryScale);
|
||||
ps->setTrajectoryFrequency(trajectoryFrequency);
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// class ParticleSystemTypeSplash
|
||||
// ===========================================================
|
||||
|
||||
void ParticleSystemTypeSplash::load(const string &dir, const string &path){
|
||||
|
||||
try{
|
||||
XmlTree xmlTree;
|
||||
xmlTree.load(path);
|
||||
const XmlNode *particleSystemNode= xmlTree.getRootNode();
|
||||
|
||||
ParticleSystemType::load(particleSystemNode, dir);
|
||||
|
||||
//emission rate fade
|
||||
const XmlNode *emissionRateFadeNode= particleSystemNode->getChild("emission-rate-fade");
|
||||
emissionRateFade= emissionRateFadeNode->getAttribute("value")->getIntValue();
|
||||
|
||||
//spread values
|
||||
const XmlNode *verticalSpreadNode= particleSystemNode->getChild("vertical-spread");
|
||||
verticalSpreadA= verticalSpreadNode->getAttribute("a")->getFloatValue(0.0f, 1.0f);
|
||||
verticalSpreadB= verticalSpreadNode->getAttribute("b")->getFloatValue(-1.0f, 1.0f);
|
||||
|
||||
const XmlNode *horizontalSpreadNode= particleSystemNode->getChild("horizontal-spread");
|
||||
horizontalSpreadA= horizontalSpreadNode->getAttribute("a")->getFloatValue(0.0f, 1.0f);
|
||||
horizontalSpreadB= horizontalSpreadNode->getAttribute("b")->getFloatValue(-1.0f, 1.0f);
|
||||
}
|
||||
catch(const exception &e){
|
||||
throw runtime_error("Error loading ParticleSystem: "+ path + "\n" +e.what());
|
||||
}
|
||||
}
|
||||
|
||||
SplashParticleSystem *ParticleSystemTypeSplash::create(){
|
||||
SplashParticleSystem *ps= new SplashParticleSystem();
|
||||
|
||||
ParticleSystemType::setValues(ps);
|
||||
|
||||
ps->setEmissionRateFade(emissionRateFade);
|
||||
ps->setVerticalSpreadA(verticalSpreadA);
|
||||
ps->setVerticalSpreadB(verticalSpreadB);
|
||||
ps->setHorizontalSpreadA(horizontalSpreadA);
|
||||
ps->setHorizontalSpreadB(horizontalSpreadB);
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
}}//end mamespace
|
|
@ -0,0 +1,104 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_PARTICLETYPE_H_
|
||||
#define _GLEST_GAME_PARTICLETYPE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "particle.h"
|
||||
#include "factory.h"
|
||||
#include "texture.h"
|
||||
#include "vec.h"
|
||||
#include "xml_parser.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Graphics::ParticleSystem;
|
||||
using Shared::Graphics::AttackParticleSystem;
|
||||
using Shared::Graphics::ProjectileParticleSystem;
|
||||
using Shared::Graphics::SplashParticleSystem;
|
||||
using Shared::Graphics::Texture2D;
|
||||
using Shared::Graphics::Vec3f;
|
||||
using Shared::Graphics::Vec4f;
|
||||
using Shared::Graphics::Model;
|
||||
using Shared::Util::MultiFactory;
|
||||
using Shared::Xml::XmlNode;
|
||||
|
||||
// ===========================================================
|
||||
// class ParticleSystemType
|
||||
//
|
||||
/// A type of particle system
|
||||
// ===========================================================
|
||||
|
||||
class ParticleSystemType{
|
||||
protected:
|
||||
string type;
|
||||
Texture2D *texture;
|
||||
Model *model;
|
||||
string primitive;
|
||||
Vec3f offset;
|
||||
Vec4f color;
|
||||
Vec4f colorNoEnergy;
|
||||
float size;
|
||||
float sizeNoEnergy;
|
||||
float speed;
|
||||
float gravity;
|
||||
int emissionRate;
|
||||
int energyMax;
|
||||
int energyVar;
|
||||
|
||||
public:
|
||||
ParticleSystemType();
|
||||
void load(const XmlNode *particleSystemNode, const string &dir);
|
||||
|
||||
protected:
|
||||
void setValues(AttackParticleSystem *ats);
|
||||
};
|
||||
|
||||
// ===========================================================
|
||||
// class ParticleSystemTypeProjectile
|
||||
// ===========================================================
|
||||
|
||||
class ParticleSystemTypeProjectile: public ParticleSystemType{
|
||||
private:
|
||||
string trajectory;
|
||||
float trajectorySpeed;
|
||||
float trajectoryScale;
|
||||
float trajectoryFrequency;
|
||||
|
||||
public:
|
||||
void load(const string &dir, const string &path);
|
||||
ProjectileParticleSystem *create();
|
||||
};
|
||||
|
||||
// ===========================================================
|
||||
// class ParticleSystemTypeSplash
|
||||
// ===========================================================
|
||||
|
||||
class ParticleSystemTypeSplash: public ParticleSystemType{
|
||||
public:
|
||||
void load(const string &dir, const string &path);
|
||||
SplashParticleSystem *create();
|
||||
|
||||
private:
|
||||
int emissionRateFade;
|
||||
float verticalSpreadA;
|
||||
float verticalSpreadB;
|
||||
float horizontalSpreadA;
|
||||
float horizontalSpreadB;
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,307 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_RENDERER_H_
|
||||
#define _GLEST_GAME_RENDERER_H_
|
||||
|
||||
#include "vec.h"
|
||||
#include "math_util.h"
|
||||
#include "model.h"
|
||||
#include "particle.h"
|
||||
#include "pixmap.h"
|
||||
#include "font.h"
|
||||
#include "matrix.h"
|
||||
#include "selection.h"
|
||||
#include "components.h"
|
||||
#include "texture.h"
|
||||
#include "model_manager.h"
|
||||
#include "graphics_factory_gl.h"
|
||||
#include "font_manager.h"
|
||||
#include "camera.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Graphics::Texture2D;
|
||||
using Shared::Graphics::Texture3D;
|
||||
using Shared::Graphics::ModelRenderer;
|
||||
using Shared::Graphics::TextRenderer2D;
|
||||
using Shared::Graphics::ParticleRenderer;
|
||||
using Shared::Graphics::ParticleManager;
|
||||
using Shared::Graphics::ModelManager;
|
||||
using Shared::Graphics::TextureManager;
|
||||
using Shared::Graphics::FontManager;
|
||||
using Shared::Graphics::Font2D;
|
||||
using Shared::Graphics::Matrix4f;
|
||||
using Shared::Graphics::Vec2i;
|
||||
using Shared::Graphics::Quad2i;
|
||||
using Shared::Graphics::Vec3f;
|
||||
using Shared::Graphics::Model;
|
||||
using Shared::Graphics::ParticleSystem;
|
||||
using Shared::Graphics::Pixmap2D;
|
||||
using Shared::Graphics::Camera;
|
||||
|
||||
//non shared classes
|
||||
class Config;
|
||||
class Game;
|
||||
class MainMenu;
|
||||
class Console;
|
||||
class MenuBackground;
|
||||
class ChatManager;
|
||||
|
||||
enum ResourceScope{
|
||||
rsGlobal,
|
||||
rsMenu,
|
||||
rsGame,
|
||||
|
||||
rsCount
|
||||
};
|
||||
|
||||
// ===========================================================
|
||||
// class Renderer
|
||||
//
|
||||
/// OpenGL renderer, uses the shared library
|
||||
// ===========================================================
|
||||
|
||||
class Renderer{
|
||||
public:
|
||||
//progress bar
|
||||
static const int maxProgressBar;
|
||||
static const Vec4f progressBarBack1;
|
||||
static const Vec4f progressBarBack2;
|
||||
static const Vec4f progressBarFront1;
|
||||
static const Vec4f progressBarFront2;
|
||||
|
||||
//sun and moon
|
||||
static const float sunDist;
|
||||
static const float moonDist;
|
||||
static const float lightAmbFactor;
|
||||
|
||||
//mouse
|
||||
static const int maxMouse2dAnim;
|
||||
|
||||
//texture units
|
||||
static const GLenum baseTexUnit;
|
||||
static const GLenum fowTexUnit;
|
||||
static const GLenum shadowTexUnit;
|
||||
|
||||
//selection
|
||||
static const float selectionCircleRadius;
|
||||
static const float magicCircleRadius;
|
||||
|
||||
//perspective values
|
||||
static const float perspFov;
|
||||
static const float perspNearPlane;
|
||||
static const float perspFarPlane;
|
||||
|
||||
//default values
|
||||
static const float ambFactor;
|
||||
static const Vec4f defSpecularColor;
|
||||
static const Vec4f defDiffuseColor;
|
||||
static const Vec4f defAmbientColor;
|
||||
static const Vec4f defColor;
|
||||
static const Vec4f fowColor;
|
||||
|
||||
//light
|
||||
static const float maxLightDist;
|
||||
|
||||
public:
|
||||
enum Shadows{
|
||||
sDisabled,
|
||||
sProjected,
|
||||
sShadowMapping,
|
||||
|
||||
sCount
|
||||
};
|
||||
|
||||
private:
|
||||
//config
|
||||
int maxLights;
|
||||
bool photoMode;
|
||||
int shadowTextureSize;
|
||||
int shadowFrameSkip;
|
||||
float shadowAlpha;
|
||||
bool focusArrows;
|
||||
bool textures3D;
|
||||
Shadows shadows;
|
||||
|
||||
//game
|
||||
const Game *game;
|
||||
|
||||
//misc
|
||||
int triangleCount;
|
||||
int pointCount;
|
||||
Quad2i visibleQuad;
|
||||
Vec4f nearestLightPos;
|
||||
|
||||
//renderers
|
||||
ModelRenderer *modelRenderer;
|
||||
TextRenderer2D *textRenderer;
|
||||
ParticleRenderer *particleRenderer;
|
||||
|
||||
//texture managers
|
||||
ModelManager *modelManager[rsCount];
|
||||
TextureManager *textureManager[rsCount];
|
||||
FontManager *fontManager[rsCount];
|
||||
ParticleManager *particleManager[rsCount];
|
||||
|
||||
//state lists
|
||||
GLuint list3d;
|
||||
GLuint list2d;
|
||||
GLuint list3dMenu;
|
||||
|
||||
//shadows
|
||||
GLuint shadowMapHandle;
|
||||
Matrix4f shadowMapMatrix;
|
||||
int shadowMapFrame;
|
||||
|
||||
//water
|
||||
float waterAnim;
|
||||
|
||||
private:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
public:
|
||||
static Renderer &getInstance();
|
||||
|
||||
//init
|
||||
void init();
|
||||
void initGame(Game *game);
|
||||
void initMenu(MainMenu *mm);
|
||||
void reset3d();
|
||||
void reset2d();
|
||||
void reset3dMenu();
|
||||
|
||||
//end
|
||||
void end();
|
||||
void endMenu();
|
||||
void endGame();
|
||||
|
||||
//get
|
||||
int getTriangleCount() const {return triangleCount;}
|
||||
int getPointCount() const {return pointCount;}
|
||||
|
||||
//misc
|
||||
void reloadResources();
|
||||
|
||||
//engine interface
|
||||
Model *newModel(ResourceScope rs);
|
||||
Texture2D *newTexture2D(ResourceScope rs);
|
||||
Texture3D *newTexture3D(ResourceScope rs);
|
||||
Font2D *newFont(ResourceScope rs);
|
||||
TextRenderer2D *getTextRenderer() const {return textRenderer;}
|
||||
void manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs);
|
||||
void updateParticleManager(ResourceScope rs);
|
||||
void renderParticleManager(ResourceScope rs);
|
||||
void swapBuffers();
|
||||
|
||||
//lights and camera
|
||||
void setupLighting();
|
||||
void loadGameCameraMatrix();
|
||||
void loadCameraMatrix(const Camera *camera);
|
||||
void computeVisibleQuad();
|
||||
|
||||
//basic rendering
|
||||
void renderMouse2d(int mouseX, int mouseY, int anim, float fade= 0.f);
|
||||
void renderMouse3d();
|
||||
void renderBackground(const Texture2D *texture);
|
||||
void renderTextureQuad(int x, int y, int w, int h, const Texture2D *texture, float alpha=1.f);
|
||||
void renderConsole(const Console *console);
|
||||
void renderChatManager(const ChatManager *chatManager);
|
||||
void renderResourceStatus();
|
||||
void renderSelectionQuad();
|
||||
void renderText(const string &text, const Font2D *font, float alpha, int x, int y, bool centered= false);
|
||||
void renderText(const string &text, const Font2D *font, const Vec3f &color, int x, int y, bool centered= false);
|
||||
void renderTextShadow(const string &text, const Font2D *font, int x, int y, bool centered= false);
|
||||
|
||||
//components
|
||||
void renderLabel(const GraphicLabel *label);
|
||||
void renderButton(const GraphicButton *button);
|
||||
void renderListBox(const GraphicListBox *listBox);
|
||||
void renderMessageBox(const GraphicMessageBox *listBox);
|
||||
|
||||
//complex rendering
|
||||
void renderSurface();
|
||||
void renderObjects();
|
||||
void renderWater();
|
||||
void renderUnits();
|
||||
void renderSelectionEffects();
|
||||
void renderWaterEffects();
|
||||
void renderMinimap();
|
||||
void renderDisplay();
|
||||
void renderMenuBackground(const MenuBackground *menuBackground);
|
||||
|
||||
//computing
|
||||
bool computePosition(const Vec2i &screenPos, Vec2i &worldPos);
|
||||
void computeSelected(Selection::UnitContainer &units, const Vec2i &posDown, const Vec2i &posUp);
|
||||
|
||||
//gl wrap
|
||||
string getGlInfo();
|
||||
string getGlMoreInfo();
|
||||
void autoConfig();
|
||||
|
||||
//clear
|
||||
void clearBuffers();
|
||||
void clearZBuffer();
|
||||
|
||||
//shadows
|
||||
void renderShadowsToTexture();
|
||||
|
||||
//misc
|
||||
void loadConfig();
|
||||
void saveScreen(const string &path);
|
||||
Quad2i getVisibleQuad() const {return visibleQuad;}
|
||||
|
||||
//static
|
||||
static Shadows strToShadows(const string &s);
|
||||
static string shadowsToStr(Shadows shadows);
|
||||
|
||||
private:
|
||||
//private misc
|
||||
float computeSunAngle(float time);
|
||||
float computeMoonAngle(float time);
|
||||
Vec4f computeSunPos(float time);
|
||||
Vec4f computeMoonPos(float time);
|
||||
Vec3f computeLightColor(float time);
|
||||
Vec4f computeWaterColor(float waterLevel, float cellHeight);
|
||||
void checkExtension(const string &extension, const string &msg);
|
||||
|
||||
//selection render
|
||||
void renderObjectsFast();
|
||||
void renderUnitsFast();
|
||||
|
||||
//gl requirements
|
||||
void checkGlCaps();
|
||||
void checkGlOptionalCaps();
|
||||
|
||||
//gl init
|
||||
void init3dList();
|
||||
void init2dList();
|
||||
void init3dListMenu(MainMenu *mm);
|
||||
|
||||
//misc
|
||||
void loadProjectionMatrix();
|
||||
void enableProjectiveTexturing();
|
||||
|
||||
//private aux drawing
|
||||
void renderSelectionCircle(Vec3f v, int size, float radius);
|
||||
void renderArrow(const Vec3f &pos1, const Vec3f &pos2, const Vec3f &color, float width);
|
||||
void renderProgressBar(int size, int x, int y, Font2D *font);
|
||||
void renderTile(const Vec2i &pos);
|
||||
void renderQuad(int x, int y, int w, int h, const Texture2D *texture);
|
||||
|
||||
//static
|
||||
static Texture2D::Filter strToTextureFilter(const string &s);
|
||||
};
|
||||
|
||||
}} //end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,83 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "display.h"
|
||||
|
||||
#include "metrics.h"
|
||||
#include "command_type.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Graphics;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Display
|
||||
// =====================================================
|
||||
|
||||
Display::Display(){
|
||||
clear();
|
||||
}
|
||||
|
||||
//misc
|
||||
void Display::clear(){
|
||||
for(int i=0; i<upCellCount; ++i){
|
||||
upImages[i]= NULL;
|
||||
}
|
||||
|
||||
for(int i=0; i<downCellCount; ++i){
|
||||
downImages[i]= NULL;
|
||||
downLighted[i]= true;
|
||||
commandTypes[i]= NULL;
|
||||
commandClasses[i]= ccNull;
|
||||
}
|
||||
|
||||
downSelectedPos= invalidPos;
|
||||
title.clear();
|
||||
text.clear();
|
||||
progressBar= -1;
|
||||
}
|
||||
|
||||
int Display::computeDownIndex(int x, int y){
|
||||
y= y-(downY-cellSideCount*imageSize);
|
||||
|
||||
if(y>imageSize*cellSideCount){
|
||||
return invalidPos;
|
||||
}
|
||||
|
||||
int cellX= x/imageSize;
|
||||
int cellY= (y/imageSize) % cellSideCount;
|
||||
int index= (cellSideCount-cellY-1)*cellSideCount+cellX;;
|
||||
|
||||
if(index<0 || index>=downCellCount || downImages[index]==NULL){
|
||||
index= invalidPos;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
int Display::computeDownX(int index) const{
|
||||
return (index % cellSideCount) * imageSize;
|
||||
}
|
||||
|
||||
int Display::computeDownY(int index) const{
|
||||
return Display::downY - (index/cellSideCount)*imageSize - imageSize;
|
||||
}
|
||||
|
||||
int Display::computeUpX(int index) const{
|
||||
return (index % cellSideCount) * imageSize;
|
||||
}
|
||||
|
||||
int Display::computeUpY(int index) const{
|
||||
return Metrics::getInstance().getDisplayH() - (index/cellSideCount)*imageSize - imageSize;
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,96 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_DISPLAY_H_
|
||||
#define _GLEST_GAME_DISPLAY_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "texture.h"
|
||||
#include "util.h"
|
||||
#include "command_type.h"
|
||||
#include "game_util.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
using Shared::Graphics::Texture2D;
|
||||
using Shared::Graphics::Vec3f;
|
||||
using Shared::Util::replaceBy;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Display
|
||||
//
|
||||
/// Display for unit commands, and unit selection
|
||||
// =====================================================
|
||||
|
||||
class Display{
|
||||
public:
|
||||
static const int cellSideCount= 4;
|
||||
static const int upCellCount= cellSideCount*cellSideCount;
|
||||
static const int downCellCount= cellSideCount*cellSideCount;
|
||||
static const int imageSize= 32;
|
||||
static const int invalidPos= -1;
|
||||
static const int downY = imageSize*9;
|
||||
static const int infoStringY= imageSize*4;
|
||||
|
||||
private:
|
||||
string title;
|
||||
string text;
|
||||
string infoText;
|
||||
const Texture2D *upImages[upCellCount];
|
||||
const Texture2D *downImages[downCellCount];
|
||||
bool downLighted[downCellCount];
|
||||
const CommandType *commandTypes[downCellCount];
|
||||
CommandClass commandClasses[downCellCount];
|
||||
int progressBar;
|
||||
int downSelectedPos;
|
||||
|
||||
public:
|
||||
Display();
|
||||
|
||||
//get
|
||||
string getTitle() const {return title;}
|
||||
string getText() const {return text;}
|
||||
string getInfoText() const {return infoText;}
|
||||
const Texture2D *getUpImage(int index) const {return upImages[index];}
|
||||
const Texture2D *getDownImage(int index) const {return downImages[index];}
|
||||
bool getDownLighted(int index) const {return downLighted[index];}
|
||||
const CommandType *getCommandType(int i) {return commandTypes[i];}
|
||||
CommandClass getCommandClass(int i) {return commandClasses[i];}
|
||||
int getProgressBar() const {return progressBar;}
|
||||
int getDownSelectedPos() const {return downSelectedPos;}
|
||||
|
||||
//set
|
||||
void setTitle(const string title) {this->title= formatString(title);}
|
||||
void setText(const string &text) {this->text= formatString(text);}
|
||||
void setInfoText(const string infoText) {this->infoText= formatString(infoText);}
|
||||
void setUpImage(int i, const Texture2D *image) {upImages[i]= image;}
|
||||
void setDownImage(int i, const Texture2D *image) {downImages[i]= image;}
|
||||
void setCommandType(int i, const CommandType *ct) {commandTypes[i]= ct;}
|
||||
void setCommandClass(int i, const CommandClass cc) {commandClasses[i]= cc;}
|
||||
void setDownLighted(int i, bool lighted) {downLighted[i]= lighted;}
|
||||
void setProgressBar(int i) {progressBar= i;}
|
||||
void setDownSelectedPos(int i) {downSelectedPos= i;}
|
||||
|
||||
//misc
|
||||
void clear();
|
||||
int computeDownIndex(int x, int y);
|
||||
int computeDownX(int index) const;
|
||||
int computeDownY(int index) const;
|
||||
int computeUpX(int index) const;
|
||||
int computeUpY(int index) const;
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,849 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "gui.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#include "world.h"
|
||||
#include "renderer.h"
|
||||
#include "game.h"
|
||||
#include "upgrade.h"
|
||||
#include "unit.h"
|
||||
#include "metrics.h"
|
||||
#include "display.h"
|
||||
#include "platform_util.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "util.h"
|
||||
#include "faction.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Mouse3d
|
||||
// =====================================================
|
||||
|
||||
const float Mouse3d::fadeSpeed= 1.f/50.f;
|
||||
|
||||
Mouse3d::Mouse3d(){
|
||||
enabled= false;
|
||||
rot= 0;
|
||||
fade= 0.f;
|
||||
}
|
||||
|
||||
void Mouse3d::enable(){
|
||||
enabled= true;
|
||||
fade= 0.f;
|
||||
}
|
||||
|
||||
void Mouse3d::update(){
|
||||
if(enabled){
|
||||
rot= (rot + 3) % 360;
|
||||
fade+= fadeSpeed;
|
||||
if(fade>1.f) fade= 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// class SelectionQuad
|
||||
// ===============================
|
||||
|
||||
SelectionQuad::SelectionQuad(){
|
||||
enabled= false;
|
||||
posDown= Vec2i(0);
|
||||
posUp= Vec2i(0);
|
||||
}
|
||||
|
||||
void SelectionQuad::setPosDown(const Vec2i &posDown){
|
||||
enabled= true;
|
||||
this->posDown= posDown;
|
||||
this->posUp= posDown;
|
||||
}
|
||||
|
||||
void SelectionQuad::setPosUp(const Vec2i &posUp){
|
||||
this->posUp= posUp;
|
||||
}
|
||||
|
||||
void SelectionQuad::disable(){
|
||||
enabled= false;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Gui
|
||||
// =====================================================
|
||||
|
||||
//constructor
|
||||
Gui::Gui(){
|
||||
posObjWorld= Vec2i(54, 14);
|
||||
computeSelection= false;
|
||||
validPosObjWorld= false;
|
||||
activeCommandType= NULL;
|
||||
activeCommandClass= ccStop;
|
||||
selectingBuilding= false;
|
||||
selectingPos= false;
|
||||
selectingMeetingPoint= false;
|
||||
activePos= invalidPos;
|
||||
}
|
||||
|
||||
void Gui::init(Game *game){
|
||||
this->commander= game->getCommander();
|
||||
this->gameCamera= game->getGameCamera();
|
||||
this->console= game->getConsole();
|
||||
this->world= game->getWorld();
|
||||
selection.init(this, world->getThisFactionIndex());
|
||||
}
|
||||
|
||||
void Gui::end(){
|
||||
selection.clear();
|
||||
}
|
||||
|
||||
// ==================== get ====================
|
||||
|
||||
const UnitType *Gui::getBuilding() const{
|
||||
assert(selectingBuilding);
|
||||
return choosenBuildingType;
|
||||
}
|
||||
|
||||
// ==================== is ====================
|
||||
|
||||
bool Gui::isPlacingBuilding() const{
|
||||
return isSelectingPos() && activeCommandType!=NULL && activeCommandType->getClass()==ccBuild;
|
||||
}
|
||||
|
||||
// ==================== set ====================
|
||||
|
||||
void Gui::invalidatePosObjWorld(){
|
||||
validPosObjWorld= false;
|
||||
}
|
||||
|
||||
void Gui::setComputeSelectionFlag(){
|
||||
computeSelection= true;
|
||||
}
|
||||
|
||||
|
||||
// ==================== reset state ====================
|
||||
|
||||
void Gui::resetState(){
|
||||
selectingBuilding= false;
|
||||
selectingPos= false;
|
||||
selectingMeetingPoint= false;
|
||||
activePos= invalidPos;
|
||||
activeCommandClass= ccStop;
|
||||
activeCommandType= NULL;
|
||||
}
|
||||
|
||||
// ==================== events ====================
|
||||
|
||||
void Gui::update(){
|
||||
setComputeSelectionFlag();
|
||||
mouse3d.update();
|
||||
}
|
||||
|
||||
void Gui::tick(){
|
||||
computeDisplay();
|
||||
}
|
||||
|
||||
//in display coords
|
||||
bool Gui::mouseValid(int x, int y){
|
||||
return computePosDisplay(x, y) != invalidPos;
|
||||
}
|
||||
|
||||
void Gui::mouseDownLeftDisplay(int x, int y){
|
||||
if(!selectingPos && !selectingMeetingPoint){
|
||||
int posDisplay= computePosDisplay(x, y);
|
||||
if(posDisplay!= invalidPos){
|
||||
if(selection.isComandable()){
|
||||
if(selectingBuilding){
|
||||
mouseDownDisplayUnitBuild(posDisplay);
|
||||
}
|
||||
else{
|
||||
mouseDownDisplayUnitSkills(posDisplay);
|
||||
}
|
||||
}
|
||||
else{
|
||||
resetState();
|
||||
}
|
||||
}
|
||||
computeDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::mouseMoveDisplay(int x, int y){
|
||||
computeInfoString(computePosDisplay(x, y));
|
||||
}
|
||||
|
||||
void Gui::mouseDownLeftGraphics(int x, int y){
|
||||
if(selectingPos){
|
||||
//give standard orders
|
||||
giveTwoClickOrders(x, y);
|
||||
resetState();
|
||||
}
|
||||
//set meeting point
|
||||
else if(selectingMeetingPoint){
|
||||
if(selection.isComandable()){
|
||||
Vec2i targetPos;
|
||||
if(Renderer::getInstance().computePosition(Vec2i(x, y), targetPos)){
|
||||
commander->trySetMeetingPoint(selection.getFrontUnit(), targetPos);
|
||||
}
|
||||
}
|
||||
resetState();
|
||||
}
|
||||
else{
|
||||
selectionQuad.setPosDown(Vec2i(x, y));
|
||||
computeSelected(false);
|
||||
}
|
||||
computeDisplay();
|
||||
}
|
||||
|
||||
void Gui::mouseDownRightGraphics(int x, int y){
|
||||
|
||||
if(selectingPos || selectingMeetingPoint){
|
||||
resetState();
|
||||
}
|
||||
else if(selection.isComandable()){
|
||||
giveDefaultOrders(x, y);
|
||||
}
|
||||
computeDisplay();
|
||||
}
|
||||
|
||||
void Gui::mouseUpLeftGraphics(int x, int y){
|
||||
if(!selectingPos && !selectingMeetingPoint){
|
||||
if(selectionQuad.isEnabled()){
|
||||
selectionQuad.setPosUp(Vec2i(x, y));
|
||||
if(selection.isComandable() && random.randRange(0, 1)==0){
|
||||
SoundRenderer::getInstance().playFx(
|
||||
selection.getFrontUnit()->getType()->getSelectionSound(),
|
||||
selection.getFrontUnit()->getCurrVector(),
|
||||
gameCamera->getPos());
|
||||
}
|
||||
selectionQuad.disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::mouseMoveGraphics(int x, int y){
|
||||
|
||||
//compute selection
|
||||
if(selectionQuad.isEnabled()){
|
||||
selectionQuad.setPosUp(Vec2i(x, y));
|
||||
if(computeSelection){
|
||||
computeSelection= false;
|
||||
computeSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
//compute position for building
|
||||
if(isPlacingBuilding()){
|
||||
validPosObjWorld= Renderer::getInstance().computePosition(Vec2i(x,y), posObjWorld);
|
||||
}
|
||||
|
||||
display.setInfoText("");
|
||||
}
|
||||
|
||||
void Gui::mouseDoubleClickLeftGraphics(int x, int y){
|
||||
if(!selectingPos && !selectingMeetingPoint){
|
||||
selectionQuad.setPosDown(Vec2i(x, y));
|
||||
computeSelected(true);
|
||||
computeDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::groupKey(int groupIndex){
|
||||
if(isKeyDown(vkControl)){
|
||||
selection.assignGroup(groupIndex);
|
||||
}
|
||||
else{
|
||||
selection.recallGroup(groupIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::hotKey(char key){
|
||||
if(key==' '){
|
||||
centerCameraOnSelection();
|
||||
}
|
||||
else if(key=='I'){
|
||||
selectInterestingUnit(iutIdleHarvester);
|
||||
}
|
||||
else if(key=='B'){
|
||||
selectInterestingUnit(iutBuiltBuilding);
|
||||
}
|
||||
else if(key=='R'){
|
||||
selectInterestingUnit(iutProducer);
|
||||
}
|
||||
else if(key=='D'){
|
||||
selectInterestingUnit(iutDamaged);
|
||||
}
|
||||
else if(key=='T'){
|
||||
selectInterestingUnit(iutStore);
|
||||
}
|
||||
else if(key=='A'){
|
||||
clickCommonCommand(ccAttack);
|
||||
}
|
||||
else if(key=='S'){
|
||||
clickCommonCommand(ccStop);
|
||||
}
|
||||
else if(key=='M'){
|
||||
clickCommonCommand(ccMove);
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::onSelectionChanged(){
|
||||
resetState();
|
||||
computeDisplay();
|
||||
}
|
||||
|
||||
// ================= PRIVATE =================
|
||||
|
||||
void Gui::giveOneClickOrders(){
|
||||
CommandResult result;
|
||||
if(selection.isUniform()){
|
||||
result= commander->tryGiveCommand(&selection, activeCommandType);
|
||||
}
|
||||
else{
|
||||
result= commander->tryGiveCommand(&selection, activeCommandClass);
|
||||
}
|
||||
addOrdersResultToConsole(activeCommandClass, result);
|
||||
activeCommandType= NULL;
|
||||
activeCommandClass= ccStop;
|
||||
}
|
||||
|
||||
void Gui::giveDefaultOrders(int x, int y){
|
||||
|
||||
//compute target
|
||||
const Unit *targetUnit= NULL;
|
||||
Vec2i targetPos;
|
||||
if(!computeTarget(Vec2i(x, y), targetPos, targetUnit)){
|
||||
console->addStdMessage("InvalidPosition");
|
||||
return;
|
||||
}
|
||||
|
||||
//give order
|
||||
CommandResult result= commander->tryGiveCommand(&selection, targetPos, targetUnit);
|
||||
|
||||
//graphical result
|
||||
addOrdersResultToConsole(activeCommandClass, result);
|
||||
if(result == crSuccess || result == crSomeFailed){
|
||||
mouse3d.enable();
|
||||
|
||||
if(random.randRange(0, 1)==0){
|
||||
SoundRenderer::getInstance().playFx(
|
||||
selection.getFrontUnit()->getType()->getCommandSound(),
|
||||
selection.getFrontUnit()->getCurrVector(),
|
||||
gameCamera->getPos());
|
||||
}
|
||||
}
|
||||
|
||||
//reset
|
||||
resetState();
|
||||
}
|
||||
|
||||
void Gui::giveTwoClickOrders(int x, int y){
|
||||
|
||||
CommandResult result;
|
||||
|
||||
//compute target
|
||||
const Unit *targetUnit= NULL;
|
||||
Vec2i targetPos;
|
||||
if(!computeTarget(Vec2i(x, y), targetPos, targetUnit)){
|
||||
console->addStdMessage("InvalidPosition");
|
||||
return;
|
||||
}
|
||||
|
||||
//give orders to the units of this faction
|
||||
if(!selectingBuilding){
|
||||
if(selection.isUniform()){
|
||||
result= commander->tryGiveCommand(&selection, activeCommandType, targetPos, targetUnit);
|
||||
}
|
||||
else{
|
||||
result= commander->tryGiveCommand(&selection, activeCommandClass, targetPos, targetUnit);
|
||||
}
|
||||
}
|
||||
else{
|
||||
//selecting building
|
||||
result= commander->tryGiveCommand( selection.getFrontUnit(), activeCommandType, posObjWorld, choosenBuildingType );
|
||||
}
|
||||
|
||||
//graphical result
|
||||
addOrdersResultToConsole(activeCommandClass, result);
|
||||
if(result == crSuccess || result == crSomeFailed){
|
||||
mouse3d.enable();
|
||||
|
||||
if(random.randRange(0, 1)==0){
|
||||
SoundRenderer::getInstance().playFx(
|
||||
selection.getFrontUnit()->getType()->getCommandSound(),
|
||||
selection.getFrontUnit()->getCurrVector(),
|
||||
gameCamera->getPos());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::centerCameraOnSelection(){
|
||||
if(!selection.isEmpty()){
|
||||
Vec3f refPos= selection.getRefPos();
|
||||
gameCamera->centerXZ(refPos.x, refPos.z);
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::selectInterestingUnit(InterestingUnitType iut){
|
||||
const Faction* thisFaction= world->getThisFaction();
|
||||
const Unit* previousUnit= NULL;
|
||||
bool previousFound= true;
|
||||
|
||||
//start at the next harvester
|
||||
if(selection.getCount()==1){
|
||||
const Unit* refUnit= selection.getFrontUnit();
|
||||
|
||||
if(refUnit->isInteresting(iut)){
|
||||
previousUnit= refUnit;
|
||||
previousFound= false;
|
||||
}
|
||||
}
|
||||
|
||||
//clear selection
|
||||
selection.clear();
|
||||
|
||||
//search
|
||||
for(int i= 0; i<thisFaction->getUnitCount(); ++i){
|
||||
Unit* unit= thisFaction->getUnit(i);
|
||||
|
||||
if(previousFound){
|
||||
if(unit->isInteresting(iut)){
|
||||
selection.select(unit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(unit==previousUnit){
|
||||
previousFound= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//search again if we have a previous
|
||||
if(selection.isEmpty() && previousUnit!=NULL && previousFound==true){
|
||||
for(int i= 0; i<thisFaction->getUnitCount(); ++i){
|
||||
Unit* unit= thisFaction->getUnit(i);
|
||||
|
||||
if(unit->isInteresting(iut)){
|
||||
selection.select(unit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::clickCommonCommand(CommandClass commandClass){
|
||||
for(int i= 0; i<Display::downCellCount; ++i){
|
||||
const CommandType* ct= display.getCommandType(i);
|
||||
if((ct!=NULL && ct->getClass()==commandClass) || display.getCommandClass(i)==commandClass){
|
||||
mouseDownDisplayUnitSkills(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::mouseDownDisplayUnitSkills(int posDisplay){
|
||||
if(!selection.isEmpty()){
|
||||
if(posDisplay != cancelPos){
|
||||
if(posDisplay!=meetingPointPos){
|
||||
const Unit *unit= selection.getFrontUnit();
|
||||
|
||||
//uniform selection
|
||||
if(selection.isUniform()){
|
||||
if(unit->getFaction()->reqsOk(display.getCommandType(posDisplay))){
|
||||
activeCommandType= display.getCommandType(posDisplay);
|
||||
activeCommandClass= activeCommandType->getClass();
|
||||
}
|
||||
else{
|
||||
posDisplay= invalidPos;
|
||||
activeCommandType= NULL;
|
||||
activeCommandClass= ccStop;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//non uniform selection
|
||||
else{
|
||||
activeCommandType= NULL;
|
||||
activeCommandClass= display.getCommandClass(posDisplay);
|
||||
}
|
||||
|
||||
//give orders depending on command type
|
||||
if(!selection.isEmpty()){
|
||||
const CommandType *ct= selection.getUnit(0)->getType()->getFirstCtOfClass(activeCommandClass);
|
||||
if(activeCommandType!=NULL && activeCommandType->getClass()==ccBuild){
|
||||
assert(selection.isUniform());
|
||||
selectingBuilding= true;
|
||||
}
|
||||
else if(ct->getClicks()==cOne){
|
||||
invalidatePosObjWorld();
|
||||
giveOneClickOrders();
|
||||
}
|
||||
else{
|
||||
selectingPos= true;
|
||||
activePos= posDisplay;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
activePos= posDisplay;
|
||||
selectingMeetingPoint= true;
|
||||
}
|
||||
}
|
||||
else{
|
||||
commander->tryCancelCommand(&selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::mouseDownDisplayUnitBuild(int posDisplay){
|
||||
int factionIndex= world->getThisFactionIndex();
|
||||
|
||||
if(posDisplay==cancelPos){
|
||||
resetState();
|
||||
}
|
||||
else{
|
||||
if(activeCommandType!=NULL && activeCommandType->getClass()==ccBuild){
|
||||
const BuildCommandType *bct= static_cast<const BuildCommandType*>(activeCommandType);
|
||||
const UnitType *ut= bct->getBuilding(posDisplay);
|
||||
if(world->getFaction(factionIndex)->reqsOk(ut)){
|
||||
choosenBuildingType= ut;
|
||||
assert(choosenBuildingType!=NULL);
|
||||
selectingPos= true;;
|
||||
activePos= posDisplay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::computeInfoString(int posDisplay){
|
||||
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
display.setInfoText("");
|
||||
if(posDisplay!=invalidPos && selection.isComandable()){
|
||||
if(!selectingBuilding){
|
||||
if(posDisplay==cancelPos){
|
||||
display.setInfoText(lang.get("Cancel"));
|
||||
}
|
||||
else if(posDisplay==meetingPointPos){
|
||||
display.setInfoText(lang.get("MeetingPoint"));
|
||||
}
|
||||
else{
|
||||
//uniform selection
|
||||
if(selection.isUniform()){
|
||||
const Unit *unit= selection.getFrontUnit();
|
||||
const CommandType *ct= display.getCommandType(posDisplay);
|
||||
if(ct!=NULL){
|
||||
if(unit->getFaction()->reqsOk(ct)){
|
||||
display.setInfoText(ct->getDesc(unit->getTotalUpgrade()));
|
||||
}
|
||||
else{
|
||||
if(ct->getClass()==ccUpgrade){
|
||||
const UpgradeCommandType *uct= static_cast<const UpgradeCommandType*>(ct);
|
||||
if(unit->getFaction()->getUpgradeManager()->isUpgrading(uct->getProducedUpgrade())){
|
||||
display.setInfoText(lang.get("Upgrading"));
|
||||
}
|
||||
else if(unit->getFaction()->getUpgradeManager()->isUpgraded(uct->getProducedUpgrade())){
|
||||
display.setInfoText(lang.get("AlreadyUpgraded"));
|
||||
}
|
||||
else{
|
||||
display.setInfoText(ct->getReqDesc());
|
||||
}
|
||||
}
|
||||
else{
|
||||
display.setInfoText(ct->getReqDesc());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//non uniform selection
|
||||
else{
|
||||
const UnitType *ut= selection.getFrontUnit()->getType();
|
||||
CommandClass cc= display.getCommandClass(posDisplay);
|
||||
if(cc!=ccNull){
|
||||
display.setInfoText(lang.get("CommonCommand") + ": " + ut->getFirstCtOfClass(cc)->toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(posDisplay==cancelPos){
|
||||
display.setInfoText(lang.get("Return"));
|
||||
}
|
||||
else{
|
||||
if(activeCommandType!=NULL && activeCommandType->getClass()==ccBuild){
|
||||
const BuildCommandType *bct= static_cast<const BuildCommandType*>(activeCommandType);
|
||||
display.setInfoText(bct->getBuilding(posDisplay)->getReqDesc());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::computeDisplay(){
|
||||
|
||||
//init
|
||||
display.clear();
|
||||
|
||||
// ================ PART 1 ================
|
||||
|
||||
//title, text and progress bar
|
||||
if(selection.getCount()==1){
|
||||
display.setTitle(selection.getFrontUnit()->getFullName());
|
||||
display.setText(selection.getFrontUnit()->getDesc());
|
||||
display.setProgressBar(selection.getFrontUnit()->getProductionPercent());
|
||||
}
|
||||
|
||||
//portraits
|
||||
for(int i=0; i<selection.getCount(); ++i){
|
||||
display.setUpImage(i, selection.getUnit(i)->getType()->getImage());
|
||||
}
|
||||
|
||||
// ================ PART 2 ================
|
||||
|
||||
if(selectingPos || selectingMeetingPoint){
|
||||
display.setDownSelectedPos(activePos);
|
||||
}
|
||||
|
||||
if(selection.isComandable()){
|
||||
if(!selectingBuilding){
|
||||
|
||||
//cancel button
|
||||
const Unit *u= selection.getFrontUnit();
|
||||
const UnitType *ut= u->getType();
|
||||
if(selection.isCancelable()){
|
||||
display.setDownImage(cancelPos, ut->getCancelImage());
|
||||
display.setDownLighted(cancelPos, true);
|
||||
}
|
||||
|
||||
//meeting point
|
||||
if(selection.isMeetable()){
|
||||
display.setDownImage(meetingPointPos, ut->getMeetingPointImage());
|
||||
display.setDownLighted(meetingPointPos, true);
|
||||
}
|
||||
|
||||
if(selection.isUniform()){
|
||||
//uniform selection
|
||||
if(u->isBuilt()){
|
||||
int morphPos= 8;
|
||||
for(int i=0; i<ut->getCommandTypeCount(); ++i){
|
||||
int displayPos= i;
|
||||
const CommandType *ct= ut->getCommandType(i);
|
||||
if(ct->getClass()==ccMorph){
|
||||
displayPos= morphPos++;
|
||||
}
|
||||
display.setDownImage(displayPos, ct->getImage());
|
||||
display.setCommandType(displayPos, ct);
|
||||
display.setDownLighted(displayPos, u->getFaction()->reqsOk(ct));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else{
|
||||
//non uniform selection
|
||||
int lastCommand= 0;
|
||||
for(int i=0; i<ccCount; ++i){
|
||||
CommandClass cc= static_cast<CommandClass>(i);
|
||||
if(isSharedCommandClass(cc) && cc!=ccBuild){
|
||||
display.setDownLighted(lastCommand, true);
|
||||
display.setDownImage(lastCommand, ut->getFirstCtOfClass(cc)->getImage());
|
||||
display.setCommandClass(lastCommand, cc);
|
||||
lastCommand++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
//selecting building
|
||||
const Unit *unit= selection.getFrontUnit();
|
||||
if(activeCommandType!=NULL && activeCommandType->getClass()==ccBuild){
|
||||
const BuildCommandType* bct= static_cast<const BuildCommandType*>(activeCommandType);
|
||||
for(int i=0; i<bct->getBuildingCount(); ++i){
|
||||
display.setDownImage(i, bct->getBuilding(i)->getImage());
|
||||
display.setDownLighted(i, unit->getFaction()->reqsOk(bct->getBuilding(i)));
|
||||
}
|
||||
display.setDownImage(cancelPos, selection.getFrontUnit()->getType()->getCancelImage());
|
||||
display.setDownLighted(cancelPos, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Gui::computePosDisplay(int x, int y){
|
||||
int posDisplay= display.computeDownIndex(x, y);
|
||||
|
||||
if(posDisplay<0 || posDisplay>=Display::downCellCount){
|
||||
posDisplay= invalidPos;
|
||||
}
|
||||
else if(selection.isComandable()){
|
||||
if(posDisplay!=cancelPos){
|
||||
if(posDisplay!=meetingPointPos){
|
||||
if(!selectingBuilding){
|
||||
//standard selection
|
||||
if(display.getCommandClass(posDisplay)==ccNull && display.getCommandType(posDisplay)==NULL){
|
||||
posDisplay= invalidPos;
|
||||
}
|
||||
}
|
||||
else{
|
||||
//building selection
|
||||
if(activeCommandType!=NULL && activeCommandType->getClass()==ccBuild){
|
||||
const BuildCommandType *bct= static_cast<const BuildCommandType*>(activeCommandType);
|
||||
if(posDisplay>=bct->getBuildingCount()){
|
||||
posDisplay= invalidPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
//check meeting point
|
||||
if(!selection.isMeetable()){
|
||||
posDisplay= invalidPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
//check cancel button
|
||||
if(!selection.isCancelable()){
|
||||
posDisplay= invalidPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
posDisplay= invalidPos;
|
||||
}
|
||||
|
||||
return posDisplay;
|
||||
}
|
||||
|
||||
void Gui::addOrdersResultToConsole(CommandClass cc, CommandResult result){
|
||||
|
||||
switch(result){
|
||||
case crSuccess:
|
||||
break;
|
||||
case crFailReqs:
|
||||
switch(cc){
|
||||
case ccBuild:
|
||||
console->addStdMessage("BuildingNoReqs");
|
||||
break;
|
||||
case ccProduce:
|
||||
console->addStdMessage("UnitNoReqs");
|
||||
break;
|
||||
case ccUpgrade:
|
||||
console->addStdMessage("UpgradeNoReqs");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case crFailRes:
|
||||
switch(cc){
|
||||
case ccBuild:
|
||||
console->addStdMessage("BuildingNoRes");
|
||||
break;
|
||||
case ccProduce:
|
||||
console->addStdMessage("UnitNoRes");
|
||||
break;
|
||||
case ccUpgrade:
|
||||
console->addStdMessage("UpgradeNoRes");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case crFailUndefined:
|
||||
console->addStdMessage("InvalidOrder");
|
||||
break;
|
||||
|
||||
case crSomeFailed:
|
||||
console->addStdMessage("SomeOrdersFailed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Gui::isSharedCommandClass(CommandClass commandClass){
|
||||
for(int i=0; i<selection.getCount(); ++i){
|
||||
const Unit *unit= selection.getUnit(i);
|
||||
const CommandType *ct= unit->getType()->getFirstCtOfClass(commandClass);
|
||||
if(ct==NULL || !unit->getFaction()->reqsOk(ct))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Gui::computeSelected(bool doubleClick){
|
||||
Selection::UnitContainer units;
|
||||
Renderer::getInstance().computeSelected(units, selectionQuad.getPosDown(), selectionQuad.getPosUp());
|
||||
selectingBuilding= false;
|
||||
activeCommandType= NULL;
|
||||
|
||||
//select all units of the same type if double click
|
||||
if(doubleClick && units.size()==1){
|
||||
const Unit *refUnit= units.front();
|
||||
int factionIndex= refUnit->getFactionIndex();
|
||||
for(int i=0; i<world->getFaction(factionIndex)->getUnitCount(); ++i){
|
||||
Unit *unit= world->getFaction(factionIndex)->getUnit(i);
|
||||
if(unit->getPos().dist(refUnit->getPos())<doubleClickSelectionRadius &&
|
||||
unit->getType()==refUnit->getType())
|
||||
{
|
||||
units.push_back(unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool shiftDown= isKeyDown(vkShift);
|
||||
bool controlDown= isKeyDown(vkControl);
|
||||
|
||||
if(!shiftDown && !controlDown){
|
||||
selection.clear();
|
||||
}
|
||||
|
||||
if(!controlDown){
|
||||
selection.select(units);
|
||||
}
|
||||
else{
|
||||
selection.unSelect(units);
|
||||
}
|
||||
}
|
||||
|
||||
bool Gui::computeTarget(const Vec2i &screenPos, Vec2i &targetPos, const Unit *&targetUnit){
|
||||
Selection::UnitContainer uc;
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
renderer.computeSelected(uc, screenPos, screenPos);
|
||||
validPosObjWorld= false;
|
||||
|
||||
if(!uc.empty()){
|
||||
targetUnit= uc.front();
|
||||
targetPos= targetUnit->getPos();
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
targetUnit= NULL;
|
||||
if(renderer.computePosition(screenPos, targetPos)){
|
||||
validPosObjWorld= true;
|
||||
posObjWorld= targetPos;
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,201 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_GUI_H_
|
||||
#define _GLEST_GAME_GUI_H_
|
||||
|
||||
#include "resource.h"
|
||||
#include "command_type.h"
|
||||
#include "display.h"
|
||||
#include "commander.h"
|
||||
#include "console.h"
|
||||
#include "selection.h"
|
||||
#include "random.h"
|
||||
|
||||
using Shared::Util::Random;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class Unit;
|
||||
class World;
|
||||
class CommandType;
|
||||
class GameCamera;
|
||||
class Game;
|
||||
|
||||
enum DisplayState{
|
||||
dsEmpty,
|
||||
dsUnitSkills,
|
||||
dsUnitBuild,
|
||||
dsEnemy
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class Mouse3d
|
||||
// =====================================================
|
||||
|
||||
class Mouse3d{
|
||||
public:
|
||||
static const float fadeSpeed;
|
||||
|
||||
private:
|
||||
bool enabled;
|
||||
int rot;
|
||||
float fade;
|
||||
|
||||
public:
|
||||
Mouse3d();
|
||||
|
||||
void enable();
|
||||
void update();
|
||||
|
||||
bool isEnabled() const {return enabled;}
|
||||
float getFade() const {return fade;}
|
||||
int getRot() const {return rot;}
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class SelectionQuad
|
||||
// =====================================================
|
||||
|
||||
class SelectionQuad{
|
||||
private:
|
||||
Vec2i posDown;
|
||||
Vec2i posUp;
|
||||
bool enabled;
|
||||
|
||||
public:
|
||||
SelectionQuad();
|
||||
|
||||
bool isEnabled() const {return enabled;}
|
||||
Vec2i getPosDown() const {return posDown;}
|
||||
Vec2i getPosUp() const {return posUp;}
|
||||
|
||||
void setPosDown(const Vec2i &posDown);
|
||||
void setPosUp(const Vec2i &posUp);
|
||||
void disable();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class Gui
|
||||
//
|
||||
/// In game GUI
|
||||
// =====================================================
|
||||
|
||||
class Gui{
|
||||
public:
|
||||
static const int maxSelBuff= 128*5;
|
||||
static const int upgradeDisplayIndex= 8;
|
||||
static const int cancelPos= 15;
|
||||
static const int meetingPointPos= 14;
|
||||
static const int imageCount= 16;
|
||||
static const int invalidPos= -1;
|
||||
static const int doubleClickSelectionRadius= 20;
|
||||
|
||||
private:
|
||||
//External objects
|
||||
Random random;
|
||||
const Commander *commander;
|
||||
const World *world;
|
||||
GameCamera *gameCamera;
|
||||
Console *console;
|
||||
|
||||
//Positions
|
||||
Vec2i posObjWorld; //world coords
|
||||
bool validPosObjWorld;
|
||||
bool computeSelection;
|
||||
|
||||
//display
|
||||
const UnitType *choosenBuildingType;
|
||||
const CommandType *activeCommandType;
|
||||
CommandClass activeCommandClass;
|
||||
int activePos;
|
||||
|
||||
//composite
|
||||
Display display;
|
||||
Mouse3d mouse3d;
|
||||
Selection selection;
|
||||
SelectionQuad selectionQuad;
|
||||
|
||||
//states
|
||||
bool selectingBuilding;
|
||||
bool selectingPos;
|
||||
bool selectingMeetingPoint;
|
||||
|
||||
public:
|
||||
Gui();
|
||||
void init(Game *game);
|
||||
void end();
|
||||
|
||||
//get
|
||||
Vec2i getPosObjWorld() const {return posObjWorld;}
|
||||
const UnitType *getBuilding() const;
|
||||
|
||||
const Mouse3d *getMouse3d() const {return &mouse3d;}
|
||||
const Display *getDisplay() const {return &display;}
|
||||
const Selection *getSelection() const {return &selection;}
|
||||
const SelectionQuad *getSelectionQuad() const {return &selectionQuad;}
|
||||
bool isSelected(const Unit *unit) const {return selection.hasUnit(unit);}
|
||||
|
||||
bool isValidPosObjWorld() const {return validPosObjWorld;}
|
||||
bool isSelecting() const {return selectionQuad.isEnabled();}
|
||||
bool isSelectingPos() const {return selectingPos;}
|
||||
bool isSelectingBuilding() const {return selectingBuilding;}
|
||||
bool isPlacingBuilding() const;
|
||||
|
||||
//set
|
||||
void invalidatePosObjWorld();
|
||||
void setComputeSelectionFlag();
|
||||
|
||||
//events
|
||||
void update();
|
||||
void tick();
|
||||
bool mouseValid(int x, int y);
|
||||
void mouseDownLeftDisplay(int x, int y);
|
||||
void mouseMoveDisplay(int x, int y);
|
||||
void mouseDownLeftGraphics(int x, int y);
|
||||
void mouseDownRightGraphics(int x, int y);
|
||||
void mouseUpLeftGraphics(int x, int y);
|
||||
void mouseMoveGraphics(int x, int y);
|
||||
void mouseDoubleClickLeftGraphics(int x, int y);
|
||||
void groupKey(int groupIndex);
|
||||
void hotKey(char key);
|
||||
|
||||
//misc
|
||||
void onSelectionChanged();
|
||||
|
||||
private:
|
||||
|
||||
//orders
|
||||
void giveDefaultOrders(int x, int y);
|
||||
void giveOneClickOrders();
|
||||
void giveTwoClickOrders(int x, int y);
|
||||
|
||||
//hotkeys
|
||||
void centerCameraOnSelection();
|
||||
void selectInterestingUnit(InterestingUnitType iut);
|
||||
void clickCommonCommand(CommandClass commandClass);
|
||||
|
||||
//misc
|
||||
int computePosDisplay(int x, int y);
|
||||
void computeDisplay();
|
||||
void resetState();
|
||||
void mouseDownDisplayUnitSkills(int posDisplay);
|
||||
void mouseDownDisplayUnitBuild(int posDisplay);
|
||||
void computeInfoString(int posDisplay);
|
||||
void addOrdersResultToConsole(CommandClass cc, CommandResult rr);
|
||||
bool isSharedCommandClass(CommandClass commandClass);
|
||||
void computeSelected(bool doubleCkick);
|
||||
bool computeTarget(const Vec2i &screenPos, Vec2i &targetPos, const Unit *&targetUnit);
|
||||
};
|
||||
|
||||
}} //end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,204 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "selection.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "unit_type.h"
|
||||
#include "gui.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Selection
|
||||
// =====================================================
|
||||
|
||||
void Selection::init(Gui *gui, int factionIndex){
|
||||
this->factionIndex= factionIndex;
|
||||
this->gui= gui;
|
||||
}
|
||||
|
||||
Selection::~Selection(){
|
||||
clear();
|
||||
}
|
||||
|
||||
void Selection::select(Unit *unit){
|
||||
|
||||
//check size
|
||||
if(selectedUnits.size()>=maxUnits){
|
||||
return;
|
||||
}
|
||||
|
||||
//check if already selected
|
||||
for(int i=0; i<selectedUnits.size(); ++i){
|
||||
if(selectedUnits[i]==unit){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//check if dead
|
||||
if(unit->isDead()){
|
||||
return;
|
||||
}
|
||||
|
||||
//check if multisel
|
||||
if(!unit->getType()->getMultiSelect() && !isEmpty()){
|
||||
return;
|
||||
}
|
||||
|
||||
//check if enemy
|
||||
if(unit->getFactionIndex()!=factionIndex && !isEmpty()){
|
||||
return;
|
||||
}
|
||||
|
||||
//check existing enemy
|
||||
if(selectedUnits.size()==1 && selectedUnits.front()->getFactionIndex()!=factionIndex){
|
||||
clear();
|
||||
}
|
||||
|
||||
//check existing multisel
|
||||
if(selectedUnits.size()==1 && !selectedUnits.front()->getType()->getMultiSelect()){
|
||||
clear();
|
||||
}
|
||||
|
||||
unit->addObserver(this);
|
||||
selectedUnits.push_back(unit);
|
||||
gui->onSelectionChanged();
|
||||
}
|
||||
|
||||
void Selection::select(const UnitContainer &units){
|
||||
|
||||
//add units to gui
|
||||
for(UnitIterator it= units.begin(); it!=units.end(); ++it){
|
||||
select(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::unSelect(const UnitContainer &units){
|
||||
|
||||
//add units to gui
|
||||
for(UnitIterator it= units.begin(); it!=units.end(); ++it){
|
||||
for(int i=0; i<selectedUnits.size(); ++i){
|
||||
if(selectedUnits[i]==*it){
|
||||
unSelect(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::unSelect(int i){
|
||||
//remove unit from list
|
||||
selectedUnits.erase(selectedUnits.begin()+i);
|
||||
gui->onSelectionChanged();
|
||||
}
|
||||
|
||||
void Selection::clear(){
|
||||
//clear list
|
||||
selectedUnits.clear();
|
||||
}
|
||||
|
||||
bool Selection::isUniform() const{
|
||||
if(selectedUnits.empty()){
|
||||
return true;
|
||||
}
|
||||
|
||||
const UnitType *ut= selectedUnits.front()->getType();
|
||||
|
||||
for(int i=0; i<selectedUnits.size(); ++i){
|
||||
if(selectedUnits[i]->getType()!=ut){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Selection::isEnemy() const{
|
||||
return selectedUnits.size()==1 && selectedUnits.front()->getFactionIndex()!=factionIndex;
|
||||
}
|
||||
|
||||
bool Selection::isComandable() const{
|
||||
return
|
||||
!isEmpty() &&
|
||||
!isEnemy() &&
|
||||
!(selectedUnits.size()==1 && !selectedUnits.front()->isOperative());
|
||||
}
|
||||
|
||||
bool Selection::isCancelable() const{
|
||||
return
|
||||
selectedUnits.size()>1 ||
|
||||
(selectedUnits.size()==1 && selectedUnits[0]->anyCommand());
|
||||
}
|
||||
|
||||
bool Selection::isMeetable() const{
|
||||
return
|
||||
isUniform() &&
|
||||
isComandable() &&
|
||||
selectedUnits.front()->getType()->getMeetingPoint();
|
||||
}
|
||||
|
||||
Vec3f Selection::getRefPos() const{
|
||||
return getFrontUnit()->getCurrVector();
|
||||
}
|
||||
|
||||
bool Selection::hasUnit(const Unit* unit) const{
|
||||
return find(selectedUnits.begin(), selectedUnits.end(), unit)!=selectedUnits.end();
|
||||
}
|
||||
|
||||
void Selection::assignGroup(int groupIndex){
|
||||
//clear group
|
||||
groups[groupIndex].clear();
|
||||
|
||||
//assign new group
|
||||
for(int i=0; i<selectedUnits.size(); ++i){
|
||||
groups[groupIndex].push_back(selectedUnits[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::recallGroup(int groupIndex){
|
||||
clear();
|
||||
for(int i=0; i<groups[groupIndex].size(); ++i){
|
||||
select(groups[groupIndex][i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::unitEvent(UnitObserver::Event event, const Unit *unit){
|
||||
|
||||
if(event==UnitObserver::eKill){
|
||||
|
||||
//remove from selection
|
||||
for(int i=0; i<selectedUnits.size(); ++i){
|
||||
if(selectedUnits[i]==unit){
|
||||
selectedUnits.erase(selectedUnits.begin()+i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//remove from groups
|
||||
for(int i=0; i<maxGroups; ++i){
|
||||
for(int j=0; j<groups[i].size(); ++j){
|
||||
if(groups[i][j]==unit){
|
||||
groups[i].erase(groups[i].begin()+j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//notify gui
|
||||
gui->onSelectionChanged();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,76 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_SELECTION_
|
||||
#define _GLEST_GAME_SELECTION_
|
||||
|
||||
#include "unit.h"
|
||||
#include <vector>
|
||||
|
||||
using std::vector;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class Gui;
|
||||
|
||||
// =====================================================
|
||||
// class Selection
|
||||
//
|
||||
/// List of selected units and groups
|
||||
// =====================================================
|
||||
|
||||
class Selection: public UnitObserver{
|
||||
public:
|
||||
typedef vector<Unit*> UnitContainer;
|
||||
typedef UnitContainer::const_iterator UnitIterator;
|
||||
|
||||
public:
|
||||
static const int maxGroups= 10;
|
||||
static const int maxUnits= 16;
|
||||
|
||||
private:
|
||||
int factionIndex;
|
||||
UnitContainer selectedUnits;
|
||||
UnitContainer groups[maxGroups];
|
||||
Gui *gui;
|
||||
|
||||
public:
|
||||
void init(Gui *gui, int factionIndex);
|
||||
virtual ~Selection();
|
||||
|
||||
void select(Unit *unit);
|
||||
void select(const UnitContainer &units);
|
||||
void unSelect(int unitIndex);
|
||||
void unSelect(const UnitContainer &units);
|
||||
void clear();
|
||||
|
||||
bool isEmpty() const {return selectedUnits.empty();}
|
||||
bool isUniform() const;
|
||||
bool isEnemy() const;
|
||||
bool isComandable() const;
|
||||
bool isCancelable() const;
|
||||
bool isMeetable() const;
|
||||
int getCount() const {return selectedUnits.size();}
|
||||
const Unit *getUnit(int i) const {return selectedUnits[i];}
|
||||
const Unit *getFrontUnit() const {return selectedUnits.front();}
|
||||
Vec3f getRefPos() const;
|
||||
bool hasUnit(const Unit* unit) const;
|
||||
|
||||
void assignGroup(int groupIndex);
|
||||
void recallGroup(int groupIndex);
|
||||
|
||||
|
||||
virtual void unitEvent(UnitObserver::Event event, const Unit *unit);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,150 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "battle_end.h"
|
||||
|
||||
#include "main_menu.h"
|
||||
#include "program.h"
|
||||
#include "core_data.h"
|
||||
#include "lang.h"
|
||||
#include "util.h"
|
||||
#include "renderer.h"
|
||||
#include "main_menu.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "components.h"
|
||||
#include "metrics.h"
|
||||
#include "stats.h"
|
||||
#include "auto_test.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class BattleEnd
|
||||
// =====================================================
|
||||
|
||||
BattleEnd::BattleEnd(Program *program, const Stats *stats):
|
||||
ProgramState(program){
|
||||
this->stats= *stats;
|
||||
}
|
||||
|
||||
BattleEnd::~BattleEnd(){
|
||||
SoundRenderer::getInstance().playMusic(CoreData::getInstance().getMenuMusic());
|
||||
}
|
||||
|
||||
void BattleEnd::update(){
|
||||
if(Config::getInstance().getBool("AutoTest")){
|
||||
AutoTest::getInstance().updateBattleEnd(program);
|
||||
}
|
||||
}
|
||||
|
||||
void BattleEnd::render(){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
TextRenderer2D *textRenderer= renderer.getTextRenderer();
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
renderer.clearBuffers();
|
||||
renderer.reset2d();
|
||||
renderer.renderBackground(CoreData::getInstance().getBackgroundTexture());
|
||||
|
||||
textRenderer->begin(CoreData::getInstance().getMenuFontBig());
|
||||
|
||||
int lm= 80;
|
||||
int bm= 100;
|
||||
|
||||
for(int i=0; i<stats.getFactionCount(); ++i){
|
||||
|
||||
int textX= lm+300+i*120;
|
||||
int team= stats.getTeam(i) + 1;
|
||||
int kills= stats.getKills(i);
|
||||
int deaths= stats.getDeaths(i);
|
||||
int unitsProduced= stats.getUnitsProduced(i);
|
||||
int resourcesHarvested= stats.getResourcesHarvested(i);
|
||||
|
||||
int score= kills*100 + unitsProduced*50 + resourcesHarvested/10;
|
||||
string controlString;
|
||||
|
||||
switch(stats.getControl(i)){
|
||||
case ctCpuEasy:
|
||||
controlString= lang.get("CpuEasy");
|
||||
break;
|
||||
case ctCpu:
|
||||
controlString= lang.get("Cpu");
|
||||
break;
|
||||
case ctCpuUltra:
|
||||
controlString= lang.get("CpuUltra");
|
||||
break;
|
||||
case ctCpuMega:
|
||||
controlString= lang.get("CpuMega");
|
||||
break;
|
||||
case ctNetwork:
|
||||
controlString= lang.get("Network");
|
||||
break;
|
||||
case ctHuman:
|
||||
controlString= lang.get("Human");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
};
|
||||
|
||||
textRenderer->render((lang.get("Player")+" "+intToStr(i+1)).c_str(), textX, bm+400);
|
||||
textRenderer->render(stats.getVictory(i)? lang.get("Victory").c_str(): lang.get("Defeat").c_str(), textX, bm+360);
|
||||
textRenderer->render(controlString, textX, bm+320);
|
||||
textRenderer->render(stats.getFactionTypeName(i), textX, bm+280);
|
||||
textRenderer->render(intToStr(team).c_str(), textX, bm+240);
|
||||
textRenderer->render(intToStr(kills).c_str(), textX, bm+200);
|
||||
textRenderer->render(intToStr(deaths).c_str(), textX, bm+160);
|
||||
textRenderer->render(intToStr(unitsProduced).c_str(), textX, bm+120);
|
||||
textRenderer->render(intToStr(resourcesHarvested).c_str(), textX, bm+80);
|
||||
textRenderer->render(intToStr(score).c_str(), textX, bm+20);
|
||||
}
|
||||
|
||||
textRenderer->render(lang.get("Result"), lm+50, bm+360);
|
||||
textRenderer->render(lang.get("Control"), lm+50, bm+320);
|
||||
textRenderer->render(lang.get("Faction"), lm+50, bm+280);
|
||||
textRenderer->render(lang.get("Team"), lm+50, bm+240);
|
||||
textRenderer->render(lang.get("Kills"), lm+50, bm+200);
|
||||
textRenderer->render(lang.get("Deaths"), lm+50, bm+160);
|
||||
textRenderer->render(lang.get("UnitsProduced"), lm+50, bm+120);
|
||||
textRenderer->render(lang.get("ResourcesHarvested"), lm+50, bm+80);
|
||||
textRenderer->render(lang.get("Score"), lm+50, bm+20);
|
||||
|
||||
textRenderer->end();
|
||||
|
||||
textRenderer->begin(CoreData::getInstance().getMenuFontVeryBig());
|
||||
|
||||
string header = stats.getDescription() + " - ";
|
||||
|
||||
if(stats.getVictory(stats.getThisFactionIndex())){
|
||||
header += lang.get("Victory");
|
||||
}
|
||||
else{
|
||||
header += lang.get("Defeat");
|
||||
}
|
||||
|
||||
textRenderer->render(header, lm+250, bm+550);
|
||||
|
||||
textRenderer->end();
|
||||
renderer.swapBuffers();
|
||||
}
|
||||
|
||||
void BattleEnd::keyDown(char key){
|
||||
program->setState(new MainMenu(program));
|
||||
}
|
||||
|
||||
void BattleEnd::mouseDownLeft(int x, int y){
|
||||
program->setState(new MainMenu(program));
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,41 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_BATTLEEND_H_
|
||||
#define _GLEST_GAME_BATTLEEND_H_
|
||||
|
||||
#include "program.h"
|
||||
#include "stats.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class BattleEnd
|
||||
//
|
||||
/// ProgramState representing the end of the game
|
||||
// =====================================================
|
||||
|
||||
class BattleEnd: public ProgramState{
|
||||
private:
|
||||
Stats stats;
|
||||
|
||||
public:
|
||||
BattleEnd(Program *program, const Stats *stats);
|
||||
~BattleEnd();
|
||||
virtual void update();
|
||||
virtual void render();
|
||||
virtual void keyDown(char key);
|
||||
virtual void mouseDownLeft(int x, int y);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,133 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
#include "intro.h"
|
||||
|
||||
#include "main_menu.h"
|
||||
#include "util.h"
|
||||
#include "game_util.h"
|
||||
#include "config.h"
|
||||
#include "program.h"
|
||||
#include "renderer.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "metrics.h"
|
||||
#include "auto_test.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Graphics;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Text
|
||||
// =====================================================
|
||||
|
||||
Text::Text(const string &text, const Vec2i &pos, int time, const Font2D *font){
|
||||
this->text= text;
|
||||
this->pos= pos;
|
||||
this->time= time;
|
||||
this->texture= NULL;
|
||||
this->font= font;
|
||||
}
|
||||
|
||||
Text::Text(const Texture2D *texture, const Vec2i &pos, const Vec2i &size, int time){
|
||||
this->pos= pos;
|
||||
this->size= size;
|
||||
this->time= time;
|
||||
this->texture= texture;
|
||||
this->font= NULL;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Intro
|
||||
// =====================================================
|
||||
|
||||
const int Intro::introTime= 24000;
|
||||
const int Intro::appearTime= 2500;
|
||||
const int Intro::showTime= 2500;
|
||||
const int Intro::disapearTime= 2500;
|
||||
|
||||
Intro::Intro(Program *program):
|
||||
ProgramState(program)
|
||||
{
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
int w= metrics.getVirtualW();
|
||||
int h= metrics.getVirtualH();
|
||||
timer=0;
|
||||
|
||||
texts.push_back(Text(coreData.getLogoTexture(), Vec2i(w/2-128, h/2-64), Vec2i(256, 128), 4000));
|
||||
texts.push_back(Text(glestVersionString, Vec2i(w/2+64, h/2-32), 4000, coreData.getMenuFontNormal()));
|
||||
texts.push_back(Text("www.glest.org", Vec2i(w/2, h/2), 12000, coreData.getMenuFontVeryBig()));
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
soundRenderer.playMusic(CoreData::getInstance().getIntroMusic());
|
||||
}
|
||||
|
||||
void Intro::update(){
|
||||
timer++;
|
||||
if(timer>introTime*GameConstants::updateFps/1000){
|
||||
program->setState(new MainMenu(program));
|
||||
}
|
||||
|
||||
if(Config::getInstance().getBool("AutoTest")){
|
||||
AutoTest::getInstance().updateIntro(program);
|
||||
}
|
||||
}
|
||||
|
||||
void Intro::render(){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
int difTime;
|
||||
|
||||
renderer.reset2d();
|
||||
renderer.clearBuffers();
|
||||
for(int i=0; i<texts.size(); ++i){
|
||||
Text *text= &texts[i];
|
||||
|
||||
difTime= 1000*timer/GameConstants::updateFps-text->getTime();
|
||||
|
||||
if(difTime>0 && difTime<appearTime+showTime+disapearTime){
|
||||
float alpha= 1.f;
|
||||
if(difTime>0 && difTime<appearTime){
|
||||
//apearing
|
||||
alpha= static_cast<float>(difTime)/appearTime;
|
||||
}
|
||||
else if(difTime>0 && difTime<appearTime+showTime+disapearTime){
|
||||
//disappearing
|
||||
alpha= 1.f- static_cast<float>(difTime-appearTime-showTime)/disapearTime;
|
||||
}
|
||||
if(!text->getText().empty()){
|
||||
renderer.renderText(
|
||||
text->getText(), text->getFont(), alpha,
|
||||
text->getPos().x, text->getPos().y, true);
|
||||
}
|
||||
if(text->getTexture()!=NULL){
|
||||
renderer.renderTextureQuad(
|
||||
text->getPos().x, text->getPos().y,
|
||||
text->getSize().x, text->getSize().y,
|
||||
text->getTexture(), alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
renderer.swapBuffers();
|
||||
}
|
||||
|
||||
void Intro::keyDown(char key){
|
||||
mouseUpLeft(0, 0);
|
||||
}
|
||||
|
||||
void Intro::mouseUpLeft(int x, int y){
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
soundRenderer.stopMusic(CoreData::getInstance().getIntroMusic());
|
||||
soundRenderer.playMusic(CoreData::getInstance().getMenuMusic());
|
||||
program->setState(new MainMenu(program));
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,84 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_INTRO_H_
|
||||
#define _GLEST_GAME_INTRO_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "program.h"
|
||||
#include "font.h"
|
||||
#include "vec.h"
|
||||
#include "texture.h"
|
||||
|
||||
using std::vector;
|
||||
|
||||
using Shared::Graphics::Vec2i;
|
||||
using Shared::Graphics::Vec2f;
|
||||
using Shared::Graphics::Vec3f;
|
||||
using Shared::Graphics::Font2D;
|
||||
using Shared::Graphics::Texture2D;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Text
|
||||
// =====================================================
|
||||
|
||||
class Text{
|
||||
private:
|
||||
string text;
|
||||
Vec2i pos;
|
||||
Vec2i size;
|
||||
int time;
|
||||
const Font2D *font;
|
||||
const Texture2D *texture;
|
||||
|
||||
public:
|
||||
Text(const string &text, const Vec2i &pos, int time, const Font2D *font);
|
||||
Text(const Texture2D *texture, const Vec2i &pos, const Vec2i &size, int time);
|
||||
|
||||
const string &getText() const {return text;}
|
||||
const Font2D *getFont() const {return font;}
|
||||
const Vec2i &getPos() const {return pos;}
|
||||
const Vec2i &getSize() const {return size;}
|
||||
int getTime() const {return time;}
|
||||
const Texture2D *getTexture() const {return texture;}
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class Intro
|
||||
//
|
||||
/// ProgramState representing the intro
|
||||
// =====================================================
|
||||
|
||||
class Intro: public ProgramState{
|
||||
private:
|
||||
static const int introTime;
|
||||
static const int appearTime;
|
||||
static const int showTime;
|
||||
static const int disapearTime;
|
||||
|
||||
private:
|
||||
vector<Text> texts;
|
||||
int timer;
|
||||
|
||||
public:
|
||||
Intro(Program *program);
|
||||
virtual void update();
|
||||
virtual void render();
|
||||
virtual void keyDown(char key);
|
||||
virtual void mouseUpLeft(int x, int y);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,159 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "game.h"
|
||||
#include "main_menu.h"
|
||||
#include "program.h"
|
||||
#include "config.h"
|
||||
#include "metrics.h"
|
||||
#include "game_util.h"
|
||||
#include "platform_util.h"
|
||||
#include "platform_main.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class ExceptionHandler
|
||||
// =====================================================
|
||||
|
||||
class ExceptionHandler: public PlatformExceptionHandler{
|
||||
public:
|
||||
virtual void handle(){
|
||||
message("An error ocurred and Glest will close.\nPlease report this bug to "+mailString+", attaching the generated "+getCrashDumpFileName()+" file.");
|
||||
}
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class MainWindow
|
||||
// =====================================================
|
||||
|
||||
MainWindow::MainWindow(Program *program){
|
||||
this->program= program;
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow(){
|
||||
delete program;
|
||||
}
|
||||
|
||||
void MainWindow::eventMouseDown(int x, int y, MouseButton mouseButton){
|
||||
switch(mouseButton){
|
||||
case mbLeft:
|
||||
program->mouseDownLeft(x, getH() - y);
|
||||
break;
|
||||
case mbRight:
|
||||
program->mouseDownRight(x, getH() - y);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::eventMouseUp(int x, int y, MouseButton mouseButton){
|
||||
if(mouseButton==mbLeft){
|
||||
program->mouseUpLeft(x, getH() - y);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::eventMouseDoubleClick(int x, int y, MouseButton mouseButton){
|
||||
if(mouseButton == mbLeft){
|
||||
program->mouseDoubleClickLeft(x, getH() - y);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::eventMouseMove(int x, int y, const MouseState *ms){
|
||||
program->mouseMove(x, getH() - y, ms);
|
||||
}
|
||||
|
||||
void MainWindow::eventKeyDown(char key){
|
||||
program->keyDown(key);
|
||||
}
|
||||
|
||||
void MainWindow::eventKeyUp(char key){
|
||||
program->keyUp(key);
|
||||
}
|
||||
|
||||
void MainWindow::eventKeyPress(char c){
|
||||
program->keyPress(c);
|
||||
}
|
||||
|
||||
void MainWindow::eventActivate(bool active){
|
||||
if(!active){
|
||||
//minimize();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::eventResize(SizeState sizeState){
|
||||
program->resize(sizeState);
|
||||
}
|
||||
|
||||
void MainWindow::eventClose(){
|
||||
delete program;
|
||||
program= NULL;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// Main
|
||||
// =====================================================
|
||||
|
||||
int glestMain(int argc, char** argv){
|
||||
|
||||
MainWindow *mainWindow= NULL;
|
||||
Program *program= NULL;
|
||||
ExceptionHandler exceptionHandler;
|
||||
exceptionHandler.install( getCrashDumpFileName() );
|
||||
|
||||
try{
|
||||
Config &config = Config::getInstance();
|
||||
|
||||
showCursor(config.getBool("Windowed"));
|
||||
|
||||
program= new Program();
|
||||
mainWindow= new MainWindow(program);
|
||||
|
||||
//parse command line
|
||||
if(argc==2 && string(argv[1])=="-server"){
|
||||
program->initServer(mainWindow);
|
||||
}
|
||||
else if(argc==3 && string(argv[1])=="-client"){
|
||||
program->initClient(mainWindow, Ip(argv[2]));
|
||||
}
|
||||
else{
|
||||
program->initNormal(mainWindow);
|
||||
}
|
||||
|
||||
//main loop
|
||||
while(Window::handleEvent()){
|
||||
program->loop();
|
||||
}
|
||||
}
|
||||
catch(const exception &e){
|
||||
restoreVideoMode();
|
||||
exceptionMessage(e);
|
||||
}
|
||||
|
||||
delete mainWindow;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}}//end namespace
|
||||
|
||||
MAIN_FUNCTION(Glest::Game::glestMain)
|
|
@ -0,0 +1,55 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MAIN_H_
|
||||
#define _GLEST_GAME_MAIN_H_
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "program.h"
|
||||
#include "window_gl.h"
|
||||
|
||||
using Shared::Platform::MouseButton;
|
||||
using Shared::Platform::MouseState;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class MainWindow
|
||||
//
|
||||
/// Main program window
|
||||
// =====================================================
|
||||
|
||||
class MainWindow: public WindowGl{
|
||||
private:
|
||||
Program* program;
|
||||
|
||||
public:
|
||||
MainWindow(Program *program);
|
||||
~MainWindow();
|
||||
|
||||
void setProgram(Program *program) {this->program= program;}
|
||||
|
||||
virtual void eventMouseDown(int x, int y, MouseButton mouseButton);
|
||||
virtual void eventMouseUp(int x, int y, MouseButton mouseButton);
|
||||
virtual void eventMouseDoubleClick(int x, int y, MouseButton mouseButton);
|
||||
virtual void eventMouseMove(int x, int y, const MouseState *mouseState);
|
||||
virtual void eventKeyDown(char key);
|
||||
virtual void eventKeyUp(char key);
|
||||
virtual void eventKeyPress(char c);
|
||||
virtual void eventActivate(bool active);
|
||||
virtual void eventResize(SizeState sizeState);
|
||||
virtual void eventClose();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,255 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "program.h"
|
||||
|
||||
#include "sound.h"
|
||||
#include "renderer.h"
|
||||
#include "config.h"
|
||||
#include "game.h"
|
||||
#include "main_menu.h"
|
||||
#include "intro.h"
|
||||
#include "world.h"
|
||||
#include "main.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "logger.h"
|
||||
#include "profiler.h"
|
||||
#include "core_data.h"
|
||||
#include "metrics.h"
|
||||
#include "network_manager.h"
|
||||
#include "menu_state_custom_game.h"
|
||||
#include "menu_state_join_game.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Graphics::Gl;
|
||||
|
||||
// =====================================================
|
||||
// class Program
|
||||
// =====================================================
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
const int Program::maxTimes= 10;
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
Program::Program(){
|
||||
programState= NULL;
|
||||
}
|
||||
|
||||
void Program::initNormal(WindowGl *window){
|
||||
init(window);
|
||||
setState(new Intro(this));
|
||||
}
|
||||
|
||||
void Program::initServer(WindowGl *window){
|
||||
MainMenu* mainMenu= NULL;
|
||||
|
||||
init(window);
|
||||
mainMenu= new MainMenu(this);
|
||||
setState(mainMenu);
|
||||
mainMenu->setState(new MenuStateCustomGame(this, mainMenu, true));
|
||||
}
|
||||
|
||||
void Program::initClient(WindowGl *window, const Ip &serverIp){
|
||||
MainMenu* mainMenu= NULL;
|
||||
|
||||
init(window);
|
||||
mainMenu= new MainMenu(this);
|
||||
setState(mainMenu);
|
||||
mainMenu->setState(new MenuStateJoinGame(this, mainMenu, true, serverIp));
|
||||
}
|
||||
|
||||
Program::~Program(){
|
||||
delete programState;
|
||||
|
||||
Renderer::getInstance().end();
|
||||
|
||||
//restore video mode
|
||||
restoreDisplaySettings();
|
||||
}
|
||||
|
||||
void Program::mouseDownLeft(int x, int y){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
programState->mouseDownLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
|
||||
}
|
||||
|
||||
void Program::mouseUpLeft(int x, int y){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
programState->mouseUpLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
|
||||
}
|
||||
|
||||
void Program::mouseDownRight(int x, int y){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
programState->mouseDownRight(metrics.toVirtualX(x), metrics.toVirtualY(y));
|
||||
}
|
||||
|
||||
void Program::mouseDoubleClickLeft(int x, int y){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
programState->mouseDoubleClickLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
|
||||
}
|
||||
|
||||
void Program::mouseMove(int x, int y, const MouseState *ms){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
programState->mouseMove(metrics.toVirtualX(x), metrics.toVirtualY(y), ms);
|
||||
}
|
||||
|
||||
void Program::keyDown(char key){
|
||||
//delegate event
|
||||
programState->keyDown(key);
|
||||
}
|
||||
|
||||
void Program::keyUp(char key){
|
||||
programState->keyUp(key);
|
||||
}
|
||||
|
||||
void Program::keyPress(char c){
|
||||
programState->keyPress(c);
|
||||
}
|
||||
|
||||
void Program::loop(){
|
||||
|
||||
//render
|
||||
programState->render();
|
||||
|
||||
//update camera
|
||||
while(updateCameraTimer.isTime()){
|
||||
programState->updateCamera();
|
||||
}
|
||||
|
||||
//update world
|
||||
while(updateTimer.isTime()){
|
||||
GraphicComponent::update();
|
||||
programState->update();
|
||||
SoundRenderer::getInstance().update();
|
||||
NetworkManager::getInstance().update();
|
||||
}
|
||||
|
||||
//fps timer
|
||||
while(fpsTimer.isTime()){
|
||||
programState->tick();
|
||||
}
|
||||
}
|
||||
|
||||
void Program::resize(SizeState sizeState){
|
||||
|
||||
switch(sizeState){
|
||||
case ssMinimized:
|
||||
//restoreVideoMode();
|
||||
break;
|
||||
case ssMaximized:
|
||||
case ssRestored:
|
||||
//setDisplaySettings();
|
||||
//renderer.reloadResources();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== misc ====================
|
||||
|
||||
void Program::setState(ProgramState *programState){
|
||||
|
||||
delete this->programState;
|
||||
|
||||
this->programState= programState;
|
||||
programState->load();
|
||||
programState->init();
|
||||
|
||||
updateTimer.reset();
|
||||
updateCameraTimer.reset();
|
||||
fpsTimer.reset();
|
||||
}
|
||||
|
||||
void Program::exit(){
|
||||
window->destroy();
|
||||
}
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
void Program::init(WindowGl *window){
|
||||
|
||||
this->window= window;
|
||||
Config &config= Config::getInstance();
|
||||
|
||||
//set video mode
|
||||
setDisplaySettings();
|
||||
|
||||
//window
|
||||
window->setText("Glest");
|
||||
window->setStyle(config.getBool("Windowed")? wsWindowedFixed: wsFullscreen);
|
||||
window->setPos(0, 0);
|
||||
window->setSize(config.getInt("ScreenWidth"), config.getInt("ScreenHeight"));
|
||||
window->create();
|
||||
|
||||
//timers
|
||||
fpsTimer.init(1, maxTimes);
|
||||
updateTimer.init(GameConstants::updateFps, maxTimes);
|
||||
updateCameraTimer.init(GameConstants::cameraFps, maxTimes);
|
||||
|
||||
//log start
|
||||
Logger &logger= Logger::getInstance();
|
||||
logger.setFile("glest.log");
|
||||
logger.clear();
|
||||
|
||||
//lang
|
||||
Lang &lang= Lang::getInstance();
|
||||
lang.loadStrings(config.getString("Lang"));
|
||||
|
||||
//render
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
window->initGl(config.getInt("ColorBits"), config.getInt("DepthBits"), config.getInt("StencilBits"));
|
||||
window->makeCurrentGl();
|
||||
|
||||
//coreData, needs renderer, but must load before renderer init
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
coreData.load();
|
||||
|
||||
//init renderer (load global textures)
|
||||
renderer.init();
|
||||
|
||||
//sound
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
soundRenderer.init(window);
|
||||
}
|
||||
|
||||
void Program::setDisplaySettings(){
|
||||
|
||||
Config &config= Config::getInstance();
|
||||
|
||||
if(!config.getBool("Windowed")){
|
||||
|
||||
int freq= config.getInt("RefreshFrequency");
|
||||
int colorBits= config.getInt("ColorBits");
|
||||
int screenWidth= config.getInt("ScreenWidth");
|
||||
int screenHeight= config.getInt("ScreenHeight");
|
||||
|
||||
if(!(changeVideoMode(screenWidth, screenHeight, colorBits, freq) ||
|
||||
changeVideoMode(screenWidth, screenHeight, colorBits, 0)))
|
||||
{
|
||||
throw runtime_error(
|
||||
"Error setting video mode: " +
|
||||
intToStr(screenWidth) + "x" + intToStr(screenHeight) + "x" + intToStr(colorBits));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Program::restoreDisplaySettings(){
|
||||
Config &config= Config::getInstance();
|
||||
|
||||
if(!config.getBool("Windowed")){
|
||||
restoreVideoMode();
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,113 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_PROGRAM_H_
|
||||
#define _GLEST_GAME_PROGRAM_H_
|
||||
|
||||
#include "context.h"
|
||||
#include "platform_util.h"
|
||||
#include "window_gl.h"
|
||||
#include "socket.h"
|
||||
|
||||
using Shared::Graphics::Context;
|
||||
using Shared::Platform::WindowGl;
|
||||
using Shared::Platform::SizeState;
|
||||
using Shared::Platform::MouseState;
|
||||
using Shared::Platform::PerformanceTimer;
|
||||
using Shared::Platform::Ip;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class Program;
|
||||
class MainWindow;
|
||||
|
||||
// =====================================================
|
||||
// class ProgramState
|
||||
//
|
||||
/// Base class for all program states:
|
||||
/// Intro, MainMenu, Game, BattleEnd (State Design pattern)
|
||||
// =====================================================
|
||||
|
||||
class ProgramState{
|
||||
protected:
|
||||
Program *program;
|
||||
|
||||
public:
|
||||
ProgramState(Program *program) {this->program= program;}
|
||||
virtual ~ProgramState(){};
|
||||
|
||||
virtual void render()=0;
|
||||
virtual void update(){};
|
||||
virtual void updateCamera(){};
|
||||
virtual void tick(){};
|
||||
virtual void init(){};
|
||||
virtual void load(){};
|
||||
virtual void end(){};
|
||||
virtual void mouseDownLeft(int x, int y){};
|
||||
virtual void mouseUpLeft(int x, int y){};
|
||||
virtual void mouseDownRight(int x, int y){};
|
||||
virtual void mouseDoubleClickLeft(int x, int y){};
|
||||
virtual void mouseMove(int x, int y, const MouseState *mouseState){};
|
||||
virtual void keyDown(char key){};
|
||||
virtual void keyUp(char key){};
|
||||
virtual void keyPress(char c){};
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class Program
|
||||
// ===============================
|
||||
|
||||
class Program{
|
||||
private:
|
||||
static const int maxTimes;
|
||||
|
||||
private:
|
||||
ProgramState *programState;
|
||||
|
||||
PerformanceTimer fpsTimer;
|
||||
PerformanceTimer updateTimer;
|
||||
PerformanceTimer updateCameraTimer;
|
||||
|
||||
WindowGl *window;
|
||||
|
||||
public:
|
||||
Program();
|
||||
~Program();
|
||||
|
||||
void initNormal(WindowGl *window);
|
||||
void initServer(WindowGl *window);
|
||||
void initClient(WindowGl *window, const Ip &serverIp);
|
||||
|
||||
//main
|
||||
void mouseDownLeft(int x, int y);
|
||||
void mouseUpLeft(int x, int y);
|
||||
void mouseDownRight(int x, int y);
|
||||
void mouseDoubleClickLeft(int x, int y);
|
||||
void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
void keyDown(char key);
|
||||
void keyUp(char key);
|
||||
void keyPress(char c);
|
||||
void loop();
|
||||
void resize(SizeState sizeState);
|
||||
|
||||
//misc
|
||||
void setState(ProgramState *programState);
|
||||
void exit();
|
||||
|
||||
private:
|
||||
void init(WindowGl *window);
|
||||
void setDisplaySettings();
|
||||
void restoreDisplaySettings();
|
||||
};
|
||||
|
||||
}} //end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,194 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "main_menu.h"
|
||||
|
||||
#include "renderer.h"
|
||||
#include "sound.h"
|
||||
#include "config.h"
|
||||
#include "program.h"
|
||||
#include "game_util.h"
|
||||
#include "game.h"
|
||||
#include "platform_util.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "faction.h"
|
||||
#include "metrics.h"
|
||||
#include "network_manager.h"
|
||||
#include "network_message.h"
|
||||
#include "socket.h"
|
||||
#include "menu_state_root.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Sound;
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Xml;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class MainMenu
|
||||
// =====================================================
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
MainMenu::MainMenu(Program *program):
|
||||
ProgramState(program)
|
||||
{
|
||||
mouseX=100;
|
||||
mouseY=100;
|
||||
|
||||
state= NULL;
|
||||
this->program= program;
|
||||
|
||||
fps= 0;
|
||||
lastFps= 0;
|
||||
|
||||
setState(new MenuStateRoot(program, this));
|
||||
}
|
||||
|
||||
MainMenu::~MainMenu(){
|
||||
delete state;
|
||||
Renderer::getInstance().endMenu();
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
soundRenderer.stopAllSounds();
|
||||
}
|
||||
|
||||
void MainMenu::init(){
|
||||
Renderer::getInstance().initMenu(this);
|
||||
}
|
||||
|
||||
//asynchronus render update
|
||||
void MainMenu::render(){
|
||||
|
||||
Config &config= Config::getInstance();
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
|
||||
fps++;
|
||||
|
||||
renderer.clearBuffers();
|
||||
|
||||
//3d
|
||||
renderer.reset3dMenu();
|
||||
renderer.clearZBuffer();
|
||||
renderer.loadCameraMatrix(menuBackground.getCamera());
|
||||
renderer.renderMenuBackground(&menuBackground);
|
||||
renderer.renderParticleManager(rsMenu);
|
||||
|
||||
//2d
|
||||
renderer.reset2d();
|
||||
state->render();
|
||||
renderer.renderMouse2d(mouseX, mouseY, mouse2dAnim);
|
||||
|
||||
if(config.getBool("DebugMode")){
|
||||
renderer.renderText(
|
||||
"FPS: " + intToStr(lastFps),
|
||||
coreData.getMenuFontNormal(), Vec3f(1.f), 10, 10, false);
|
||||
}
|
||||
|
||||
renderer.swapBuffers();
|
||||
}
|
||||
|
||||
//syncronus update
|
||||
void MainMenu::update(){
|
||||
Renderer::getInstance().updateParticleManager(rsMenu);
|
||||
mouse2dAnim= (mouse2dAnim +1) % Renderer::maxMouse2dAnim;
|
||||
menuBackground.update();
|
||||
state->update();
|
||||
}
|
||||
|
||||
void MainMenu::tick(){
|
||||
lastFps= fps;
|
||||
fps= 0;
|
||||
}
|
||||
|
||||
//event magangement: mouse click
|
||||
void MainMenu::mouseMove(int x, int y, const MouseState *ms){
|
||||
mouseX= x; mouseY= y;
|
||||
state->mouseMove(x, y, ms);
|
||||
}
|
||||
|
||||
//returns if exiting
|
||||
void MainMenu::mouseDownLeft(int x, int y){
|
||||
state->mouseClick(x, y, mbLeft);
|
||||
}
|
||||
|
||||
void MainMenu::mouseDownRight(int x, int y){
|
||||
state->mouseClick(x, y, mbRight);
|
||||
}
|
||||
|
||||
void MainMenu::keyDown(char key){
|
||||
state->keyDown(key);
|
||||
}
|
||||
|
||||
void MainMenu::keyPress(char c){
|
||||
state->keyPress(c);
|
||||
}
|
||||
|
||||
void MainMenu::setState(MenuState *state){
|
||||
delete this->state;
|
||||
this->state= state;
|
||||
GraphicComponent::resetFade();
|
||||
|
||||
menuBackground.setTargetCamera(state->getCamera());
|
||||
}
|
||||
|
||||
|
||||
// =====================================================
|
||||
// class MenuState
|
||||
// =====================================================
|
||||
|
||||
MenuState::MenuState(Program *program, MainMenu *mainMenu, const string &stateName){
|
||||
this->program= program;
|
||||
this->mainMenu= mainMenu;
|
||||
|
||||
//camera
|
||||
XmlTree xmlTree;
|
||||
xmlTree.load("data/core/menu/menu.xml");
|
||||
const XmlNode *menuNode= xmlTree.getRootNode();
|
||||
const XmlNode *cameraNode= menuNode->getChild("camera");
|
||||
|
||||
//position
|
||||
const XmlNode *positionNode= cameraNode->getChild(stateName + "-position");
|
||||
Vec3f startPosition;
|
||||
startPosition.x= positionNode->getAttribute("x")->getFloatValue();
|
||||
startPosition.y= positionNode->getAttribute("y")->getFloatValue();
|
||||
startPosition.z= positionNode->getAttribute("z")->getFloatValue();
|
||||
camera.setPosition(startPosition);
|
||||
|
||||
//rotation
|
||||
const XmlNode *rotationNode= cameraNode->getChild(stateName + "-rotation");
|
||||
Vec3f startRotation;
|
||||
startRotation.x= rotationNode->getAttribute("x")->getFloatValue();
|
||||
startRotation.y= rotationNode->getAttribute("y")->getFloatValue();
|
||||
startRotation.z= rotationNode->getAttribute("z")->getFloatValue();
|
||||
camera.setOrientation(Quaternion(EulerAngles(
|
||||
degToRad(startRotation.x),
|
||||
degToRad(startRotation.y),
|
||||
degToRad(startRotation.z))));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,121 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MAINMENU_H_
|
||||
#define _GLEST_GAME_MAINMENU_H_
|
||||
|
||||
#include "lang.h"
|
||||
#include "console.h"
|
||||
#include "vec.h"
|
||||
#include "world.h"
|
||||
#include "program.h"
|
||||
#include "components.h"
|
||||
#include "menu_background.h"
|
||||
#include "game_settings.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
//misc consts
|
||||
struct MapInfo{
|
||||
Vec2i size;
|
||||
int players;
|
||||
string desc;
|
||||
};
|
||||
|
||||
struct ScenarioInfo
|
||||
{
|
||||
int difficulty;
|
||||
ControlType factionControls[GameConstants::maxPlayers];
|
||||
int teams[GameConstants::maxPlayers];
|
||||
string factionTypeNames[GameConstants::maxPlayers];
|
||||
|
||||
string mapName;
|
||||
string tilesetName;
|
||||
string techTreeName;
|
||||
|
||||
bool defaultUnits;
|
||||
bool defaultResources;
|
||||
bool defaultVictoryConditions;
|
||||
|
||||
string desc;
|
||||
};
|
||||
|
||||
class MenuState;
|
||||
|
||||
// =====================================================
|
||||
// class MainMenu
|
||||
//
|
||||
/// Main menu ProgramState
|
||||
// =====================================================
|
||||
|
||||
class MainMenu: public ProgramState{
|
||||
private:
|
||||
//up
|
||||
Program *program;
|
||||
|
||||
//shared
|
||||
GameSettings gameSettings;
|
||||
MenuBackground menuBackground;
|
||||
|
||||
MenuState *state;
|
||||
|
||||
//shared
|
||||
int mouseX, mouseY;
|
||||
int mouse2dAnim;
|
||||
int fps, lastFps;
|
||||
|
||||
public:
|
||||
MainMenu(Program *program);
|
||||
~MainMenu();
|
||||
|
||||
MenuBackground *getMenuBackground() {return &menuBackground;}
|
||||
|
||||
virtual void render();
|
||||
virtual void update();
|
||||
virtual void tick();
|
||||
virtual void init();
|
||||
virtual void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
virtual void mouseDownLeft(int x, int y);
|
||||
virtual void mouseDownRight(int x, int y);
|
||||
virtual void keyDown(char key);
|
||||
virtual void keyPress(char key);
|
||||
|
||||
void setState(MenuState *state);
|
||||
};
|
||||
|
||||
|
||||
// ===============================
|
||||
// class MenuState
|
||||
// ===============================
|
||||
|
||||
class MenuState{
|
||||
protected:
|
||||
Program *program;
|
||||
|
||||
MainMenu *mainMenu;
|
||||
Camera camera;
|
||||
|
||||
public:
|
||||
MenuState(Program *program, MainMenu *mainMenu, const string &stateName);
|
||||
virtual ~MenuState(){};
|
||||
virtual void mouseClick(int x, int y, MouseButton mouseButton)=0;
|
||||
virtual void mouseMove(int x, int y, const MouseState *mouseState)=0;
|
||||
virtual void render()=0;
|
||||
virtual void update(){};
|
||||
virtual void keyDown(char key){};
|
||||
virtual void keyPress(char c){};
|
||||
|
||||
const Camera *getCamera() const {return &camera;}
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,180 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "menu_background.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "config.h"
|
||||
#include "xml_parser.h"
|
||||
#include "util.h"
|
||||
#include "game_constants.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Xml;
|
||||
using namespace Shared::Graphics;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class MenuBackground
|
||||
// =====================================================
|
||||
|
||||
MenuBackground::MenuBackground(){
|
||||
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
//load data
|
||||
|
||||
XmlTree xmlTree;
|
||||
xmlTree.load("data/core/menu/menu.xml");
|
||||
const XmlNode *menuNode= xmlTree.getRootNode();
|
||||
|
||||
//water
|
||||
const XmlNode *waterNode= menuNode->getChild("water");
|
||||
water= waterNode->getAttribute("value")->getBoolValue();
|
||||
if(water){
|
||||
waterHeight= waterNode->getAttribute("height")->getFloatValue();
|
||||
|
||||
//water texture
|
||||
waterTexture= renderer.newTexture2D(rsMenu);
|
||||
waterTexture->getPixmap()->init(4);
|
||||
waterTexture->getPixmap()->load("data/core/menu/textures/water.tga");
|
||||
}
|
||||
|
||||
//fog
|
||||
const XmlNode *fogNode= menuNode->getChild("fog");
|
||||
fog= fogNode->getAttribute("value")->getBoolValue();
|
||||
if(fog){
|
||||
fogDensity= fogNode->getAttribute("density")->getFloatValue();
|
||||
}
|
||||
|
||||
//rain
|
||||
rain= menuNode->getChild("rain")->getAttribute("value")->getBoolValue();
|
||||
if(rain){
|
||||
RainParticleSystem *rps= new RainParticleSystem();
|
||||
rps->setSpeed(12.f/GameConstants::updateFps);
|
||||
rps->setEmissionRate(25);
|
||||
rps->setWind(-90.f, 4.f/GameConstants::updateFps);
|
||||
rps->setPos(Vec3f(0.f, 25.f, 0.f));
|
||||
rps->setColor(Vec4f(1.f, 1.f, 1.f, 0.2f));
|
||||
rps->setRadius(30.f);
|
||||
renderer.manageParticleSystem(rps, rsMenu);
|
||||
|
||||
for(int i=0; i<raindropCount; ++i){
|
||||
raindropStates[i]= random.randRange(0.f, 1.f);
|
||||
raindropPos[i]= computeRaindropPos();
|
||||
}
|
||||
}
|
||||
|
||||
//camera
|
||||
const XmlNode *cameraNode= menuNode->getChild("camera");
|
||||
|
||||
//position
|
||||
const XmlNode *positionNode= cameraNode->getChild("start-position");
|
||||
Vec3f startPosition;
|
||||
startPosition.x= positionNode->getAttribute("x")->getFloatValue();
|
||||
startPosition.y= positionNode->getAttribute("y")->getFloatValue();
|
||||
startPosition.z= positionNode->getAttribute("z")->getFloatValue();
|
||||
camera.setPosition(startPosition);
|
||||
|
||||
//rotation
|
||||
const XmlNode *rotationNode= cameraNode->getChild("start-rotation");
|
||||
Vec3f startRotation;
|
||||
startRotation.x= rotationNode->getAttribute("x")->getFloatValue();
|
||||
startRotation.y= rotationNode->getAttribute("y")->getFloatValue();
|
||||
startRotation.z= rotationNode->getAttribute("z")->getFloatValue();
|
||||
camera.setOrientation(Quaternion(EulerAngles(
|
||||
degToRad(startRotation.x),
|
||||
degToRad(startRotation.y),
|
||||
degToRad(startRotation.z))));
|
||||
|
||||
//load main model
|
||||
mainModel= renderer.newModel(rsMenu);
|
||||
mainModel->load("data/core/menu/main_model/menu_main.g3d");
|
||||
|
||||
//models
|
||||
for(int i=0; i<5; ++i){
|
||||
characterModels[i]= renderer.newModel(rsMenu);
|
||||
characterModels[i]->load("data/core/menu/about_models/character"+intToStr(i)+".g3d");
|
||||
}
|
||||
|
||||
//about position
|
||||
positionNode= cameraNode->getChild("about-position");
|
||||
aboutPosition.x= positionNode->getAttribute("x")->getFloatValue();
|
||||
aboutPosition.y= positionNode->getAttribute("y")->getFloatValue();
|
||||
aboutPosition.z= positionNode->getAttribute("z")->getFloatValue();
|
||||
rotationNode= cameraNode->getChild("about-rotation");
|
||||
|
||||
targetCamera= NULL;
|
||||
t= 0.f;
|
||||
fade= 0.f;
|
||||
anim= 0.f;
|
||||
}
|
||||
|
||||
void MenuBackground::setTargetCamera(const Camera *targetCamera){
|
||||
this->targetCamera= targetCamera;
|
||||
this->lastCamera= camera;
|
||||
t= 0.f;
|
||||
}
|
||||
|
||||
void MenuBackground::update(){
|
||||
|
||||
//rain drops
|
||||
for(int i=0; i<raindropCount; ++i){
|
||||
raindropStates[i]+= 1.f / GameConstants::updateFps;
|
||||
if(raindropStates[i]>=1.f){
|
||||
raindropStates[i]= 0.f;
|
||||
raindropPos[i]= computeRaindropPos();
|
||||
}
|
||||
}
|
||||
|
||||
if(targetCamera!=NULL){
|
||||
t+= ((0.01f+(1.f-t)/10.f)/20.f)*(60.f/GameConstants::updateFps);
|
||||
|
||||
//interpolate position
|
||||
camera.setPosition(lastCamera.getPosition().lerp(t, targetCamera->getPosition()));
|
||||
|
||||
//interpolate orientation
|
||||
Quaternion q= lastCamera.getOrientation().lerp(t, targetCamera->getOrientation());
|
||||
camera.setOrientation(q);
|
||||
|
||||
if(t>=1.f){
|
||||
targetCamera= NULL;
|
||||
t= 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
//fade
|
||||
if(fade<=1.f){
|
||||
fade+= 0.6f/GameConstants::updateFps;
|
||||
if(fade>1.f){
|
||||
fade= 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
//animation
|
||||
anim+=(0.6f/GameConstants::updateFps)/5+random.randRange(0.f, (0.6f/GameConstants::updateFps)/5.f);
|
||||
if(anim>1.f){
|
||||
anim= 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
Vec2f MenuBackground::computeRaindropPos(){
|
||||
float f= static_cast<float>(meshSize);
|
||||
return Vec2f(random.randRange(-f, f), random.randRange(-f, f));
|
||||
}
|
||||
|
||||
}}//end namespace
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MENUBACKGROUND_H_
|
||||
#define _GLEST_GAME_MENUBACKGROUND_H_
|
||||
|
||||
#include "particle.h"
|
||||
#include "camera.h"
|
||||
#include "vec.h"
|
||||
#include "texture.h"
|
||||
#include "model.h"
|
||||
#include "random.h"
|
||||
|
||||
using Shared::Graphics::RainParticleSystem;
|
||||
using Shared::Graphics::FireParticleSystem;
|
||||
using Shared::Graphics::Camera;
|
||||
using Shared::Graphics::Vec3f;
|
||||
using Shared::Graphics::Vec2f;
|
||||
using Shared::Graphics::Texture2D;
|
||||
using Shared::Graphics::Model;
|
||||
using Shared::Util::Random;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// ===========================================================
|
||||
// class MenuBackground
|
||||
//
|
||||
/// Holds the data to display the 3D environment
|
||||
/// in the MenuState
|
||||
// ===========================================================
|
||||
|
||||
class MenuBackground{
|
||||
public:
|
||||
static const int meshSize= 32;
|
||||
static const int raindropCount= 1000;
|
||||
static const int characterCount= 5;
|
||||
|
||||
private:
|
||||
Model *mainModel;
|
||||
|
||||
//water
|
||||
bool water;
|
||||
float waterHeight;
|
||||
Texture2D *waterTexture;
|
||||
|
||||
//fog
|
||||
bool fog;
|
||||
float fogDensity;
|
||||
|
||||
//rain
|
||||
bool rain;
|
||||
Vec2f raindropPos[raindropCount];
|
||||
float raindropStates[raindropCount];
|
||||
|
||||
//camera
|
||||
Camera camera;
|
||||
Camera lastCamera;
|
||||
const Camera *targetCamera;
|
||||
float t;
|
||||
|
||||
//misc
|
||||
Random random;
|
||||
Model *characterModels[characterCount];
|
||||
float anim;
|
||||
float fade;
|
||||
Vec3f aboutPosition;
|
||||
|
||||
public:
|
||||
MenuBackground();
|
||||
|
||||
bool getWater() const {return water;}
|
||||
float getWaterHeight() const {return waterHeight;}
|
||||
bool getFog() const {return fog;}
|
||||
float getFogDensity() const {return fogDensity;}
|
||||
bool getRain() const {return rain;}
|
||||
Texture2D *getWaterTexture() const {return waterTexture;}
|
||||
const Camera *getCamera() const {return &camera;}
|
||||
const Model *getCharacterModel(int i) const {return characterModels[i];}
|
||||
const Model *getMainModel() const {return mainModel;}
|
||||
float getFade() const {return fade;}
|
||||
Vec2f getRaindropPos(int i) const {return raindropPos[i];}
|
||||
float getRaindropState(int i) const {return raindropStates[i];}
|
||||
float getAnim() const {return anim;}
|
||||
const Vec3f &getAboutPosition() const {return aboutPosition;}
|
||||
|
||||
void setTargetCamera(const Camera *targetCamera);
|
||||
void update();
|
||||
|
||||
private:
|
||||
Vec2f computeRaindropPos();
|
||||
};
|
||||
|
||||
}} //end namespace
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "menu_state_about.h"
|
||||
|
||||
#include "renderer.h"
|
||||
#include "menu_state_root.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "menu_state_options.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class MenuStateAbout
|
||||
// =====================================================
|
||||
|
||||
MenuStateAbout::MenuStateAbout(Program *program, MainMenu *mainMenu):
|
||||
MenuState(program, mainMenu, "about")
|
||||
{
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
//init
|
||||
buttonReturn.init(460, 100, 125);
|
||||
buttonReturn.setText(lang.get("Return"));
|
||||
|
||||
for(int i= 0; i<aboutStringCount1; ++i){
|
||||
labelAbout1[i].init(100, 650-i*20);
|
||||
labelAbout1[i].setText(getAboutString1(i));
|
||||
}
|
||||
|
||||
for(int i= 0; i<aboutStringCount2; ++i){
|
||||
labelAbout2[i].init(460, 650-i*20);
|
||||
labelAbout2[i].setText(getAboutString2(i));
|
||||
}
|
||||
|
||||
for(int i= 0; i<teammateCount; ++i){
|
||||
labelTeammateName[i].init(100+i*180, 500);
|
||||
labelTeammateRole[i].init(100+i*180, 520);
|
||||
labelTeammateName[i].setText(getTeammateName(i));
|
||||
labelTeammateRole[i].setText(getTeammateRole(i));
|
||||
}
|
||||
|
||||
labelTeammateName[5].init(360, 160);
|
||||
labelTeammateRole[5].init(360, 180);
|
||||
labelTeammateName[6].init(540, 160);
|
||||
labelTeammateRole[6].init(540, 180);
|
||||
}
|
||||
|
||||
void MenuStateAbout::mouseClick(int x, int y, MouseButton mouseButton){
|
||||
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
|
||||
if(buttonReturn.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
mainMenu->setState(new MenuStateRoot(program, mainMenu));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MenuStateAbout::mouseMove(int x, int y, const MouseState *ms){
|
||||
buttonReturn.mouseMove(x, y);
|
||||
}
|
||||
|
||||
void MenuStateAbout::render(){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
renderer.renderButton(&buttonReturn);
|
||||
for(int i= 0; i<aboutStringCount1; ++i){
|
||||
renderer.renderLabel(&labelAbout1[i]);
|
||||
}
|
||||
for(int i= 0; i<aboutStringCount2; ++i){
|
||||
renderer.renderLabel(&labelAbout2[i]);
|
||||
}
|
||||
for(int i= 0; i<teammateCount; ++i){
|
||||
renderer.renderLabel(&labelTeammateName[i]);
|
||||
renderer.renderLabel(&labelTeammateRole[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,46 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MENUSTATEABOUT_H_
|
||||
#define _GLEST_GAME_MENUSTATEABOUT_H_
|
||||
|
||||
#include "main_menu.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// ===============================
|
||||
// class MenuStateAbout
|
||||
// ===============================
|
||||
|
||||
class MenuStateAbout: public MenuState{
|
||||
public:
|
||||
static const int aboutStringCount1= 3;
|
||||
static const int aboutStringCount2= 3;
|
||||
static const int teammateCount= 7;
|
||||
|
||||
private:
|
||||
GraphicButton buttonReturn;
|
||||
GraphicLabel labelAbout1[aboutStringCount1];
|
||||
GraphicLabel labelAbout2[aboutStringCount2];
|
||||
GraphicLabel labelTeammateName[teammateCount];
|
||||
GraphicLabel labelTeammateRole[teammateCount];
|
||||
|
||||
public:
|
||||
MenuStateAbout(Program *program, MainMenu *mainMenu);
|
||||
|
||||
void mouseClick(int x, int y, MouseButton mouseButton);
|
||||
void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
void render();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,427 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "menu_state_custom_game.h"
|
||||
|
||||
#include "renderer.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "config.h"
|
||||
#include "menu_state_new_game.h"
|
||||
#include "metrics.h"
|
||||
#include "network_manager.h"
|
||||
#include "network_message.h"
|
||||
#include "client_interface.h"
|
||||
#include "conversion.h"
|
||||
#include "socket.h"
|
||||
#include "game.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using namespace Shared::Util;
|
||||
|
||||
// =====================================================
|
||||
// class MenuStateCustomGame
|
||||
// =====================================================
|
||||
|
||||
MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, bool openNetworkSlots):
|
||||
MenuState(program, mainMenu, "new-game")
|
||||
{
|
||||
Lang &lang= Lang::getInstance();
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
|
||||
vector<string> results, teamItems, controlItems;
|
||||
|
||||
//create
|
||||
buttonReturn.init(350, 200, 125);
|
||||
buttonPlayNow.init(525, 200, 125);
|
||||
|
||||
//map listBox
|
||||
findAll("maps/*.gbm", results, true);
|
||||
if(results.size()==0){
|
||||
throw runtime_error("There is no maps");
|
||||
}
|
||||
mapFiles= results;
|
||||
for(int i= 0; i<results.size(); ++i){
|
||||
results[i]= formatString(results[i]);
|
||||
}
|
||||
listBoxMap.init(200, 320, 150);
|
||||
listBoxMap.setItems(results);
|
||||
labelMap.init(200, 350);
|
||||
labelMapInfo.init(200, 290, 200, 40);
|
||||
|
||||
//tileset listBox
|
||||
findAll("tilesets/*.", results);
|
||||
if(results.size()==0){
|
||||
throw runtime_error("There is no tile set");
|
||||
}
|
||||
tilesetFiles= results;
|
||||
for(int i= 0; i<results.size(); ++i){
|
||||
results[i]= formatString(results[i]);
|
||||
}
|
||||
listBoxTileset.init(400, 320, 150);
|
||||
listBoxTileset.setItems(results);
|
||||
labelTileset.init(400, 350);
|
||||
|
||||
//tech Tree listBox
|
||||
findAll("techs/*.", results);
|
||||
if(results.size()==0){
|
||||
throw runtime_error("There is no tech tree");
|
||||
}
|
||||
techTreeFiles= results;
|
||||
for(int i= 0; i<results.size(); ++i){
|
||||
results[i]= formatString(results[i]);
|
||||
}
|
||||
listBoxTechTree.init(600, 320, 150);
|
||||
listBoxTechTree.setItems(results);
|
||||
labelTechTree.init(600, 350);
|
||||
|
||||
//list boxes
|
||||
for(int i=0; i<GameConstants::maxPlayers; ++i){
|
||||
labelPlayers[i].init(200, 500-i*30);
|
||||
listBoxControls[i].init(300, 500-i*30);
|
||||
listBoxFactions[i].init(500, 500-i*30);
|
||||
listBoxTeams[i].init(700, 500-i*30, 60);
|
||||
labelNetStatus[i].init(800, 500-i*30, 60);
|
||||
}
|
||||
|
||||
labelControl.init(300, 550, GraphicListBox::defW, GraphicListBox::defH, true);
|
||||
labelFaction.init(500, 550, GraphicListBox::defW, GraphicListBox::defH, true);
|
||||
labelTeam.init(700, 550, 60, GraphicListBox::defH, true);
|
||||
|
||||
//texts
|
||||
buttonReturn.setText(lang.get("Return"));
|
||||
buttonPlayNow.setText(lang.get("PlayNow"));
|
||||
|
||||
controlItems.push_back(lang.get("Closed"));
|
||||
controlItems.push_back(lang.get("CpuEasy"));
|
||||
controlItems.push_back(lang.get("Cpu"));
|
||||
controlItems.push_back(lang.get("CpuUltra"));
|
||||
controlItems.push_back(lang.get("CpuMega"));
|
||||
controlItems.push_back(lang.get("Network"));
|
||||
controlItems.push_back(lang.get("Human"));
|
||||
teamItems.push_back("1");
|
||||
teamItems.push_back("2");
|
||||
teamItems.push_back("3");
|
||||
teamItems.push_back("4");
|
||||
|
||||
reloadFactions();
|
||||
|
||||
findAll("techs/"+techTreeFiles[listBoxTechTree.getSelectedItemIndex()]+"/factions/*.", results);
|
||||
if(results.size()==0){
|
||||
throw runtime_error("There is no factions for this tech tree");
|
||||
}
|
||||
|
||||
for(int i=0; i<GameConstants::maxPlayers; ++i){
|
||||
labelPlayers[i].setText(lang.get("Player")+" "+intToStr(i));
|
||||
listBoxTeams[i].setItems(teamItems);
|
||||
listBoxTeams[i].setSelectedItemIndex(i);
|
||||
listBoxControls[i].setItems(controlItems);
|
||||
labelNetStatus[i].setText("");
|
||||
}
|
||||
|
||||
labelMap.setText(lang.get("Map"));
|
||||
labelTileset.setText(lang.get("Tileset"));
|
||||
labelTechTree.setText(lang.get("TechTree"));
|
||||
labelControl.setText(lang.get("Control"));
|
||||
labelFaction.setText(lang.get("Faction"));
|
||||
labelTeam.setText(lang.get("Team"));
|
||||
|
||||
loadMapInfo(Map::getMapPath(mapFiles[listBoxMap.getSelectedItemIndex()]), &mapInfo);
|
||||
|
||||
labelMapInfo.setText(mapInfo.desc);
|
||||
|
||||
//initialize network interface
|
||||
networkManager.init(nrServer);
|
||||
|
||||
//init controllers
|
||||
listBoxControls[0].setSelectedItemIndex(ctHuman);
|
||||
if(openNetworkSlots){
|
||||
for(int i= 1; i<mapInfo.players; ++i){
|
||||
listBoxControls[i].setSelectedItemIndex(ctNetwork);
|
||||
}
|
||||
}
|
||||
else{
|
||||
listBoxControls[1].setSelectedItemIndex(ctCpu);
|
||||
}
|
||||
updateControlers();
|
||||
updateNetworkSlots();
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton){
|
||||
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
|
||||
|
||||
if(buttonReturn.mouseClick(x,y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
mainMenu->setState(new MenuStateNewGame(program, mainMenu));
|
||||
}
|
||||
else if(buttonPlayNow.mouseClick(x,y)){
|
||||
GameSettings gameSettings;
|
||||
|
||||
closeUnusedSlots();
|
||||
soundRenderer.playFx(coreData.getClickSoundC());
|
||||
loadGameSettings(&gameSettings);
|
||||
serverInterface->launchGame(&gameSettings);
|
||||
program->setState(new Game(program, &gameSettings));
|
||||
}
|
||||
else if(listBoxMap.mouseClick(x, y)){
|
||||
loadMapInfo(Map::getMapPath(mapFiles[listBoxMap.getSelectedItemIndex()]), &mapInfo);
|
||||
labelMapInfo.setText(mapInfo.desc);
|
||||
updateControlers();
|
||||
}
|
||||
else if(listBoxTileset.mouseClick(x, y)){
|
||||
}
|
||||
else if(listBoxTechTree.mouseClick(x, y)){
|
||||
reloadFactions();
|
||||
}
|
||||
else{
|
||||
for(int i=0; i<mapInfo.players; ++i){
|
||||
//ensure thet only 1 human player is present
|
||||
if(listBoxControls[i].mouseClick(x, y)){
|
||||
|
||||
//look for human players
|
||||
int humanIndex1= -1;
|
||||
int humanIndex2= -1;
|
||||
for(int j=0; j<GameConstants::maxPlayers; ++j){
|
||||
ControlType ct= static_cast<ControlType>(listBoxControls[j].getSelectedItemIndex());
|
||||
if(ct==ctHuman){
|
||||
if(humanIndex1==-1){
|
||||
humanIndex1= j;
|
||||
}
|
||||
else{
|
||||
humanIndex2= j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//no human
|
||||
if(humanIndex1==-1 && humanIndex2==-1){
|
||||
listBoxControls[i].setSelectedItemIndex(ctHuman);
|
||||
}
|
||||
|
||||
//2 humans
|
||||
if(humanIndex1!=-1 && humanIndex2!=-1){
|
||||
listBoxControls[humanIndex1==i? humanIndex2: humanIndex1].setSelectedItemIndex(ctClosed);
|
||||
}
|
||||
updateNetworkSlots();
|
||||
}
|
||||
else if(listBoxFactions[i].mouseClick(x, y)){
|
||||
}
|
||||
else if(listBoxTeams[i].mouseClick(x, y)){
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::mouseMove(int x, int y, const MouseState *ms){
|
||||
|
||||
buttonReturn.mouseMove(x, y);
|
||||
buttonPlayNow.mouseMove(x, y);
|
||||
|
||||
for(int i=0; i<GameConstants::maxPlayers; ++i){
|
||||
listBoxControls[i].mouseMove(x, y);
|
||||
listBoxFactions[i].mouseMove(x, y);
|
||||
listBoxTeams[i].mouseMove(x, y);
|
||||
}
|
||||
listBoxMap.mouseMove(x, y);
|
||||
listBoxTileset.mouseMove(x, y);
|
||||
listBoxTechTree.mouseMove(x, y);
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::render(){
|
||||
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
int i;
|
||||
|
||||
renderer.renderButton(&buttonReturn);
|
||||
renderer.renderButton(&buttonPlayNow);
|
||||
|
||||
for(i=0; i<GameConstants::maxPlayers; ++i){
|
||||
renderer.renderLabel(&labelPlayers[i]);
|
||||
renderer.renderListBox(&listBoxControls[i]);
|
||||
if(listBoxControls[i].getSelectedItemIndex()!=ctClosed){
|
||||
renderer.renderListBox(&listBoxFactions[i]);
|
||||
renderer.renderListBox(&listBoxTeams[i]);
|
||||
renderer.renderLabel(&labelNetStatus[i]);
|
||||
}
|
||||
}
|
||||
renderer.renderLabel(&labelMap);
|
||||
renderer.renderLabel(&labelTileset);
|
||||
renderer.renderLabel(&labelTechTree);
|
||||
renderer.renderLabel(&labelControl);
|
||||
renderer.renderLabel(&labelFaction);
|
||||
renderer.renderLabel(&labelTeam);
|
||||
renderer.renderLabel(&labelMapInfo);
|
||||
|
||||
renderer.renderListBox(&listBoxMap);
|
||||
renderer.renderListBox(&listBoxTileset);
|
||||
renderer.renderListBox(&listBoxTechTree);
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::update(){
|
||||
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
|
||||
Lang& lang= Lang::getInstance();
|
||||
|
||||
for(int i= 0; i<mapInfo.players; ++i){
|
||||
if(listBoxControls[i].getSelectedItemIndex()==ctNetwork){
|
||||
ConnectionSlot* connectionSlot= serverInterface->getSlot(i);
|
||||
|
||||
assert(connectionSlot!=NULL);
|
||||
|
||||
if(connectionSlot->isConnected()){
|
||||
labelNetStatus[i].setText(connectionSlot->getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
labelNetStatus[i].setText(lang.get("NotConnected"));
|
||||
}
|
||||
}
|
||||
else{
|
||||
labelNetStatus[i].setText("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings){
|
||||
|
||||
int factionCount= 0;
|
||||
|
||||
gameSettings->setDescription(formatString(mapFiles[listBoxMap.getSelectedItemIndex()]));
|
||||
gameSettings->setMap(mapFiles[listBoxMap.getSelectedItemIndex()]);
|
||||
gameSettings->setTileset(tilesetFiles[listBoxTileset.getSelectedItemIndex()]);
|
||||
gameSettings->setTech(techTreeFiles[listBoxTechTree.getSelectedItemIndex()]);
|
||||
gameSettings->setDefaultUnits(true);
|
||||
gameSettings->setDefaultResources(true);
|
||||
gameSettings->setDefaultVictoryConditions(true);
|
||||
|
||||
for(int i=0; i<mapInfo.players; ++i){
|
||||
ControlType ct= static_cast<ControlType>(listBoxControls[i].getSelectedItemIndex());
|
||||
if(ct!=ctClosed){
|
||||
if(ct==ctHuman){
|
||||
gameSettings->setThisFactionIndex(factionCount);
|
||||
}
|
||||
gameSettings->setFactionControl(factionCount, ct);
|
||||
gameSettings->setTeam(factionCount, listBoxTeams[i].getSelectedItemIndex());
|
||||
gameSettings->setStartLocationIndex(factionCount, i);
|
||||
gameSettings->setFactionTypeName(factionCount, factionFiles[listBoxFactions[i].getSelectedItemIndex()]);
|
||||
factionCount++;
|
||||
}
|
||||
}
|
||||
gameSettings->setFactionCount(factionCount);
|
||||
}
|
||||
|
||||
// ============ PRIVATE ===========================
|
||||
|
||||
void MenuStateCustomGame::loadMapInfo(string file, MapInfo *mapInfo){
|
||||
|
||||
struct MapFileHeader{
|
||||
int32 version;
|
||||
int32 maxPlayers;
|
||||
int32 width;
|
||||
int32 height;
|
||||
int32 altFactor;
|
||||
int32 waterLevel;
|
||||
int8 title[128];
|
||||
};
|
||||
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
try{
|
||||
FILE *f= fopen(file.c_str(), "rb");
|
||||
if(f==NULL)
|
||||
throw runtime_error("Can't open file");
|
||||
|
||||
MapFileHeader header;
|
||||
fread(&header, sizeof(MapFileHeader), 1, f);
|
||||
|
||||
mapInfo->size.x= header.width;
|
||||
mapInfo->size.y= header.height;
|
||||
mapInfo->players= header.maxPlayers;
|
||||
|
||||
mapInfo->desc= lang.get("MaxPlayers")+": "+intToStr(mapInfo->players)+"\n";
|
||||
mapInfo->desc+=lang.get("Size")+": "+intToStr(mapInfo->size.x) + " x " + intToStr(mapInfo->size.y);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
catch(exception e){
|
||||
throw runtime_error("Error loading map file: "+file+'\n'+e.what());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::reloadFactions(){
|
||||
|
||||
vector<string> results;
|
||||
|
||||
findAll("techs/"+techTreeFiles[listBoxTechTree.getSelectedItemIndex()]+"/factions/*.", results);
|
||||
if(results.size()==0){
|
||||
throw runtime_error("There is no factions for this tech tree");
|
||||
}
|
||||
factionFiles= results;
|
||||
for(int i= 0; i<results.size(); ++i){
|
||||
results[i]= formatString(results[i]);
|
||||
}
|
||||
for(int i=0; i<GameConstants::maxPlayers; ++i){
|
||||
listBoxFactions[i].setItems(results);
|
||||
listBoxFactions[i].setSelectedItemIndex(i % results.size());
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::updateControlers(){
|
||||
bool humanPlayer= false;
|
||||
|
||||
for(int i= 0; i<mapInfo.players; ++i){
|
||||
if(listBoxControls[i].getSelectedItemIndex() == ctHuman){
|
||||
humanPlayer= true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!humanPlayer){
|
||||
listBoxControls[0].setSelectedItemIndex(ctHuman);
|
||||
}
|
||||
|
||||
for(int i= mapInfo.players; i<GameConstants::maxPlayers; ++i){
|
||||
listBoxControls[i].setSelectedItemIndex(ctClosed);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::closeUnusedSlots(){
|
||||
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
|
||||
for(int i= 0; i<mapInfo.players; ++i){
|
||||
if(listBoxControls[i].getSelectedItemIndex()==ctNetwork){
|
||||
if(!serverInterface->getSlot(i)->isConnected()){
|
||||
listBoxControls[i].setSelectedItemIndex(ctClosed);
|
||||
}
|
||||
}
|
||||
}
|
||||
updateNetworkSlots();
|
||||
}
|
||||
|
||||
void MenuStateCustomGame::updateNetworkSlots(){
|
||||
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
if(serverInterface->getSlot(i)==NULL && listBoxControls[i].getSelectedItemIndex()==ctNetwork){
|
||||
serverInterface->addSlot(i);
|
||||
}
|
||||
if(serverInterface->getSlot(i) != NULL && listBoxControls[i].getSelectedItemIndex()!=ctNetwork){
|
||||
serverInterface->removeSlot(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,67 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MENUSTATECUSTOMGAME_H_
|
||||
#define _GLEST_GAME_MENUSTATECUSTOMGAME_H_
|
||||
|
||||
#include "main_menu.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// ===============================
|
||||
// class MenuStateCustomGame
|
||||
// ===============================
|
||||
|
||||
class MenuStateCustomGame: public MenuState{
|
||||
private:
|
||||
GraphicButton buttonReturn;
|
||||
GraphicButton buttonPlayNow;
|
||||
GraphicLabel labelControl;
|
||||
GraphicLabel labelFaction;
|
||||
GraphicLabel labelTeam;
|
||||
GraphicLabel labelMap;
|
||||
GraphicLabel labelTechTree;
|
||||
GraphicLabel labelTileset;
|
||||
GraphicLabel labelMapInfo;
|
||||
GraphicListBox listBoxMap;
|
||||
GraphicListBox listBoxTechTree;
|
||||
GraphicListBox listBoxTileset;
|
||||
vector<string> mapFiles;
|
||||
vector<string> techTreeFiles;
|
||||
vector<string> tilesetFiles;
|
||||
vector<string> factionFiles;
|
||||
GraphicLabel labelPlayers[GameConstants::maxPlayers];
|
||||
GraphicListBox listBoxControls[GameConstants::maxPlayers];
|
||||
GraphicListBox listBoxFactions[GameConstants::maxPlayers];
|
||||
GraphicListBox listBoxTeams[GameConstants::maxPlayers];
|
||||
GraphicLabel labelNetStatus[GameConstants::maxPlayers];
|
||||
MapInfo mapInfo;
|
||||
|
||||
public:
|
||||
MenuStateCustomGame(Program *program, MainMenu *mainMenu, bool openNetworkSlots= false);
|
||||
|
||||
void mouseClick(int x, int y, MouseButton mouseButton);
|
||||
void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
void render();
|
||||
void update();
|
||||
|
||||
private:
|
||||
void loadGameSettings(GameSettings *gameSettings);
|
||||
void loadMapInfo(string file, MapInfo *mapInfo);
|
||||
void reloadFactions();
|
||||
void updateControlers();
|
||||
void closeUnusedSlots();
|
||||
void updateNetworkSlots();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,68 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "menu_state_graphic_info.h"
|
||||
|
||||
#include "renderer.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "menu_state_options.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class MenuStateGraphicInfo
|
||||
// =====================================================
|
||||
|
||||
MenuStateGraphicInfo::MenuStateGraphicInfo(Program *program, MainMenu *mainMenu):
|
||||
MenuState(program, mainMenu, "info")
|
||||
{
|
||||
buttonReturn.init(387, 100, 125);
|
||||
labelInfo.init(100, 700);
|
||||
labelMoreInfo.init(100, 500);
|
||||
labelMoreInfo.setFont(CoreData::getInstance().getMenuFontSmall());
|
||||
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
glInfo= renderer.getGlInfo();
|
||||
glMoreInfo= renderer.getGlMoreInfo();
|
||||
}
|
||||
|
||||
void MenuStateGraphicInfo::mouseClick(int x, int y, MouseButton mouseButton){
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
|
||||
if(buttonReturn.mouseClick(x,y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
mainMenu->setState(new MenuStateOptions(program, mainMenu));
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateGraphicInfo::mouseMove(int x, int y, const MouseState *ms){
|
||||
buttonReturn.mouseMove(x, y);
|
||||
}
|
||||
|
||||
void MenuStateGraphicInfo::render(){
|
||||
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
buttonReturn.setText(lang.get("Return"));
|
||||
labelInfo.setText(glInfo);
|
||||
labelMoreInfo.setText(glMoreInfo);
|
||||
|
||||
renderer.renderButton(&buttonReturn);
|
||||
renderer.renderLabel(&labelInfo);
|
||||
renderer.renderLabel(&labelMoreInfo);
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,41 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MENUSTATEGRAPHICINFO_H_
|
||||
#define _GLEST_GAME_MENUSTATEGRAPHICINFO_H_
|
||||
|
||||
#include "main_menu.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// ===============================
|
||||
// class MenuStateGraphicInfo
|
||||
// ===============================
|
||||
|
||||
class MenuStateGraphicInfo: public MenuState{
|
||||
private:
|
||||
GraphicButton buttonReturn;
|
||||
GraphicLabel labelInfo;
|
||||
GraphicLabel labelMoreInfo;
|
||||
|
||||
string glInfo;
|
||||
string glMoreInfo;
|
||||
public:
|
||||
MenuStateGraphicInfo(Program *program, MainMenu *mainMenu);
|
||||
|
||||
void mouseClick(int x, int y, MouseButton mouseButton);
|
||||
void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
void render();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,277 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "menu_state_join_game.h"
|
||||
|
||||
#include "renderer.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "config.h"
|
||||
#include "menu_state_root.h"
|
||||
#include "metrics.h"
|
||||
#include "network_manager.h"
|
||||
#include "network_message.h"
|
||||
#include "client_interface.h"
|
||||
#include "conversion.h"
|
||||
#include "game.h"
|
||||
#include "socket.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using namespace Shared::Util;
|
||||
|
||||
// ===============================
|
||||
// class MenuStateJoinGame
|
||||
// ===============================
|
||||
|
||||
const int MenuStateJoinGame::newServerIndex= 0;
|
||||
const string MenuStateJoinGame::serverFileName= "servers.ini";
|
||||
|
||||
MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool connect, Ip serverIp):
|
||||
MenuState(program, mainMenu, "join-game")
|
||||
{
|
||||
Lang &lang= Lang::getInstance();
|
||||
Config &config= Config::getInstance();
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
|
||||
servers.load(serverFileName);
|
||||
|
||||
//buttons
|
||||
buttonReturn.init(325, 300, 125);
|
||||
buttonReturn.setText(lang.get("Return"));
|
||||
|
||||
buttonConnect.init(475, 300, 125);
|
||||
buttonConnect.setText(lang.get("Connect"));
|
||||
|
||||
//server type label
|
||||
labelServerType.init(330, 460);
|
||||
labelServerType.setText(lang.get("ServerType") + ":");
|
||||
|
||||
//server type list box
|
||||
listBoxServerType.init(465, 460);
|
||||
listBoxServerType.pushBackItem(lang.get("ServerTypeNew"));
|
||||
listBoxServerType.pushBackItem(lang.get("ServerTypePrevious"));
|
||||
|
||||
//server label
|
||||
labelServer.init(330, 430);
|
||||
labelServer.setText(lang.get("Server") + ": ");
|
||||
|
||||
//server listbox
|
||||
listBoxServers.init(465, 430);
|
||||
|
||||
for(int i= 0; i<servers.getPropertyCount(); ++i){
|
||||
listBoxServers.pushBackItem(servers.getKey(i));
|
||||
}
|
||||
|
||||
//server ip
|
||||
labelServerIp.init(465, 430);
|
||||
|
||||
labelStatus.init(330, 400);
|
||||
labelStatus.setText("");
|
||||
|
||||
labelInfo.init(330, 370);
|
||||
labelInfo.setText("");
|
||||
|
||||
networkManager.init(nrClient);
|
||||
connected= false;
|
||||
playerIndex= -1;
|
||||
|
||||
//server ip
|
||||
if(connect){
|
||||
labelServerIp.setText(serverIp.getString() + "_");
|
||||
connectToServer();
|
||||
}
|
||||
else
|
||||
{
|
||||
labelServerIp.setText(config.getString("ServerIp") + "_");
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton){
|
||||
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
ClientInterface* clientInterface= networkManager.getClientInterface();
|
||||
|
||||
if(!clientInterface->isConnected()){
|
||||
//server type
|
||||
if(listBoxServerType.mouseClick(x, y)){
|
||||
if(!listBoxServers.getText().empty()){
|
||||
labelServerIp.setText(servers.getString(listBoxServers.getText())+"_");
|
||||
}
|
||||
}
|
||||
|
||||
//server list
|
||||
else if(listBoxServerType.getSelectedItemIndex()!=newServerIndex){
|
||||
if(listBoxServers.mouseClick(x, y)){
|
||||
labelServerIp.setText(servers.getString(listBoxServers.getText())+"_");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//return
|
||||
if(buttonReturn.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
mainMenu->setState(new MenuStateRoot(program, mainMenu));
|
||||
}
|
||||
|
||||
//connect
|
||||
else if(buttonConnect.mouseClick(x, y)){
|
||||
ClientInterface* clientInterface= networkManager.getClientInterface();
|
||||
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
labelInfo.setText("");
|
||||
|
||||
if(clientInterface->isConnected()){
|
||||
clientInterface->reset();
|
||||
}
|
||||
else{
|
||||
connectToServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::mouseMove(int x, int y, const MouseState *ms){
|
||||
buttonReturn.mouseMove(x, y);
|
||||
buttonConnect.mouseMove(x, y);
|
||||
listBoxServerType.mouseMove(x, y);
|
||||
|
||||
//hide-show options depending on the selection
|
||||
if(listBoxServers.getSelectedItemIndex()==newServerIndex){
|
||||
labelServerIp.mouseMove(x, y);
|
||||
}
|
||||
else{
|
||||
listBoxServers.mouseMove(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::render(){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
renderer.renderButton(&buttonReturn);
|
||||
renderer.renderLabel(&labelServer);
|
||||
renderer.renderLabel(&labelServerType);
|
||||
renderer.renderLabel(&labelStatus);
|
||||
renderer.renderLabel(&labelInfo);
|
||||
renderer.renderButton(&buttonConnect);
|
||||
renderer.renderListBox(&listBoxServerType);
|
||||
|
||||
if(listBoxServerType.getSelectedItemIndex()==newServerIndex){
|
||||
renderer.renderLabel(&labelServerIp);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.renderListBox(&listBoxServers);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::update(){
|
||||
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
//update status label
|
||||
if(clientInterface->isConnected()){
|
||||
buttonConnect.setText(lang.get("Disconnect"));
|
||||
if(!clientInterface->getServerName().empty()){
|
||||
labelStatus.setText(lang.get("ConnectedToServer") + " " + clientInterface->getServerName());
|
||||
}
|
||||
else{
|
||||
labelStatus.setText(lang.get("ConnectedToServer"));
|
||||
}
|
||||
}
|
||||
else{
|
||||
buttonConnect.setText(lang.get("Connect"));
|
||||
labelStatus.setText(lang.get("NotConnected"));
|
||||
labelInfo.setText("");
|
||||
}
|
||||
|
||||
//process network messages
|
||||
if(clientInterface->isConnected()){
|
||||
|
||||
//update lobby
|
||||
clientInterface->updateLobby();
|
||||
|
||||
//intro
|
||||
if(clientInterface->getIntroDone()){
|
||||
labelInfo.setText(lang.get("WaitingHost"));
|
||||
servers.setString(clientInterface->getServerName(), Ip(labelServerIp.getText()).getString());
|
||||
}
|
||||
|
||||
//launch
|
||||
if(clientInterface->getLaunchGame()){
|
||||
servers.save(serverFileName);
|
||||
program->setState(new Game(program, clientInterface->getGameSettings()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::keyDown(char key){
|
||||
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
|
||||
|
||||
if(!clientInterface->isConnected()){
|
||||
if(key==vkBack){
|
||||
string text= labelServerIp.getText();
|
||||
|
||||
if(text.size()>1){
|
||||
text.erase(text.end()-2);
|
||||
}
|
||||
|
||||
labelServerIp.setText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::keyPress(char c){
|
||||
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
|
||||
|
||||
if(!clientInterface->isConnected()){
|
||||
int maxTextSize= 16;
|
||||
|
||||
if(c>='0' && c<='9'){
|
||||
|
||||
if(labelServerIp.getText().size()<maxTextSize){
|
||||
string text= labelServerIp.getText();
|
||||
|
||||
text.insert(text.end()-1, c);
|
||||
|
||||
labelServerIp.setText(text);
|
||||
}
|
||||
}
|
||||
else if (c=='.'){
|
||||
if(labelServerIp.getText().size()<maxTextSize){
|
||||
string text= labelServerIp.getText();
|
||||
|
||||
text.insert(text.end()-1, '.');
|
||||
|
||||
labelServerIp.setText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateJoinGame::connectToServer(){
|
||||
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
|
||||
Config& config= Config::getInstance();
|
||||
Ip serverIp(labelServerIp.getText());
|
||||
|
||||
clientInterface->connect(serverIp, GameConstants::serverPort);
|
||||
labelServerIp.setText(serverIp.getString()+'_');
|
||||
labelInfo.setText("");
|
||||
|
||||
//save server ip
|
||||
config.setString("ServerIp", serverIp.getString());
|
||||
config.save();
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,63 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MENUSTATEJOINGAME_H_
|
||||
#define _GLEST_GAME_MENUSTATEJOINGAME_H_
|
||||
|
||||
#include "properties.h"
|
||||
#include "main_menu.h"
|
||||
|
||||
using Shared::Util::Properties;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class NetworkMessageIntro;
|
||||
|
||||
// ===============================
|
||||
// class MenuStateJoinGame
|
||||
// ===============================
|
||||
|
||||
class MenuStateJoinGame: public MenuState{
|
||||
private:
|
||||
static const int newServerIndex;
|
||||
static const string serverFileName;
|
||||
|
||||
private:
|
||||
GraphicButton buttonReturn;
|
||||
GraphicButton buttonConnect;
|
||||
GraphicLabel labelServer;
|
||||
GraphicLabel labelServerType;
|
||||
GraphicLabel labelServerIp;
|
||||
GraphicLabel labelStatus;
|
||||
GraphicLabel labelInfo;
|
||||
GraphicListBox listBoxServerType;
|
||||
GraphicListBox listBoxServers;
|
||||
|
||||
bool connected;
|
||||
int playerIndex;
|
||||
Properties servers;
|
||||
|
||||
public:
|
||||
MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool connect= false, Ip serverIp= Ip());
|
||||
|
||||
void mouseClick(int x, int y, MouseButton mouseButton);
|
||||
void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
void render();
|
||||
void update();
|
||||
void keyDown(char key);
|
||||
void keyPress(char c);
|
||||
|
||||
private:
|
||||
void connectToServer();
|
||||
};
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,98 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "menu_state_new_game.h"
|
||||
|
||||
#include "renderer.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "config.h"
|
||||
#include "menu_state_custom_game.h"
|
||||
#include "menu_state_scenario.h"
|
||||
#include "menu_state_root.h"
|
||||
#include "metrics.h"
|
||||
#include "network_manager.h"
|
||||
#include "network_message.h"
|
||||
#include "auto_test.h"
|
||||
#include "socket.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class MenuStateNewGame
|
||||
// =====================================================
|
||||
|
||||
MenuStateNewGame::MenuStateNewGame(Program *program, MainMenu *mainMenu):
|
||||
MenuState(program, mainMenu, "root")
|
||||
{
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
buttonCustomGame.init(425, 350, 150);
|
||||
buttonScenario.init(425, 310, 150);
|
||||
buttonTutorial.init(425, 270, 150);
|
||||
buttonReturn.init(425, 230, 150);
|
||||
|
||||
buttonCustomGame.setText(lang.get("CustomGame"));
|
||||
buttonScenario.setText(lang.get("Scenario"));
|
||||
buttonTutorial.setText(lang.get("Tutorial"));
|
||||
buttonReturn.setText(lang.get("Return"));
|
||||
|
||||
NetworkManager::getInstance().end();
|
||||
}
|
||||
|
||||
void MenuStateNewGame::mouseClick(int x, int y, MouseButton mouseButton){
|
||||
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
|
||||
if(buttonCustomGame.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundB());
|
||||
mainMenu->setState(new MenuStateCustomGame(program, mainMenu));
|
||||
}
|
||||
else if(buttonScenario.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundB());
|
||||
mainMenu->setState(new MenuStateScenario(program, mainMenu, "scenarios"));
|
||||
}
|
||||
else if(buttonTutorial.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundB());
|
||||
mainMenu->setState(new MenuStateScenario(program, mainMenu, "tutorials"));
|
||||
}
|
||||
else if(buttonReturn.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundB());
|
||||
mainMenu->setState(new MenuStateRoot(program, mainMenu));
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateNewGame::mouseMove(int x, int y, const MouseState *ms){
|
||||
buttonCustomGame.mouseMove(x, y);
|
||||
buttonScenario.mouseMove(x, y);
|
||||
buttonTutorial.mouseMove(x, y);
|
||||
buttonReturn.mouseMove(x, y);
|
||||
}
|
||||
|
||||
void MenuStateNewGame::render(){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
renderer.renderButton(&buttonCustomGame);
|
||||
renderer.renderButton(&buttonScenario);
|
||||
renderer.renderButton(&buttonTutorial);
|
||||
renderer.renderButton(&buttonReturn);
|
||||
}
|
||||
|
||||
void MenuStateNewGame::update(){
|
||||
if(Config::getInstance().getBool("AutoTest")){
|
||||
AutoTest::getInstance().updateNewGame(program, mainMenu);
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,42 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MENUSTATENEWGAME_H_
|
||||
#define _GLEST_GAME_MENUSTATENEWGAME_H_
|
||||
|
||||
#include "main_menu.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// ===============================
|
||||
// class MenuStateNewGame
|
||||
// ===============================
|
||||
|
||||
class MenuStateNewGame: public MenuState{
|
||||
private:
|
||||
GraphicButton buttonCustomGame;
|
||||
GraphicButton buttonScenario;
|
||||
GraphicButton buttonTutorial;
|
||||
GraphicButton buttonReturn;
|
||||
|
||||
public:
|
||||
MenuStateNewGame(Program *program, MainMenu *mainMenu);
|
||||
|
||||
void mouseClick(int x, int y, MouseButton mouseButton);
|
||||
void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
void update();
|
||||
void render();
|
||||
};
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,227 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "menu_state_options.h"
|
||||
|
||||
#include "renderer.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "config.h"
|
||||
#include "menu_state_root.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class MenuStateOptions
|
||||
// =====================================================
|
||||
|
||||
MenuStateOptions::MenuStateOptions(Program *program, MainMenu *mainMenu):
|
||||
MenuState(program, mainMenu, "config")
|
||||
{
|
||||
Lang &lang= Lang::getInstance();
|
||||
Config &config= Config::getInstance();
|
||||
|
||||
//create
|
||||
buttonReturn.init(200, 150, 125);
|
||||
buttonAutoConfig.init(375, 150, 125);
|
||||
|
||||
//labels
|
||||
labelVolumeFx.init(200, 530);
|
||||
labelVolumeAmbient.init(200, 500);
|
||||
labelVolumeMusic.init(200, 470);
|
||||
|
||||
labelLang.init(200, 400);
|
||||
|
||||
labelFilter.init(200, 340);
|
||||
labelShadows.init(200, 310);
|
||||
labelTextures3D.init(200, 280);
|
||||
labelLights.init(200, 250);
|
||||
|
||||
//list boxes
|
||||
listBoxVolumeFx.init(350, 530, 80);
|
||||
listBoxVolumeAmbient.init(350, 500, 80);
|
||||
listBoxVolumeMusic.init(350, 470, 80);
|
||||
listBoxMusicSelect.init(350, 440, 150);
|
||||
|
||||
listBoxLang.init(350, 400, 170);
|
||||
|
||||
listBoxFilter.init(350, 340, 170);
|
||||
listBoxShadows.init(350, 310, 170);
|
||||
listBoxTextures3D.init(350, 280, 80);
|
||||
listBoxLights.init(350, 250, 80);
|
||||
|
||||
//set text
|
||||
buttonReturn.setText(lang.get("Return"));
|
||||
buttonAutoConfig.setText(lang.get("AutoConfig"));
|
||||
labelLang.setText(lang.get("Language"));
|
||||
labelShadows.setText(lang.get("Shadows"));
|
||||
labelFilter.setText(lang.get("Filter"));
|
||||
labelTextures3D.setText(lang.get("Textures3D"));
|
||||
labelLights.setText(lang.get("MaxLights"));
|
||||
labelVolumeFx.setText(lang.get("FxVolume"));
|
||||
labelVolumeAmbient.setText(lang.get("AmbientVolume"));
|
||||
labelVolumeMusic.setText(lang.get("MusicVolume"));
|
||||
|
||||
//sound
|
||||
|
||||
//lang
|
||||
vector<string> langResults;
|
||||
findAll("data/lang/*.lng", langResults, true);
|
||||
if(langResults.empty()){
|
||||
throw runtime_error("There is no lang file");
|
||||
}
|
||||
listBoxLang.setItems(langResults);
|
||||
listBoxLang.setSelectedItem(config.getString("Lang"));
|
||||
|
||||
//shadows
|
||||
for(int i= 0; i<Renderer::sCount; ++i){
|
||||
listBoxShadows.pushBackItem(lang.get(Renderer::shadowsToStr(static_cast<Renderer::Shadows>(i))));
|
||||
}
|
||||
|
||||
string str= config.getString("Shadows");
|
||||
listBoxShadows.setSelectedItemIndex(clamp(Renderer::strToShadows(str), 0, Renderer::sCount-1));
|
||||
|
||||
//filter
|
||||
listBoxFilter.pushBackItem("Bilinear");
|
||||
listBoxFilter.pushBackItem("Trilinear");
|
||||
listBoxFilter.setSelectedItem(config.getString("Filter"));
|
||||
|
||||
//textures 3d
|
||||
listBoxTextures3D.pushBackItem(lang.get("No"));
|
||||
listBoxTextures3D.pushBackItem(lang.get("Yes"));
|
||||
listBoxTextures3D.setSelectedItemIndex(clamp(config.getInt("Textures3D"), 0, 1));
|
||||
|
||||
//lights
|
||||
for(int i= 1; i<=8; ++i){
|
||||
listBoxLights.pushBackItem(intToStr(i));
|
||||
}
|
||||
listBoxLights.setSelectedItemIndex(clamp(config.getInt("MaxLights")-1, 0, 7));
|
||||
|
||||
//sound
|
||||
for(int i=0; i<=100; i+=5){
|
||||
listBoxVolumeFx.pushBackItem(intToStr(i));
|
||||
listBoxVolumeAmbient.pushBackItem(intToStr(i));
|
||||
listBoxVolumeMusic.pushBackItem(intToStr(i));
|
||||
}
|
||||
listBoxVolumeFx.setSelectedItem(intToStr(config.getInt("SoundVolumeFx")/5*5));
|
||||
listBoxVolumeAmbient.setSelectedItem(intToStr(config.getInt("SoundVolumeAmbient")/5*5));
|
||||
listBoxVolumeMusic.setSelectedItem(intToStr(config.getInt("SoundVolumeMusic")/5*5));
|
||||
}
|
||||
|
||||
void MenuStateOptions::mouseClick(int x, int y, MouseButton mouseButton){
|
||||
|
||||
Config &config= Config::getInstance();
|
||||
Lang &lang= Lang::getInstance();
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
|
||||
if(buttonReturn.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
mainMenu->setState(new MenuStateRoot(program, mainMenu));
|
||||
}
|
||||
else if(buttonAutoConfig.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
Renderer::getInstance().autoConfig();
|
||||
saveConfig();
|
||||
mainMenu->setState(new MenuStateOptions(program, mainMenu));
|
||||
}
|
||||
else if(listBoxLang.mouseClick(x, y)){
|
||||
config.setString("Lang", listBoxLang.getSelectedItem());
|
||||
lang.loadStrings(config.getString("Lang"));
|
||||
saveConfig();
|
||||
mainMenu->setState(new MenuStateOptions(program, mainMenu));
|
||||
|
||||
}
|
||||
else if(listBoxShadows.mouseClick(x, y)){
|
||||
int index= listBoxShadows.getSelectedItemIndex();
|
||||
config.setString("Shadows", Renderer::shadowsToStr(static_cast<Renderer::Shadows>(index)));
|
||||
saveConfig();
|
||||
}
|
||||
else if(listBoxFilter.mouseClick(x, y)){
|
||||
config.setString("Filter", listBoxFilter.getSelectedItem());
|
||||
saveConfig();
|
||||
}
|
||||
else if(listBoxTextures3D.mouseClick(x, y)){
|
||||
config.setInt("Textures3D", listBoxTextures3D.getSelectedItemIndex());
|
||||
saveConfig();
|
||||
}
|
||||
else if(listBoxLights.mouseClick(x, y)){
|
||||
config.setInt("MaxLights", listBoxLights.getSelectedItemIndex()+1);
|
||||
saveConfig();
|
||||
}
|
||||
else if(listBoxVolumeFx.mouseClick(x, y)){
|
||||
config.setString("SoundVolumeFx", listBoxVolumeFx.getSelectedItem());
|
||||
saveConfig();
|
||||
}
|
||||
else if(listBoxVolumeAmbient.mouseClick(x, y)){
|
||||
config.setString("SoundVolumeAmbient", listBoxVolumeAmbient.getSelectedItem());
|
||||
saveConfig();
|
||||
}
|
||||
else if(listBoxVolumeMusic.mouseClick(x, y)){
|
||||
CoreData::getInstance().getMenuMusic()->setVolume(strToInt(listBoxVolumeMusic.getSelectedItem())/100.f);
|
||||
config.setString("SoundVolumeMusic", listBoxVolumeMusic.getSelectedItem());
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MenuStateOptions::mouseMove(int x, int y, const MouseState *ms){
|
||||
buttonReturn.mouseMove(x, y);
|
||||
buttonAutoConfig.mouseMove(x, y);
|
||||
listBoxLang.mouseMove(x, y);
|
||||
listBoxVolumeFx.mouseMove(x, y);
|
||||
listBoxVolumeAmbient.mouseMove(x, y);
|
||||
listBoxVolumeMusic.mouseMove(x, y);
|
||||
listBoxLang.mouseMove(x, y);
|
||||
listBoxFilter.mouseMove(x, y);
|
||||
listBoxShadows.mouseMove(x, y);
|
||||
listBoxTextures3D.mouseMove(x, y);
|
||||
listBoxLights.mouseMove(x, y);
|
||||
}
|
||||
|
||||
void MenuStateOptions::render(){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
renderer.renderButton(&buttonReturn);
|
||||
renderer.renderButton(&buttonAutoConfig);
|
||||
renderer.renderListBox(&listBoxLang);
|
||||
renderer.renderListBox(&listBoxShadows);
|
||||
renderer.renderListBox(&listBoxTextures3D);
|
||||
renderer.renderListBox(&listBoxLights);
|
||||
renderer.renderListBox(&listBoxFilter);
|
||||
renderer.renderListBox(&listBoxVolumeFx);
|
||||
renderer.renderListBox(&listBoxVolumeAmbient);
|
||||
renderer.renderListBox(&listBoxVolumeMusic);
|
||||
renderer.renderLabel(&labelLang);
|
||||
renderer.renderLabel(&labelShadows);
|
||||
renderer.renderLabel(&labelTextures3D);
|
||||
renderer.renderLabel(&labelLights);
|
||||
renderer.renderLabel(&labelFilter);
|
||||
renderer.renderLabel(&labelVolumeFx);
|
||||
renderer.renderLabel(&labelVolumeAmbient);
|
||||
renderer.renderLabel(&labelVolumeMusic);
|
||||
}
|
||||
|
||||
void MenuStateOptions::saveConfig(){
|
||||
Config &config= Config::getInstance();
|
||||
|
||||
config.save();
|
||||
Renderer::getInstance().loadConfig();
|
||||
SoundRenderer::getInstance().loadConfig();
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,59 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MENUSTATEOPTIONS_H_
|
||||
#define _GLEST_GAME_MENUSTATEOPTIONS_H_
|
||||
|
||||
#include "main_menu.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// ===============================
|
||||
// class MenuStateOptions
|
||||
// ===============================
|
||||
|
||||
class MenuStateOptions: public MenuState{
|
||||
private:
|
||||
GraphicButton buttonReturn;
|
||||
GraphicButton buttonAutoConfig;
|
||||
|
||||
GraphicLabel labelLang;
|
||||
GraphicLabel labelShadows;
|
||||
GraphicLabel labelFilter;
|
||||
GraphicLabel labelTextures3D;
|
||||
GraphicLabel labelLights;
|
||||
GraphicLabel labelVolumeFx;
|
||||
GraphicLabel labelVolumeAmbient;
|
||||
GraphicLabel labelVolumeMusic;
|
||||
GraphicListBox listBoxLang;
|
||||
GraphicListBox listBoxShadows;
|
||||
GraphicListBox listBoxFilter;
|
||||
GraphicListBox listBoxTextures3D;
|
||||
GraphicListBox listBoxLights;
|
||||
GraphicListBox listBoxVolumeFx;
|
||||
GraphicListBox listBoxVolumeAmbient;
|
||||
GraphicListBox listBoxVolumeMusic;
|
||||
GraphicListBox listBoxMusicSelect;
|
||||
|
||||
public:
|
||||
MenuStateOptions(Program *program, MainMenu *mainMenu);
|
||||
|
||||
void mouseClick(int x, int y, MouseButton mouseButton);
|
||||
void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
void render();
|
||||
|
||||
private:
|
||||
void saveConfig();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,116 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "menu_state_root.h"
|
||||
|
||||
#include "renderer.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "config.h"
|
||||
#include "menu_state_new_game.h"
|
||||
#include "menu_state_join_game.h"
|
||||
#include "menu_state_options.h"
|
||||
#include "menu_state_about.h"
|
||||
#include "metrics.h"
|
||||
#include "network_manager.h"
|
||||
#include "network_message.h"
|
||||
#include "socket.h"
|
||||
#include "auto_test.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class MenuStateRoot
|
||||
// =====================================================
|
||||
|
||||
MenuStateRoot::MenuStateRoot(Program *program, MainMenu *mainMenu):
|
||||
MenuState(program, mainMenu, "root")
|
||||
{
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
buttonNewGame.init(425, 350, 150);
|
||||
buttonJoinGame.init(425, 310, 150);
|
||||
buttonOptions.init(425, 270, 150);
|
||||
buttonAbout.init(425, 230, 150);
|
||||
buttonExit.init(425, 190, 150);
|
||||
labelVersion.init(525, 420);
|
||||
|
||||
buttonNewGame.setText(lang.get("NewGame"));
|
||||
buttonJoinGame.setText(lang.get("JoinGame"));
|
||||
buttonOptions.setText(lang.get("Options"));
|
||||
buttonAbout.setText(lang.get("About"));
|
||||
buttonExit.setText(lang.get("Exit"));
|
||||
labelVersion.setText(glestVersionString);
|
||||
}
|
||||
|
||||
void MenuStateRoot::mouseClick(int x, int y, MouseButton mouseButton){
|
||||
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
|
||||
if(buttonNewGame.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundB());
|
||||
mainMenu->setState(new MenuStateNewGame(program, mainMenu));
|
||||
}
|
||||
else if(buttonJoinGame.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundB());
|
||||
mainMenu->setState(new MenuStateJoinGame(program, mainMenu));
|
||||
}
|
||||
else if(buttonOptions.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundB());
|
||||
mainMenu->setState(new MenuStateOptions(program, mainMenu));
|
||||
}
|
||||
else if(buttonAbout.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundB());
|
||||
mainMenu->setState(new MenuStateAbout(program, mainMenu));
|
||||
}
|
||||
else if(buttonExit.mouseClick(x, y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
program->exit();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateRoot::mouseMove(int x, int y, const MouseState *ms){
|
||||
buttonNewGame.mouseMove(x, y);
|
||||
buttonJoinGame.mouseMove(x, y);
|
||||
buttonOptions.mouseMove(x, y);
|
||||
buttonAbout.mouseMove(x, y);
|
||||
buttonExit.mouseMove(x,y);
|
||||
}
|
||||
|
||||
void MenuStateRoot::render(){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
|
||||
int w= 300;
|
||||
int h= 150;
|
||||
|
||||
renderer.renderTextureQuad(
|
||||
(metrics.getVirtualW()-w)/2, 475-h/2, w, h,
|
||||
coreData.getLogoTexture(), GraphicComponent::getFade());
|
||||
renderer.renderButton(&buttonNewGame);
|
||||
renderer.renderButton(&buttonJoinGame);
|
||||
renderer.renderButton(&buttonOptions);
|
||||
renderer.renderButton(&buttonAbout);
|
||||
renderer.renderButton(&buttonExit);
|
||||
renderer.renderLabel(&labelVersion);
|
||||
}
|
||||
|
||||
void MenuStateRoot::update(){
|
||||
if(Config::getInstance().getBool("AutoTest")){
|
||||
AutoTest::getInstance().updateRoot(program, mainMenu);
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,44 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MENUSTATEROOT_H_
|
||||
#define _GLEST_GAME_MENUSTATEROOT_H_
|
||||
|
||||
#include "main_menu.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// ===============================
|
||||
// class MenuStateRoot
|
||||
// ===============================
|
||||
|
||||
class MenuStateRoot: public MenuState{
|
||||
private:
|
||||
GraphicButton buttonNewGame;
|
||||
GraphicButton buttonJoinGame;
|
||||
GraphicButton buttonOptions;
|
||||
GraphicButton buttonAbout;
|
||||
GraphicButton buttonExit;
|
||||
GraphicLabel labelVersion;
|
||||
|
||||
public:
|
||||
MenuStateRoot(Program *program, MainMenu *mainMenu);
|
||||
|
||||
void mouseClick(int x, int y, MouseButton mouseButton);
|
||||
void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
void render();
|
||||
void update();
|
||||
};
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,248 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "menu_state_scenario.h"
|
||||
|
||||
#include "renderer.h"
|
||||
#include "menu_state_new_game.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "core_data.h"
|
||||
#include "menu_state_options.h"
|
||||
#include "network_manager.h"
|
||||
#include "config.h"
|
||||
#include "auto_test.h"
|
||||
#include "game.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using namespace Shared::Xml;
|
||||
|
||||
// =====================================================
|
||||
// class MenuStateScenario
|
||||
// =====================================================
|
||||
|
||||
MenuStateScenario::MenuStateScenario(Program *program, MainMenu *mainMenu, const string &dir):
|
||||
MenuState(program, mainMenu, "scenario")
|
||||
{
|
||||
Lang &lang= Lang::getInstance();
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
vector<string> results;
|
||||
|
||||
this->dir = dir;
|
||||
|
||||
labelInfo.init(350, 350);
|
||||
labelInfo.setFont(CoreData::getInstance().getMenuFontNormal());
|
||||
|
||||
buttonReturn.init(350, 200, 125);
|
||||
buttonPlayNow.init(525, 200, 125);
|
||||
|
||||
listBoxScenario.init(350, 400, 190);
|
||||
labelScenario.init(350, 430);
|
||||
|
||||
buttonReturn.setText(lang.get("Return"));
|
||||
buttonPlayNow.setText(lang.get("PlayNow"));
|
||||
|
||||
labelScenario.setText(lang.get("Scenario"));
|
||||
|
||||
//scenario listbox
|
||||
findAll(dir+"/*.", results);
|
||||
scenarioFiles= results;
|
||||
if(results.size()==0){
|
||||
throw runtime_error("There are no scenarios");
|
||||
}
|
||||
for(int i= 0; i<results.size(); ++i){
|
||||
results[i]= formatString(results[i]);
|
||||
}
|
||||
listBoxScenario.setItems(results);
|
||||
|
||||
loadScenarioInfo(Scenario::getScenarioPath(dir, scenarioFiles[listBoxScenario.getSelectedItemIndex()]), &scenarioInfo );
|
||||
labelInfo.setText(scenarioInfo.desc);
|
||||
|
||||
networkManager.init(nrServer);
|
||||
}
|
||||
|
||||
void MenuStateScenario::mouseClick(int x, int y, MouseButton mouseButton){
|
||||
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
|
||||
if(buttonReturn.mouseClick(x,y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundA());
|
||||
mainMenu->setState(new MenuStateNewGame(program, mainMenu));
|
||||
}
|
||||
else if(buttonPlayNow.mouseClick(x,y)){
|
||||
soundRenderer.playFx(coreData.getClickSoundC());
|
||||
launchGame();
|
||||
}
|
||||
else if(listBoxScenario.mouseClick(x, y)){
|
||||
loadScenarioInfo(Scenario::getScenarioPath(dir, scenarioFiles[listBoxScenario.getSelectedItemIndex()]), &scenarioInfo);
|
||||
labelInfo.setText(scenarioInfo.desc);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateScenario::mouseMove(int x, int y, const MouseState *ms){
|
||||
|
||||
listBoxScenario.mouseMove(x, y);
|
||||
|
||||
buttonReturn.mouseMove(x, y);
|
||||
buttonPlayNow.mouseMove(x, y);
|
||||
}
|
||||
|
||||
void MenuStateScenario::render(){
|
||||
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
renderer.renderLabel(&labelInfo);
|
||||
renderer.renderLabel(&labelScenario);
|
||||
renderer.renderListBox(&listBoxScenario);
|
||||
|
||||
renderer.renderButton(&buttonReturn);
|
||||
renderer.renderButton(&buttonPlayNow);
|
||||
}
|
||||
|
||||
void MenuStateScenario::update(){
|
||||
if(Config::getInstance().getBool("AutoTest")){
|
||||
AutoTest::getInstance().updateScenario(this);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuStateScenario::launchGame(){
|
||||
GameSettings gameSettings;
|
||||
loadGameSettings(&scenarioInfo, &gameSettings);
|
||||
program->setState(new Game(program, &gameSettings));
|
||||
}
|
||||
|
||||
void MenuStateScenario::setScenario(int i){
|
||||
listBoxScenario.setSelectedItemIndex(i);
|
||||
loadScenarioInfo(Scenario::getScenarioPath(dir, scenarioFiles[listBoxScenario.getSelectedItemIndex()]), &scenarioInfo);
|
||||
}
|
||||
|
||||
void MenuStateScenario::loadScenarioInfo(string file, ScenarioInfo *scenarioInfo){
|
||||
|
||||
Lang &lang= Lang::getInstance();
|
||||
|
||||
XmlTree xmlTree;
|
||||
xmlTree.load(file);
|
||||
|
||||
const XmlNode *scenarioNode= xmlTree.getRootNode();
|
||||
const XmlNode *difficultyNode= scenarioNode->getChild("difficulty");
|
||||
scenarioInfo->difficulty = difficultyNode->getAttribute("value")->getIntValue();
|
||||
if( scenarioInfo->difficulty < dVeryEasy || scenarioInfo->difficulty > dInsane )
|
||||
{
|
||||
throw std::runtime_error("Invalid difficulty");
|
||||
}
|
||||
|
||||
const XmlNode *playersNode= scenarioNode->getChild("players");
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
const XmlNode* playerNode = playersNode->getChild("player", i);
|
||||
ControlType factionControl = strToControllerType( playerNode->getAttribute("control")->getValue() );
|
||||
string factionTypeName;
|
||||
|
||||
scenarioInfo->factionControls[i] = factionControl;
|
||||
|
||||
if(factionControl != ctClosed){
|
||||
int teamIndex = playerNode->getAttribute("team")->getIntValue();
|
||||
|
||||
if( teamIndex < 1 || teamIndex > GameConstants::maxPlayers )
|
||||
{
|
||||
throw runtime_error("Team out of range: " + intToStr(teamIndex) );
|
||||
}
|
||||
|
||||
scenarioInfo->teams[i]= playerNode->getAttribute("team")->getIntValue();
|
||||
scenarioInfo->factionTypeNames[i]= playerNode->getAttribute("faction")->getValue();
|
||||
}
|
||||
|
||||
scenarioInfo->mapName = scenarioNode->getChild("map")->getAttribute("value")->getValue();
|
||||
scenarioInfo->tilesetName = scenarioNode->getChild("tileset")->getAttribute("value")->getValue();
|
||||
scenarioInfo->techTreeName = scenarioNode->getChild("tech-tree")->getAttribute("value")->getValue();
|
||||
scenarioInfo->defaultUnits = scenarioNode->getChild("default-units")->getAttribute("value")->getBoolValue();
|
||||
scenarioInfo->defaultResources = scenarioNode->getChild("default-resources")->getAttribute("value")->getBoolValue();
|
||||
scenarioInfo->defaultVictoryConditions = scenarioNode->getChild("default-victory-conditions")->getAttribute("value")->getBoolValue();
|
||||
}
|
||||
|
||||
//add player info
|
||||
scenarioInfo->desc= lang.get("Player") + ": ";
|
||||
for(int i=0; i<GameConstants::maxPlayers; ++i )
|
||||
{
|
||||
if(scenarioInfo->factionControls[i] == ctHuman )
|
||||
{
|
||||
scenarioInfo->desc+= formatString(scenarioInfo->factionTypeNames[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//add misc info
|
||||
string difficultyString = "Difficulty" + intToStr(scenarioInfo->difficulty);
|
||||
|
||||
scenarioInfo->desc+= "\n";
|
||||
scenarioInfo->desc+= lang.get("Difficulty") + ": " + lang.get(difficultyString) +"\n";
|
||||
scenarioInfo->desc+= lang.get("Map") + ": " + formatString(scenarioInfo->mapName) + "\n";
|
||||
scenarioInfo->desc+= lang.get("Tileset") + ": " + formatString(scenarioInfo->tilesetName) + "\n";
|
||||
scenarioInfo->desc+= lang.get("TechTree") + ": " + formatString(scenarioInfo->techTreeName) + "\n";
|
||||
}
|
||||
|
||||
void MenuStateScenario::loadGameSettings(const ScenarioInfo *scenarioInfo, GameSettings *gameSettings){
|
||||
|
||||
int factionCount= 0;
|
||||
|
||||
gameSettings->setDescription(formatString(scenarioFiles[listBoxScenario.getSelectedItemIndex()]));
|
||||
gameSettings->setMap(scenarioInfo->mapName);
|
||||
gameSettings->setTileset(scenarioInfo->tilesetName);
|
||||
gameSettings->setTech(scenarioInfo->techTreeName);
|
||||
gameSettings->setScenario(scenarioFiles[listBoxScenario.getSelectedItemIndex()]);
|
||||
gameSettings->setScenarioDir(dir);
|
||||
gameSettings->setDefaultUnits(scenarioInfo->defaultUnits);
|
||||
gameSettings->setDefaultResources(scenarioInfo->defaultResources);
|
||||
gameSettings->setDefaultVictoryConditions(scenarioInfo->defaultVictoryConditions);
|
||||
|
||||
for(int i=0; i<GameConstants::maxPlayers; ++i){
|
||||
ControlType ct= static_cast<ControlType>(scenarioInfo->factionControls[i]);
|
||||
if(ct!=ctClosed){
|
||||
if(ct==ctHuman){
|
||||
gameSettings->setThisFactionIndex(factionCount);
|
||||
}
|
||||
gameSettings->setFactionControl(factionCount, ct);
|
||||
gameSettings->setTeam(factionCount, scenarioInfo->teams[i]-1);
|
||||
gameSettings->setStartLocationIndex(factionCount, i);
|
||||
gameSettings->setFactionTypeName(factionCount, scenarioInfo->factionTypeNames[i]);
|
||||
factionCount++;
|
||||
}
|
||||
}
|
||||
|
||||
gameSettings->setFactionCount(factionCount);
|
||||
}
|
||||
|
||||
ControlType MenuStateScenario::strToControllerType(const string &str){
|
||||
if(str=="closed"){
|
||||
return ctClosed;
|
||||
}
|
||||
else if(str=="cpu-easy"){
|
||||
return ctCpuEasy;
|
||||
}
|
||||
else if(str=="cpu"){
|
||||
return ctCpu;
|
||||
}
|
||||
else if(str=="cpu-ultra"){
|
||||
return ctCpuUltra;
|
||||
}
|
||||
else if(str=="cpu-mega"){
|
||||
return ctCpuMega;
|
||||
}
|
||||
else if(str=="human"){
|
||||
return ctHuman;
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unknown controller type: " + str);
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,69 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2005 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_MENUSTATESCENARIO_H_
|
||||
#define _GLEST_GAME_MENUSTATESCENARIO_H_
|
||||
|
||||
#include "main_menu.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// ===============================
|
||||
// class MenuStateScenario
|
||||
// ===============================
|
||||
|
||||
class MenuStateScenario: public MenuState{
|
||||
private:
|
||||
enum Difficulty{
|
||||
dVeryEasy,
|
||||
dEasy,
|
||||
dMedium,
|
||||
dHard,
|
||||
dVeryHard,
|
||||
dInsane
|
||||
};
|
||||
|
||||
GraphicButton buttonReturn;
|
||||
GraphicButton buttonPlayNow;
|
||||
|
||||
GraphicLabel labelInfo;
|
||||
GraphicLabel labelScenario;
|
||||
GraphicListBox listBoxScenario;
|
||||
|
||||
vector<string> scenarioFiles;
|
||||
|
||||
ScenarioInfo scenarioInfo;
|
||||
string dir;
|
||||
|
||||
public:
|
||||
MenuStateScenario(Program *program, MainMenu *mainMenu, const string &dir);
|
||||
|
||||
void mouseClick(int x, int y, MouseButton mouseButton);
|
||||
void mouseMove(int x, int y, const MouseState *mouseState);
|
||||
void render();
|
||||
void update();
|
||||
|
||||
void launchGame();
|
||||
void setScenario(int i);
|
||||
int getScenarioCount() const { return listBoxScenario.getItemCount(); }
|
||||
|
||||
private:
|
||||
void loadScenarioInfo(string file, ScenarioInfo *scenarioInfo);
|
||||
void loadGameSettings(const ScenarioInfo *scenarioInfo, GameSettings *gameSettings);
|
||||
Difficulty computeDifficulty(const ScenarioInfo *scenarioInfo);
|
||||
ControlType strToControllerType(const string &str);
|
||||
|
||||
};
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,273 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "client_interface.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
#include "platform_util.h"
|
||||
#include "game_util.h"
|
||||
#include "conversion.h"
|
||||
#include "config.h"
|
||||
#include "lang.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class ClientInterface
|
||||
// =====================================================
|
||||
|
||||
const int ClientInterface::messageWaitTimeout= 10000; //10 seconds
|
||||
const int ClientInterface::waitSleepTime= 50;
|
||||
|
||||
ClientInterface::ClientInterface(){
|
||||
clientSocket= NULL;
|
||||
launchGame= false;
|
||||
introDone= false;
|
||||
playerIndex= -1;
|
||||
}
|
||||
|
||||
ClientInterface::~ClientInterface(){
|
||||
delete clientSocket;
|
||||
}
|
||||
|
||||
void ClientInterface::connect(const Ip &ip, int port){
|
||||
delete clientSocket;
|
||||
clientSocket= new ClientSocket();
|
||||
clientSocket->setBlock(false);
|
||||
clientSocket->connect(ip, port);
|
||||
}
|
||||
|
||||
void ClientInterface::reset(){
|
||||
delete clientSocket;
|
||||
clientSocket= NULL;
|
||||
}
|
||||
|
||||
void ClientInterface::update(){
|
||||
NetworkMessageCommandList networkMessageCommandList;
|
||||
|
||||
//send as many commands as we can
|
||||
while(!requestedCommands.empty()){
|
||||
if(networkMessageCommandList.addCommand(&requestedCommands.back())){
|
||||
requestedCommands.pop_back();
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(networkMessageCommandList.getCommandCount()>0){
|
||||
sendMessage(&networkMessageCommandList);
|
||||
}
|
||||
|
||||
//clear chat variables
|
||||
chatText.clear();
|
||||
chatSender.clear();
|
||||
chatTeamIndex= -1;
|
||||
}
|
||||
|
||||
void ClientInterface::updateLobby(){
|
||||
NetworkMessageType networkMessageType= getNextMessageType();
|
||||
|
||||
switch(networkMessageType){
|
||||
case nmtInvalid:
|
||||
break;
|
||||
|
||||
case nmtIntro:{
|
||||
NetworkMessageIntro networkMessageIntro;
|
||||
|
||||
if(receiveMessage(&networkMessageIntro)){
|
||||
|
||||
//check consistency
|
||||
if(Config::getInstance().getBool("NetworkConsistencyChecks")){
|
||||
if(networkMessageIntro.getVersionString()!=getNetworkVersionString()){
|
||||
throw runtime_error("Server and client versions do not match (" + networkMessageIntro.getVersionString() + "). You have to use the same binaries.");
|
||||
}
|
||||
}
|
||||
|
||||
//send intro message
|
||||
NetworkMessageIntro sendNetworkMessageIntro(getNetworkVersionString(), getHostName(), -1);
|
||||
|
||||
playerIndex= networkMessageIntro.getPlayerIndex();
|
||||
serverName= networkMessageIntro.getName();
|
||||
sendMessage(&sendNetworkMessageIntro);
|
||||
|
||||
assert(playerIndex>=0 && playerIndex<GameConstants::maxPlayers);
|
||||
introDone= true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case nmtLaunch:{
|
||||
NetworkMessageLaunch networkMessageLaunch;
|
||||
|
||||
if(receiveMessage(&networkMessageLaunch)){
|
||||
networkMessageLaunch.buildGameSettings(&gameSettings);
|
||||
|
||||
//replace server player by network
|
||||
for(int i= 0; i<gameSettings.getFactionCount(); ++i){
|
||||
|
||||
//replace by network
|
||||
if(gameSettings.getFactionControl(i)==ctHuman){
|
||||
gameSettings.setFactionControl(i, ctNetwork);
|
||||
}
|
||||
|
||||
//set the faction index
|
||||
if(gameSettings.getStartLocationIndex(i)==playerIndex){
|
||||
gameSettings.setThisFactionIndex(i);
|
||||
}
|
||||
}
|
||||
launchGame= true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw runtime_error("Unexpected network message: " + intToStr(networkMessageType));
|
||||
}
|
||||
}
|
||||
|
||||
void ClientInterface::updateKeyframe(int frameCount){
|
||||
|
||||
bool done= false;
|
||||
|
||||
while(!done){
|
||||
//wait for the next message
|
||||
waitForMessage();
|
||||
|
||||
//check we have an expected message
|
||||
NetworkMessageType networkMessageType= getNextMessageType();
|
||||
|
||||
switch(networkMessageType){
|
||||
case nmtCommandList:{
|
||||
//make sure we read the message
|
||||
NetworkMessageCommandList networkMessageCommandList;
|
||||
while(!receiveMessage(&networkMessageCommandList)){
|
||||
sleep(waitSleepTime);
|
||||
}
|
||||
|
||||
//check that we are in the right frame
|
||||
if(networkMessageCommandList.getFrameCount()!=frameCount){
|
||||
throw runtime_error("Network synchronization error, frame counts do not match");
|
||||
}
|
||||
|
||||
// give all commands
|
||||
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i){
|
||||
pendingCommands.push_back(*networkMessageCommandList.getCommand(i));
|
||||
}
|
||||
|
||||
done= true;
|
||||
}
|
||||
break;
|
||||
|
||||
case nmtQuit:{
|
||||
NetworkMessageQuit networkMessageQuit;
|
||||
if(receiveMessage(&networkMessageQuit)){
|
||||
quit= true;
|
||||
}
|
||||
done= true;
|
||||
}
|
||||
break;
|
||||
|
||||
case nmtText:{
|
||||
NetworkMessageText networkMessageText;
|
||||
if(receiveMessage(&networkMessageText)){
|
||||
chatText= networkMessageText.getText();
|
||||
chatSender= networkMessageText.getSender();
|
||||
chatTeamIndex= networkMessageText.getTeamIndex();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw runtime_error("Unexpected message in client interface: " + intToStr(networkMessageType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientInterface::waitUntilReady(Checksum* checksum){
|
||||
|
||||
NetworkMessageReady networkMessageReady;
|
||||
Chrono chrono;
|
||||
|
||||
chrono.start();
|
||||
|
||||
//send ready message
|
||||
sendMessage(&networkMessageReady);
|
||||
|
||||
//wait until we get a ready message from the server
|
||||
while(true){
|
||||
|
||||
NetworkMessageType networkMessageType= getNextMessageType();
|
||||
|
||||
if(networkMessageType==nmtReady){
|
||||
if(receiveMessage(&networkMessageReady)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(networkMessageType==nmtInvalid){
|
||||
if(chrono.getMillis()>readyWaitTimeout){
|
||||
throw runtime_error("Timeout waiting for server");
|
||||
}
|
||||
}
|
||||
else{
|
||||
throw runtime_error("Unexpected network message: " + intToStr(networkMessageType) );
|
||||
}
|
||||
|
||||
// sleep a bit
|
||||
sleep(waitSleepTime);
|
||||
}
|
||||
|
||||
//check checksum
|
||||
if(Config::getInstance().getBool("NetworkConsistencyChecks")){
|
||||
if(networkMessageReady.getChecksum()!=checksum->getSum()){
|
||||
throw runtime_error("Checksum error, you don't have the same data as the server");
|
||||
}
|
||||
}
|
||||
|
||||
//delay the start a bit, so clients have nore room to get messages
|
||||
sleep(GameConstants::networkExtraLatency);
|
||||
}
|
||||
|
||||
void ClientInterface::sendTextMessage(const string &text, int teamIndex){
|
||||
NetworkMessageText networkMessageText(text, getHostName(), teamIndex);
|
||||
sendMessage(&networkMessageText);
|
||||
}
|
||||
|
||||
string ClientInterface::getNetworkStatus() const{
|
||||
return Lang::getInstance().get("Server") + ": " + serverName;
|
||||
}
|
||||
|
||||
void ClientInterface::waitForMessage(){
|
||||
Chrono chrono;
|
||||
|
||||
chrono.start();
|
||||
|
||||
while(getNextMessageType()==nmtInvalid){
|
||||
|
||||
if(!isConnected()){
|
||||
throw runtime_error("Disconnected");
|
||||
}
|
||||
|
||||
if(chrono.getMillis()>messageWaitTimeout){
|
||||
throw runtime_error("Timeout waiting for message");
|
||||
}
|
||||
|
||||
sleep(waitSleepTime);
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,81 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_CLIENTINTERFACE_H_
|
||||
#define _GLEST_GAME_CLIENTINTERFACE_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "network_interface.h"
|
||||
#include "game_settings.h"
|
||||
|
||||
#include "socket.h"
|
||||
|
||||
using Shared::Platform::Ip;
|
||||
using Shared::Platform::ClientSocket;
|
||||
using std::vector;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class ClientInterface
|
||||
// =====================================================
|
||||
|
||||
class ClientInterface: public GameNetworkInterface{
|
||||
private:
|
||||
static const int messageWaitTimeout;
|
||||
static const int waitSleepTime;
|
||||
|
||||
private:
|
||||
ClientSocket *clientSocket;
|
||||
GameSettings gameSettings;
|
||||
string serverName;
|
||||
bool introDone;
|
||||
bool launchGame;
|
||||
int playerIndex;
|
||||
|
||||
public:
|
||||
ClientInterface();
|
||||
virtual ~ClientInterface();
|
||||
|
||||
virtual Socket* getSocket() {return clientSocket;}
|
||||
virtual const Socket* getSocket() const {return clientSocket;}
|
||||
|
||||
//message processing
|
||||
virtual void update();
|
||||
virtual void updateLobby();
|
||||
virtual void updateKeyframe(int frameCount);
|
||||
virtual void waitUntilReady(Checksum* checksum);
|
||||
|
||||
// message sending
|
||||
virtual void sendTextMessage(const string &text, int teamIndex);
|
||||
virtual void quitGame(){}
|
||||
|
||||
//misc
|
||||
virtual string getNetworkStatus() const;
|
||||
|
||||
//accessors
|
||||
string getServerName() const {return serverName;}
|
||||
bool getLaunchGame() const {return launchGame;}
|
||||
bool getIntroDone() const {return introDone;}
|
||||
int getPlayerIndex() const {return playerIndex;}
|
||||
const GameSettings *getGameSettings() {return &gameSettings;}
|
||||
|
||||
void connect(const Ip &ip, int port);
|
||||
void reset();
|
||||
|
||||
private:
|
||||
void waitForMessage();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,99 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "connection_slot.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "conversion.h"
|
||||
#include "game_util.h"
|
||||
#include "config.h"
|
||||
#include "server_interface.h"
|
||||
#include "network_message.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class ClientConnection
|
||||
// =====================================================
|
||||
|
||||
ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex){
|
||||
this->serverInterface= serverInterface;
|
||||
this->playerIndex= playerIndex;
|
||||
socket= NULL;
|
||||
ready= false;
|
||||
}
|
||||
|
||||
ConnectionSlot::~ConnectionSlot(){
|
||||
close();
|
||||
}
|
||||
|
||||
void ConnectionSlot::update(){
|
||||
if(socket==NULL){
|
||||
socket= serverInterface->getServerSocket()->accept();
|
||||
|
||||
//send intro message when connected
|
||||
if(socket!=NULL){
|
||||
NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex);
|
||||
sendMessage(&networkMessageIntro);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(socket->isConnected()){
|
||||
NetworkMessageType networkMessageType= getNextMessageType();
|
||||
|
||||
//process incoming commands
|
||||
switch(networkMessageType){
|
||||
|
||||
case nmtInvalid:
|
||||
case nmtText:
|
||||
break;
|
||||
|
||||
//command list
|
||||
case nmtCommandList:{
|
||||
NetworkMessageCommandList networkMessageCommandList;
|
||||
if(receiveMessage(&networkMessageCommandList)){
|
||||
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i){
|
||||
serverInterface->requestCommand(networkMessageCommandList.getCommand(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//process intro messages
|
||||
case nmtIntro:{
|
||||
NetworkMessageIntro networkMessageIntro;
|
||||
if(receiveMessage(&networkMessageIntro)){
|
||||
name= networkMessageIntro.getName();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw runtime_error("Unexpected message in connection slot: " + intToStr(networkMessageType));
|
||||
}
|
||||
}
|
||||
else{
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionSlot::close(){
|
||||
delete socket;
|
||||
socket= NULL;
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,61 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_CONNECTIONSLOT_H_
|
||||
#define _GLEST_GAME_CONNECTIONSLOT_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "socket.h"
|
||||
|
||||
#include "network_interface.h"
|
||||
|
||||
using Shared::Platform::ServerSocket;
|
||||
using Shared::Platform::Socket;
|
||||
using std::vector;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class ServerInterface;
|
||||
|
||||
// =====================================================
|
||||
// class ConnectionSlot
|
||||
// =====================================================
|
||||
|
||||
class ConnectionSlot: public NetworkInterface{
|
||||
private:
|
||||
ServerInterface* serverInterface;
|
||||
Socket* socket;
|
||||
int playerIndex;
|
||||
string name;
|
||||
bool ready;
|
||||
|
||||
public:
|
||||
ConnectionSlot(ServerInterface* serverInterface, int playerIndex);
|
||||
~ConnectionSlot();
|
||||
|
||||
virtual void update();
|
||||
|
||||
void setReady() {ready= true;}
|
||||
const string &getName() const {return name;}
|
||||
bool isReady() const {return ready;}
|
||||
|
||||
protected:
|
||||
virtual Socket* getSocket() {return socket;}
|
||||
virtual Socket* getSocket() const {return socket;}
|
||||
|
||||
private:
|
||||
void close();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,77 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "network_interface.h"
|
||||
|
||||
#include <exception>
|
||||
#include <cassert>
|
||||
|
||||
#include "types.h"
|
||||
#include "conversion.h"
|
||||
#include "platform_util.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class NetworkInterface
|
||||
// =====================================================
|
||||
|
||||
const int NetworkInterface::readyWaitTimeout= 60000; //1 minute
|
||||
|
||||
|
||||
void NetworkInterface::sendMessage(const NetworkMessage* networkMessage){
|
||||
Socket* socket= getSocket();
|
||||
|
||||
networkMessage->send(socket);
|
||||
}
|
||||
|
||||
NetworkMessageType NetworkInterface::getNextMessageType(){
|
||||
Socket* socket= getSocket();
|
||||
int8 messageType= nmtInvalid;
|
||||
|
||||
//peek message type
|
||||
if(socket->getDataToRead()>=sizeof(messageType)){
|
||||
socket->peek(&messageType, sizeof(messageType));
|
||||
}
|
||||
|
||||
//sanity check new message type
|
||||
if(messageType<0 || messageType>=nmtCount){
|
||||
throw runtime_error("Invalid message type: " + intToStr(messageType));
|
||||
}
|
||||
|
||||
return static_cast<NetworkMessageType>(messageType);
|
||||
}
|
||||
|
||||
bool NetworkInterface::receiveMessage(NetworkMessage* networkMessage){
|
||||
Socket* socket= getSocket();
|
||||
|
||||
return networkMessage->receive(socket);
|
||||
}
|
||||
|
||||
bool NetworkInterface::isConnected(){
|
||||
return getSocket()!=NULL && getSocket()->isConnected();
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class GameNetworkInterface
|
||||
// =====================================================
|
||||
|
||||
GameNetworkInterface::GameNetworkInterface(){
|
||||
quit= false;
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,100 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_NETWORKINTERFACE_H_
|
||||
#define _GLEST_GAME_NETWORKINTERFACE_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "checksum.h"
|
||||
#include "network_message.h"
|
||||
#include "network_types.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using Shared::Util::Checksum;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class NetworkInterface
|
||||
// =====================================================
|
||||
|
||||
class NetworkInterface{
|
||||
public:
|
||||
static const int readyWaitTimeout;
|
||||
|
||||
public:
|
||||
virtual ~NetworkInterface(){}
|
||||
|
||||
virtual Socket* getSocket()= 0;
|
||||
virtual const Socket* getSocket() const= 0;
|
||||
|
||||
string getIp() const {return getSocket()->getIp();}
|
||||
string getHostName() const {return getSocket()->getHostName();}
|
||||
|
||||
void sendMessage(const NetworkMessage* networkMessage);
|
||||
NetworkMessageType getNextMessageType();
|
||||
bool receiveMessage(NetworkMessage* networkMessage);
|
||||
|
||||
bool isConnected();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class GameNetworkInterface
|
||||
//
|
||||
// Adds functions common to servers and clients
|
||||
// but not connection slots
|
||||
// =====================================================
|
||||
|
||||
class GameNetworkInterface: public NetworkInterface{
|
||||
private:
|
||||
typedef vector<NetworkCommand> Commands;
|
||||
|
||||
protected:
|
||||
Commands requestedCommands; //commands requested by the user
|
||||
Commands pendingCommands; //commands ready to be given
|
||||
bool quit;
|
||||
string chatText;
|
||||
string chatSender;
|
||||
int chatTeamIndex;
|
||||
|
||||
public:
|
||||
GameNetworkInterface();
|
||||
|
||||
//message processimg
|
||||
virtual void update()= 0;
|
||||
virtual void updateLobby()= 0;
|
||||
virtual void updateKeyframe(int frameCount)= 0;
|
||||
virtual void waitUntilReady(Checksum* checksum)= 0;
|
||||
|
||||
//message sending
|
||||
virtual void sendTextMessage(const string &text, int teamIndex)= 0;
|
||||
virtual void quitGame()=0;
|
||||
|
||||
//misc
|
||||
virtual string getNetworkStatus() const= 0;
|
||||
|
||||
//access functions
|
||||
void requestCommand(const NetworkCommand *networkCommand) {requestedCommands.push_back(*networkCommand);}
|
||||
int getPendingCommandCount() const {return pendingCommands.size();}
|
||||
const NetworkCommand* getPendingCommand(int i) const {return &pendingCommands[i];}
|
||||
void clearPendingCommands() {pendingCommands.clear();}
|
||||
bool getQuit() const {return quit;}
|
||||
const string getChatText() const {return chatText;}
|
||||
const string getChatSender() const {return chatSender;}
|
||||
int getChatTeamIndex() const {return chatTeamIndex;}
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,78 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "network_manager.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class NetworkManager
|
||||
// =====================================================
|
||||
|
||||
NetworkManager &NetworkManager::getInstance(){
|
||||
static NetworkManager networkManager;
|
||||
return networkManager;
|
||||
}
|
||||
|
||||
NetworkManager::NetworkManager(){
|
||||
gameNetworkInterface= NULL;
|
||||
networkRole= nrIdle;
|
||||
}
|
||||
|
||||
void NetworkManager::init(NetworkRole networkRole)
|
||||
{
|
||||
assert(gameNetworkInterface==NULL);
|
||||
|
||||
this->networkRole = networkRole;
|
||||
|
||||
if(networkRole==nrServer){
|
||||
gameNetworkInterface = new ServerInterface();
|
||||
}
|
||||
else
|
||||
{
|
||||
gameNetworkInterface = new ClientInterface();
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkManager::end(){
|
||||
delete gameNetworkInterface;
|
||||
gameNetworkInterface= NULL;
|
||||
networkRole= nrIdle;
|
||||
}
|
||||
|
||||
void NetworkManager::update(){
|
||||
if(gameNetworkInterface!=NULL){
|
||||
gameNetworkInterface->update();
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkManager::isNetworkGame(){
|
||||
return networkRole==nrClient || getServerInterface()->getConnectedSlotCount()>0;
|
||||
}
|
||||
|
||||
GameNetworkInterface* NetworkManager::getGameNetworkInterface(){
|
||||
assert(gameNetworkInterface!=NULL);
|
||||
return gameNetworkInterface;
|
||||
}
|
||||
|
||||
ServerInterface* NetworkManager::getServerInterface(){
|
||||
assert(gameNetworkInterface!=NULL);
|
||||
assert(networkRole==nrServer);
|
||||
return static_cast<ServerInterface*>(gameNetworkInterface);
|
||||
}
|
||||
|
||||
ClientInterface* NetworkManager::getClientInterface(){
|
||||
assert(gameNetworkInterface!=NULL);
|
||||
assert(networkRole==nrClient);
|
||||
return static_cast<ClientInterface*>(gameNetworkInterface);
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,57 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_NETWORKMANAGER_H_
|
||||
#define _GLEST_GAME_NETWORKMANAGER_H_
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "socket.h"
|
||||
#include "checksum.h"
|
||||
#include "server_interface.h"
|
||||
#include "client_interface.h"
|
||||
|
||||
using Shared::Util::Checksum;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class NetworkManager
|
||||
// =====================================================
|
||||
|
||||
enum NetworkRole{
|
||||
nrServer,
|
||||
nrClient,
|
||||
nrIdle
|
||||
};
|
||||
|
||||
class NetworkManager{
|
||||
private:
|
||||
GameNetworkInterface* gameNetworkInterface;
|
||||
NetworkRole networkRole;
|
||||
|
||||
public:
|
||||
static NetworkManager &getInstance();
|
||||
|
||||
NetworkManager();
|
||||
void init(NetworkRole networkRole);
|
||||
void end();
|
||||
void update();
|
||||
|
||||
bool isNetworkGame();
|
||||
GameNetworkInterface* getGameNetworkInterface();
|
||||
ServerInterface* getServerInterface();
|
||||
ClientInterface* getClientInterface();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,218 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "network_message.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
#include "game_settings.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessage
|
||||
// =====================================================
|
||||
|
||||
bool NetworkMessage::receive(Socket* socket, void* data, int dataSize){
|
||||
if(socket->getDataToRead()>=dataSize){
|
||||
if(socket->receive(data, dataSize)!=dataSize){
|
||||
throw runtime_error("Error receiving NetworkMessage");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const{
|
||||
if(socket->send(data, dataSize)!=dataSize){
|
||||
throw runtime_error("Error sending NetworkMessage");
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageIntro
|
||||
// =====================================================
|
||||
|
||||
NetworkMessageIntro::NetworkMessageIntro(){
|
||||
data.messageType= -1;
|
||||
data.playerIndex= -1;
|
||||
}
|
||||
|
||||
NetworkMessageIntro::NetworkMessageIntro(const string &versionString, const string &name, int playerIndex){
|
||||
data.messageType=nmtIntro;
|
||||
data.versionString= versionString;
|
||||
data.name= name;
|
||||
data.playerIndex= static_cast<int16>(playerIndex);
|
||||
}
|
||||
|
||||
bool NetworkMessageIntro::receive(Socket* socket){
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void NetworkMessageIntro::send(Socket* socket) const{
|
||||
assert(data.messageType==nmtIntro);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageReady
|
||||
// =====================================================
|
||||
|
||||
NetworkMessageReady::NetworkMessageReady(){
|
||||
data.messageType= nmtReady;
|
||||
}
|
||||
|
||||
NetworkMessageReady::NetworkMessageReady(int32 checksum){
|
||||
data.messageType= nmtReady;
|
||||
data.checksum= checksum;
|
||||
}
|
||||
|
||||
bool NetworkMessageReady::receive(Socket* socket){
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void NetworkMessageReady::send(Socket* socket) const{
|
||||
assert(data.messageType==nmtReady);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageLaunch
|
||||
// =====================================================
|
||||
|
||||
NetworkMessageLaunch::NetworkMessageLaunch(){
|
||||
data.messageType=-1;
|
||||
}
|
||||
|
||||
NetworkMessageLaunch::NetworkMessageLaunch(const GameSettings *gameSettings){
|
||||
data.messageType=nmtLaunch;
|
||||
|
||||
data.description= gameSettings->getDescription();
|
||||
data.map= gameSettings->getMap();
|
||||
data.tileset= gameSettings->getTileset();
|
||||
data.tech= gameSettings->getTech();
|
||||
data.factionCount= gameSettings->getFactionCount();
|
||||
data.thisFactionIndex= gameSettings->getThisFactionIndex();
|
||||
data.defaultResources= gameSettings->getDefaultResources();
|
||||
data.defaultUnits= gameSettings->getDefaultUnits();
|
||||
data.defaultVictoryConditions= gameSettings->getDefaultVictoryConditions();
|
||||
|
||||
for(int i= 0; i<data.factionCount; ++i){
|
||||
data.factionTypeNames[i]= gameSettings->getFactionTypeName(i);
|
||||
data.factionControls[i]= gameSettings->getFactionControl(i);
|
||||
data.teams[i]= gameSettings->getTeam(i);
|
||||
data.startLocationIndex[i]= gameSettings->getStartLocationIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMessageLaunch::buildGameSettings(GameSettings *gameSettings) const{
|
||||
gameSettings->setDescription(data.description.getString());
|
||||
gameSettings->setMap(data.map.getString());
|
||||
gameSettings->setTileset(data.tileset.getString());
|
||||
gameSettings->setTech(data.tech.getString());
|
||||
gameSettings->setFactionCount(data.factionCount);
|
||||
gameSettings->setThisFactionIndex(data.thisFactionIndex);
|
||||
gameSettings->setDefaultResources(data.defaultResources);
|
||||
gameSettings->setDefaultUnits(data.defaultUnits);
|
||||
gameSettings->setDefaultVictoryConditions(data.defaultVictoryConditions);
|
||||
|
||||
for(int i= 0; i<data.factionCount; ++i){
|
||||
gameSettings->setFactionTypeName(i, data.factionTypeNames[i].getString());
|
||||
gameSettings->setFactionControl(i, static_cast<ControlType>(data.factionControls[i]));
|
||||
gameSettings->setTeam(i, data.teams[i]);
|
||||
gameSettings->setStartLocationIndex(i, data.startLocationIndex[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkMessageLaunch::receive(Socket* socket){
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void NetworkMessageLaunch::send(Socket* socket) const{
|
||||
assert(data.messageType==nmtLaunch);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageLaunch
|
||||
// =====================================================
|
||||
|
||||
NetworkMessageCommandList::NetworkMessageCommandList(int32 frameCount){
|
||||
data.messageType= nmtCommandList;
|
||||
data.frameCount= frameCount;
|
||||
data.commandCount= 0;
|
||||
}
|
||||
|
||||
bool NetworkMessageCommandList::addCommand(const NetworkCommand* networkCommand){
|
||||
if(data.commandCount<maxCommandCount){
|
||||
data.commands[static_cast<int>(data.commandCount)]= *networkCommand;
|
||||
data.commandCount++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetworkMessageCommandList::receive(Socket* socket){
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void NetworkMessageCommandList::send(Socket* socket) const{
|
||||
assert(data.messageType==nmtCommandList);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageText
|
||||
// =====================================================
|
||||
|
||||
NetworkMessageText::NetworkMessageText(const string &text, const string &sender, int teamIndex){
|
||||
data.messageType= nmtText;
|
||||
data.text= text;
|
||||
data.sender= sender;
|
||||
data.teamIndex= teamIndex;
|
||||
}
|
||||
|
||||
bool NetworkMessageText::receive(Socket* socket){
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void NetworkMessageText::send(Socket* socket) const{
|
||||
assert(data.messageType==nmtText);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageQuit
|
||||
// =====================================================
|
||||
|
||||
NetworkMessageQuit::NetworkMessageQuit(){
|
||||
data.messageType= nmtQuit;
|
||||
}
|
||||
|
||||
bool NetworkMessageQuit::receive(Socket* socket){
|
||||
return NetworkMessage::receive(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void NetworkMessageQuit::send(Socket* socket) const{
|
||||
assert(data.messageType==nmtQuit);
|
||||
NetworkMessage::send(socket, &data, sizeof(data));
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,252 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_NETWORKMESSAGE_H_
|
||||
#define _GLEST_GAME_NETWORKMESSAGE_H_
|
||||
|
||||
#include "socket.h"
|
||||
#include "game_constants.h"
|
||||
#include "network_types.h"
|
||||
|
||||
using Shared::Platform::Socket;
|
||||
using Shared::Platform::int8;
|
||||
using Shared::Platform::int16;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class GameSettings;
|
||||
|
||||
enum NetworkMessageType{
|
||||
nmtInvalid,
|
||||
nmtIntro,
|
||||
nmtPing,
|
||||
nmtReady,
|
||||
nmtLaunch,
|
||||
nmtCommandList,
|
||||
nmtText,
|
||||
nmtQuit,
|
||||
|
||||
nmtCount
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessage
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessage{
|
||||
public:
|
||||
virtual ~NetworkMessage(){}
|
||||
virtual bool receive(Socket* socket)= 0;
|
||||
virtual void send(Socket* socket) const = 0;
|
||||
|
||||
protected:
|
||||
bool receive(Socket* socket, void* data, int dataSize);
|
||||
void send(Socket* socket, const void* data, int dataSize) const;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageIntro
|
||||
//
|
||||
// Message sent from the server to the client
|
||||
// when the client connects and vice versa
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessageIntro: public NetworkMessage{
|
||||
private:
|
||||
static const int maxVersionStringSize= 64;
|
||||
static const int maxNameSize= 16;
|
||||
|
||||
private:
|
||||
struct Data{
|
||||
int8 messageType;
|
||||
NetworkString<maxVersionStringSize> versionString;
|
||||
NetworkString<maxNameSize> name;
|
||||
int16 playerIndex;
|
||||
};
|
||||
|
||||
private:
|
||||
Data data;
|
||||
|
||||
public:
|
||||
NetworkMessageIntro();
|
||||
NetworkMessageIntro(const string &versionString, const string &name, int playerIndex);
|
||||
|
||||
string getVersionString() const {return data.versionString.getString();}
|
||||
string getName() const {return data.name.getString();}
|
||||
int getPlayerIndex() const {return data.playerIndex;}
|
||||
|
||||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageReady
|
||||
//
|
||||
// Message sent at the beggining of the game
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessageReady: public NetworkMessage{
|
||||
private:
|
||||
struct Data{
|
||||
int8 messageType;
|
||||
int32 checksum;
|
||||
};
|
||||
|
||||
private:
|
||||
Data data;
|
||||
|
||||
public:
|
||||
NetworkMessageReady();
|
||||
NetworkMessageReady(int32 checksum);
|
||||
|
||||
int32 getChecksum() const {return data.checksum;}
|
||||
|
||||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageLaunch
|
||||
//
|
||||
// Message sent from the server to the client
|
||||
// to launch the game
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessageLaunch: public NetworkMessage{
|
||||
private:
|
||||
static const int maxStringSize= 256;
|
||||
|
||||
private:
|
||||
struct Data{
|
||||
int8 messageType;
|
||||
NetworkString<maxStringSize> description;
|
||||
NetworkString<maxStringSize> map;
|
||||
NetworkString<maxStringSize> tileset;
|
||||
NetworkString<maxStringSize> tech;
|
||||
NetworkString<maxStringSize> factionTypeNames[GameConstants::maxPlayers]; //faction names
|
||||
|
||||
int8 factionControls[GameConstants::maxPlayers];
|
||||
|
||||
int8 thisFactionIndex;
|
||||
int8 factionCount;
|
||||
int8 teams[GameConstants::maxPlayers];
|
||||
int8 startLocationIndex[GameConstants::maxPlayers];
|
||||
int8 defaultResources;
|
||||
int8 defaultUnits;
|
||||
int8 defaultVictoryConditions;
|
||||
};
|
||||
|
||||
private:
|
||||
Data data;
|
||||
|
||||
public:
|
||||
NetworkMessageLaunch();
|
||||
NetworkMessageLaunch(const GameSettings *gameSettings);
|
||||
|
||||
void buildGameSettings(GameSettings *gameSettings) const;
|
||||
|
||||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class CommandList
|
||||
//
|
||||
// Message to order a commands to several units
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessageCommandList: public NetworkMessage{
|
||||
private:
|
||||
static const int maxCommandCount= 16*4;
|
||||
|
||||
private:
|
||||
struct Data{
|
||||
int8 messageType;
|
||||
int8 commandCount;
|
||||
int32 frameCount;
|
||||
NetworkCommand commands[maxCommandCount];
|
||||
};
|
||||
|
||||
private:
|
||||
Data data;
|
||||
|
||||
public:
|
||||
NetworkMessageCommandList(int32 frameCount= -1);
|
||||
|
||||
bool addCommand(const NetworkCommand* networkCommand);
|
||||
|
||||
void clear() {data.commandCount= 0;}
|
||||
int getCommandCount() const {return data.commandCount;}
|
||||
int getFrameCount() const {return data.frameCount;}
|
||||
const NetworkCommand* getCommand(int i) const {return &data.commands[i];}
|
||||
|
||||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageText
|
||||
//
|
||||
// Chat text message
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessageText: public NetworkMessage{
|
||||
private:
|
||||
static const int maxStringSize= 64;
|
||||
|
||||
private:
|
||||
struct Data{
|
||||
int8 messageType;
|
||||
NetworkString<maxStringSize> text;
|
||||
NetworkString<maxStringSize> sender;
|
||||
int8 teamIndex;
|
||||
};
|
||||
|
||||
private:
|
||||
Data data;
|
||||
|
||||
public:
|
||||
NetworkMessageText(){}
|
||||
NetworkMessageText(const string &text, const string &sender, int teamIndex);
|
||||
|
||||
string getText() const {return data.text.getString();}
|
||||
string getSender() const {return data.sender.getString();}
|
||||
int getTeamIndex() const {return data.teamIndex;}
|
||||
|
||||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkMessageQuit
|
||||
//
|
||||
// Message sent at the beggining of the game
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessageQuit: public NetworkMessage{
|
||||
private:
|
||||
struct Data{
|
||||
int8 messageType;
|
||||
};
|
||||
|
||||
private:
|
||||
Data data;
|
||||
|
||||
public:
|
||||
NetworkMessageQuit();
|
||||
|
||||
virtual bool receive(Socket* socket);
|
||||
virtual void send(Socket* socket) const;
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "network_types.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class NetworkCommand
|
||||
// =====================================================
|
||||
|
||||
NetworkCommand::NetworkCommand(int networkCommandType, int unitId, int commandTypeId, const Vec2i &pos, int unitTypeId, int targetId){
|
||||
this->networkCommandType= networkCommandType;
|
||||
this->unitId= unitId;
|
||||
this->commandTypeId= commandTypeId;
|
||||
this->positionX= pos.x;
|
||||
this->positionY= pos.y;
|
||||
this->unitTypeId= unitTypeId;
|
||||
this->targetId= targetId;
|
||||
}
|
||||
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,77 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_NETWORKTYPES_H_
|
||||
#define _GLEST_GAME_NETWORKTYPES_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "types.h"
|
||||
#include "vec.h"
|
||||
|
||||
using std::string;
|
||||
using Shared::Platform::int8;
|
||||
using Shared::Platform::int16;
|
||||
using Shared::Platform::int32;
|
||||
using Shared::Graphics::Vec2i;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class NetworkString
|
||||
// =====================================================
|
||||
|
||||
template<int S>
|
||||
class NetworkString{
|
||||
private:
|
||||
char buffer[S];
|
||||
|
||||
public:
|
||||
NetworkString() {memset(buffer, 0, S);}
|
||||
void operator=(const string& str) {strncpy(buffer, str.c_str(), S-1);}
|
||||
string getString() const {return buffer;}
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class NetworkCommand
|
||||
// =====================================================
|
||||
|
||||
enum NetworkCommandType{
|
||||
nctGiveCommand,
|
||||
nctCancelCommand,
|
||||
nctSetMeetingPoint
|
||||
};
|
||||
|
||||
class NetworkCommand{
|
||||
private:
|
||||
int16 networkCommandType;
|
||||
int16 unitId;
|
||||
int16 commandTypeId;
|
||||
int16 positionX;
|
||||
int16 positionY;
|
||||
int16 unitTypeId;
|
||||
int16 targetId;
|
||||
|
||||
public:
|
||||
NetworkCommand(){};
|
||||
NetworkCommand(int networkCommandType, int unitId, int commandTypeId= -1, const Vec2i &pos= Vec2i(0), int unitTypeId= -1, int targetId= -1);
|
||||
|
||||
NetworkCommandType getNetworkCommandType() const {return static_cast<NetworkCommandType>(networkCommandType);}
|
||||
int getUnitId() const {return unitId;}
|
||||
int getCommandTypeId() const {return commandTypeId;}
|
||||
Vec2i getPosition() const {return Vec2i(positionX, positionY);}
|
||||
int getUnitTypeId() const {return unitTypeId;}
|
||||
int getTargetId() const {return targetId;}
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,244 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#include "server_interface.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "platform_util.h"
|
||||
#include "conversion.h"
|
||||
#include "config.h"
|
||||
#include "lang.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class ServerInterface
|
||||
// =====================================================
|
||||
|
||||
ServerInterface::ServerInterface(){
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
slots[i]= NULL;
|
||||
}
|
||||
serverSocket.setBlock(false);
|
||||
serverSocket.bind(GameConstants::serverPort);
|
||||
}
|
||||
|
||||
ServerInterface::~ServerInterface(){
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
delete slots[i];
|
||||
}
|
||||
}
|
||||
|
||||
void ServerInterface::addSlot(int playerIndex){
|
||||
assert(playerIndex>=0 && playerIndex<GameConstants::maxPlayers);
|
||||
|
||||
delete slots[playerIndex];
|
||||
slots[playerIndex]= new ConnectionSlot(this, playerIndex);
|
||||
updateListen();
|
||||
}
|
||||
|
||||
void ServerInterface::removeSlot(int playerIndex){
|
||||
delete slots[playerIndex];
|
||||
slots[playerIndex]= NULL;
|
||||
updateListen();
|
||||
}
|
||||
|
||||
ConnectionSlot* ServerInterface::getSlot(int playerIndex){
|
||||
return slots[playerIndex];
|
||||
}
|
||||
|
||||
int ServerInterface::getConnectedSlotCount(){
|
||||
int connectedSlotCount= 0;
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
if(slots[i]!= NULL){
|
||||
++connectedSlotCount;
|
||||
}
|
||||
}
|
||||
return connectedSlotCount;
|
||||
}
|
||||
|
||||
void ServerInterface::update(){
|
||||
|
||||
//update all slots
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
if(slots[i]!= NULL){
|
||||
slots[i]->update();
|
||||
}
|
||||
}
|
||||
|
||||
//process text messages
|
||||
chatText.clear();
|
||||
chatSender.clear();
|
||||
chatTeamIndex= -1;
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
|
||||
if(connectionSlot!= NULL){
|
||||
if(connectionSlot->isConnected()){
|
||||
if(connectionSlot->getNextMessageType()==nmtText){
|
||||
NetworkMessageText networkMessageText;
|
||||
if(connectionSlot->receiveMessage(&networkMessageText)){
|
||||
broadcastMessage(&networkMessageText, i);
|
||||
chatText= networkMessageText.getText();
|
||||
chatSender= networkMessageText.getSender();
|
||||
chatTeamIndex= networkMessageText.getTeamIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerInterface::updateKeyframe(int frameCount){
|
||||
|
||||
NetworkMessageCommandList networkMessageCommandList(frameCount);
|
||||
|
||||
//build command list, remove commands from requested and add to pending
|
||||
while(!requestedCommands.empty()){
|
||||
if(networkMessageCommandList.addCommand(&requestedCommands.back())){
|
||||
pendingCommands.push_back(requestedCommands.back());
|
||||
requestedCommands.pop_back();
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//broadcast commands
|
||||
broadcastMessage(&networkMessageCommandList);
|
||||
}
|
||||
|
||||
void ServerInterface::waitUntilReady(Checksum* checksum){
|
||||
|
||||
Chrono chrono;
|
||||
bool allReady= false;
|
||||
|
||||
chrono.start();
|
||||
|
||||
//wait until we get a ready message from all clients
|
||||
while(!allReady){
|
||||
|
||||
allReady= true;
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
|
||||
if(connectionSlot!=NULL){
|
||||
if(!connectionSlot->isReady()){
|
||||
NetworkMessageType networkMessageType= connectionSlot->getNextMessageType();
|
||||
NetworkMessageReady networkMessageReady;
|
||||
|
||||
if(networkMessageType==nmtReady && connectionSlot->receiveMessage(&networkMessageReady)){
|
||||
connectionSlot->setReady();
|
||||
}
|
||||
else if(networkMessageType!=nmtInvalid){
|
||||
throw runtime_error("Unexpected network message: " + intToStr(networkMessageType));
|
||||
}
|
||||
|
||||
allReady= false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check for timeout
|
||||
if(chrono.getMillis()>readyWaitTimeout){
|
||||
throw runtime_error("Timeout waiting for clients");
|
||||
}
|
||||
}
|
||||
|
||||
//send ready message after, so clients start delayed
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
NetworkMessageReady networkMessageReady(checksum->getSum());
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
|
||||
if(connectionSlot!=NULL){
|
||||
connectionSlot->sendMessage(&networkMessageReady);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerInterface::sendTextMessage(const string &text, int teamIndex){
|
||||
NetworkMessageText networkMessageText(text, getHostName(), teamIndex);
|
||||
broadcastMessage(&networkMessageText);
|
||||
}
|
||||
|
||||
void ServerInterface::quitGame(){
|
||||
NetworkMessageQuit networkMessageQuit;
|
||||
broadcastMessage(&networkMessageQuit);
|
||||
}
|
||||
|
||||
string ServerInterface::getNetworkStatus() const{
|
||||
Lang &lang= Lang::getInstance();
|
||||
string str;
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
|
||||
str+= intToStr(i)+ ": ";
|
||||
|
||||
if(connectionSlot!= NULL){
|
||||
if(connectionSlot->isConnected()){
|
||||
str+= connectionSlot->getName();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
str+= lang.get("NotConnected");
|
||||
}
|
||||
|
||||
str+= '\n';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void ServerInterface::launchGame(const GameSettings* gameSettings){
|
||||
NetworkMessageLaunch networkMessageLaunch(gameSettings);
|
||||
broadcastMessage(&networkMessageLaunch);
|
||||
}
|
||||
|
||||
void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot){
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
|
||||
if(i!= excludeSlot && connectionSlot!= NULL){
|
||||
if(connectionSlot->isConnected()){
|
||||
connectionSlot->sendMessage(networkMessage);
|
||||
}
|
||||
else{
|
||||
removeSlot(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerInterface::updateListen(){
|
||||
int openSlotCount= 0;
|
||||
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||
if(slots[i]!= NULL && !slots[i]->isConnected()){
|
||||
++openSlotCount;
|
||||
}
|
||||
}
|
||||
|
||||
serverSocket.listen(openSlotCount);
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,71 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _GLEST_GAME_SERVERINTERFACE_H_
|
||||
#define _GLEST_GAME_SERVERINTERFACE_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "game_constants.h"
|
||||
#include "network_interface.h"
|
||||
#include "connection_slot.h"
|
||||
#include "socket.h"
|
||||
|
||||
using std::vector;
|
||||
using Shared::Platform::ServerSocket;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class ServerInterface
|
||||
// =====================================================
|
||||
|
||||
class ServerInterface: public GameNetworkInterface{
|
||||
private:
|
||||
ConnectionSlot* slots[GameConstants::maxPlayers];
|
||||
ServerSocket serverSocket;
|
||||
|
||||
public:
|
||||
ServerInterface();
|
||||
virtual ~ServerInterface();
|
||||
|
||||
virtual Socket* getSocket() {return &serverSocket;}
|
||||
virtual const Socket* getSocket() const {return &serverSocket;}
|
||||
|
||||
//message processing
|
||||
virtual void update();
|
||||
virtual void updateLobby(){};
|
||||
virtual void updateKeyframe(int frameCount);
|
||||
virtual void waitUntilReady(Checksum* checksum);
|
||||
|
||||
// message sending
|
||||
virtual void sendTextMessage(const string &text, int teamIndex);
|
||||
virtual void quitGame();
|
||||
|
||||
//misc
|
||||
virtual string getNetworkStatus() const;
|
||||
|
||||
ServerSocket* getServerSocket() {return &serverSocket;}
|
||||
void addSlot(int playerIndex);
|
||||
void removeSlot(int playerIndex);
|
||||
ConnectionSlot* getSlot(int playerIndex);
|
||||
int getConnectedSlotCount();
|
||||
|
||||
void launchGame(const GameSettings* gameSettings);
|
||||
|
||||
private:
|
||||
void broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot= -1);
|
||||
void updateListen();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue