|
27.06.2009, 23:00
|
#1
|
Терабайт исходников
Регистрация: 13.09.2008
Сообщений: 3,947
Написано 2,189 полезных сообщений (для 6,051 пользователей)
|
Хитрая хитрость
итак, задача:
есть несколько классов.
допустим,
class human
{
int x,y,z, height, width;
};
class car
{
int x,y,z,speed;
};
нам нужно задавать внутренние значения для разных объектов разных классов, но имея лишь условный номер значения в объекте класса и
само значение. для примера я сделал что все значения всех классов - int.
т.е. пример условия: 2, 40
где 2 - номер значения (Y для обоих классов), а 40 - само значение, т.е. будь объект хоть car хоть human, в нём Y выставится в 40.
я предположил что надо сделать
массив, имеющийся в объекте каждого класса
который содержит указатели
на все значения (блин ну field'ы короче если говорить по блицевски)
мы сами суём в него указатели на филды при создании объекта в конструкторе класса.
в общем,
не мог бы кто реализовать такой пример, чтоб в результате это можно было уместить в одну функцию типа SetValue(num,value) для этих двух классов которые я привёл?
я довольно запутался... помню что если класс находится в иерархии другого класса, то мы можем из объектов дочерних классов получать объекты класса родителя, т.е. универсальные, это вроде ещё полиморфизм зовётся. думаю этот массив должен быть как раз в родительском...
|
(Offline)
|
|
27.06.2009, 23:23
|
#2
|
|
Ответ: Хитрая хитрость
эх
class position
{
public:
int x,y,z;
};
class human:public position
{
public:
int height, width;
};
class car:public position
{
public:
int speed;
};
void setposition(position * obj)
{
obj->x = 1;
}
...
human * lol1 = new human;
setposition(lol1);
delete lol1;
car * lol2 = new car;
setposition(lol2);
delete lol2;
...
если ты хочешь назначать переменную по номеру то это можно, но является жудким говнокодом
ps. я делал бы так
class CVector3d
{
...
};
class CNode
{
protected:
CVector3d Position;
CVector3d Rotation;
CVector3d Scale;
...
public:
...
};
class CCar:public CNode
{
...
};
class CHuman:public CHuman
{
...
};
|
|
|
Сообщение было полезно следующим пользователям:
|
|
27.06.2009, 23:34
|
#3
|
Знающий
Регистрация: 02.11.2007
Сообщений: 255
Написано 27 полезных сообщений (для 43 пользователей)
|
Ответ: Хитрая хитрость
Сообщение от jimon
эх
class position
{
public:
int x,y,z;
};
class human:public position
{
public:
int height, width;
};
class car:public position
{
public:
int speed;
};
void setposition(position * obj)
{
obj->x = 1;
}
...
human * lol1 = new human;
setposition(lol1);
delete lol1;
car * lol2 = new car;
setposition(lol2);
delete lol2;
...
если ты хочешь назначать переменную по номеру то это можно, но является жудким говнокодом
|
Я бы вообще сделал так:
class Car;
class Human;
class GameObject
{
public:
float x,y,z,pitch,yaw,roll;
bool alive;
bool isAlive() { return alive; }
Car* getCar(){return 0;}
Human* getHuman(){return 0;}
virtual void setPosition(float _x,float _y,float _z){ x=_x;y=_y;z=_z; }
virtual void setOrientation(float _pitch,float _yaw,float _roll){ pitch=_pitch;yaw=_yaw;roll=_roll;}
virtual void update(){}
};
class Car : public GameObject
{
public:
Car* getCar(){return this;}
void setPosition(float x,float y,float z)
{
GameObject::setPosition(x,y,z);
....
}
void setOrientation(float pitch,float yaw,float roll)
{
GameObject::setOrientation(pitch,yaw,roll);
...
}
void update()
{
car physic update...
}
};
class Human : public GameObject
{
public:
Human* getHuman(){return this;}
void setPosition(float x,float y,float z)
{
GameObject::setPosition(x,y,z);
....
}
void setOrientation(float pitch,float yaw,float roll)
{
GameObject::setOrientation(pitch,yaw,roll);
...
}
void update()
{
if(health <= 0)alive=false;
}
};
class CarDriver : public Human
{
....
};
GameObject* car = new Car();
GameObject* human = new Humman();
if(car->getCar() != 0)car->setPosition(40,10,0);
if(human->getHuman() != 0)human->setPosition(40,15,0);
А вообще я не совсем понял вопрос.
|
(Offline)
|
|
27.06.2009, 23:38
|
#4
|
|
Ответ: Хитрая хитрость
Genius
Car* getCar(){return 0;}
Human* getHuman(){return 0;}
|
самый большой говнокод в ООП ! это хуже чем тупо модифицировать класс через смещение в указателях
я за такое тебя бы уволил бы без разбирательств
|
|
|
27.06.2009, 23:43
|
#5
|
Знающий
Регистрация: 02.11.2007
Сообщений: 255
Написано 27 полезных сообщений (для 43 пользователей)
|
Ответ: Хитрая хитрость
Сообщение от jimon
Genius
самый большой говнокод в ООП ! это хуже чем тупо модифицировать класс через смещение в указателях
я за такое тебя бы уволил бы без разбирательств
|
Не бузи мне тут как бабка на базаре,ты делаеш так как тебе удобнее а я предпочитаю делать так как мне удобнее,и мне будет удобнее при переборе 100 объектов функции getCar узнать какие из них есть Car...
З.Ы. Я не говорю что твой код дерьмо,я вырозил своё мнение.
|
(Offline)
|
|
27.06.2009, 23:52
|
#6
|
Терабайт исходников
Регистрация: 13.09.2008
Сообщений: 3,947
Написано 2,189 полезных сообщений (для 6,051 пользователей)
|
Ответ: Хитрая хитрость
не, xyz у меня тут случайно совпали, в реале могут быть абсолютно разные штуки там)
говнокод тоже не хочется
Гениус чето совсем не по теме вроде.
посоветовали мне тут уже два человека юзать Vector.
запихну его в родительский класс и попробую)
|
(Offline)
|
|
27.06.2009, 23:56
|
#7
|
|
Ответ: Хитрая хитрость
Genius
о static_cast слышал ?
если уж у тебя так получилось (кривая архитектура или что-то еще) то можно и dynamic_cast использовать
Mr_F_
просто представь что у тебя нету понятия индекс переменной, компилятор переменную которая у тебя написана второй может сделать первой или третей
программируй так чтобы тебе индекс переменной был не нужен
|
|
|
27.06.2009, 23:58
|
#8
|
Знающий
Регистрация: 02.11.2007
Сообщений: 255
Написано 27 полезных сообщений (для 43 пользователей)
|
Вот ещё немного расширил:
class Car;
class Human;
static std::vector<GameObject*> gameWorld;
void insertGameObject( GameObject* object )
{
gameWorld.push_back(object);
}
class GameObject
{
public:
float x,y,z,pitch,yaw,roll;
bool alive;
GameObject(){ insertGameObject(this); }
virtual ~GameObject(){}
bool isAlive() { return alive; }
Car* getCar(){return 0;}
Human* getHuman(){return 0;}
virtual void setPosition(float _x,float _y,float _z){ x=_x;y=_y;z=_z; }
virtual void setOrientation(float _pitch,float _yaw,float _roll){ pitch=_pitch;yaw=_yaw;roll=_roll;}
virtual void update(float ifps){}
};
class Car : public GameObject
{
public:
int model;
float max_speed;
Car()
{
max_speed=0;
}
virtual ~Car()
{
xFreeEntity(model);
}
Car* getCar(){return this;}
void setPosition(float x,float y,float z)
{
GameObject::setPosition(x,y,z);
....
}
void setOrientation(float pitch,float yaw,float roll)
{
GameObject::setOrientation(pitch,yaw,roll);
...
}
void update()
{
car physic update...
}
};
class Human : public GameObject
{
public:
int health;
int model;
Human()
{
model = xLoadAnimMesh("human.b3d");
health=100;
}
~Human()
{
xFreeEntity(model);
}
Human* getHuman(){return this;}
void setPosition(float x,float y,float z)
{
GameObject::setPosition(x,y,z);
....
}
void setOrientation(float pitch,float yaw,float roll)
{
GameObject::setOrientation(pitch,yaw,roll);
...
}
void update(float ifps)
{
if(health <= 0)alive=false;
}
};
class CarDriver : public Human
{
....
};
void updateGameWorld(float ifps)
{
for(unsigned int i = 0; i < gameWorld.size(); i++)
{
GameObject* obj = gameWorld[i];
if(obj->isAlive())
{
obj->update(ifps);
}
}
}
....
GameObject* car = new Car();
GameObject* human = new Humman();
if(car->getCar() != 0)car->setPosition(40,10,0);
if(human->getHuman() != 0)human->setPosition(40,15,0);
while(!xKeyDown(1))
{
....
updateGameWorld(deltaTime);
xUpdateWorld(deltaTime);
xRenderWorld();
}
Сообщение от Mr_F_
не, xyz у меня тут случайно совпали, в реале могут быть абсолютно разные штуки там)
говнокод тоже не хочется
Гениус чето совсем не по теме вроде.
посоветовали мне тут уже два человека юзать Vector.
запихну его в родительский класс и попробую)
|
А что мешает юзать Вектор,так даже удобнее,я просто изначально по твоему посту сделал xyz.
А вообще тогда бы было что-то типа
void Car::setPosition(const Vector& pos)
{
position = pos;
бла бла бла,ставим тело в позицию...
А вообще невижу смысла сохранять позицию так как есть же фунекции типа xPositionEntity,pxBodyPosition,xEntityX,pxBodyPosi tionX,etc.
}
Вот те многофункциональный 3D Вектор
Последний раз редактировалось Genius, 28.06.2009 в 00:09.
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
28.06.2009, 00:05
|
#9
|
Бывалый
Регистрация: 04.01.2008
Адрес: Казахстан \ Талдыкорган
Сообщений: 659
Написано 170 полезных сообщений (для 509 пользователей)
|
Ответ: Хитрая хитрость
В серьёз не воспринемай =), да и пожалуй так не делай )))
struct XYZ{ float x,y,z;};
struct c1{
char buffer[12]; // sizeof( xyz )
// ...
};
void main(){
// Тут типа наш вектор
XYZ mx;
//Тут классик
c1 c;
// А вот так мы передаём данные вектора
memcpu( &c, (void*)&mx, sizeof( XYZ );
}
__________________
Жизнь как говориться игра- делать игры моя профессия(с)
Программирование, это религия! Её нужно исповедовать.
|
(Offline)
|
|
28.06.2009, 01:46
|
#10
|
Бывалый
Регистрация: 09.09.2006
Сообщений: 656
Написано 54 полезных сообщений (для 110 пользователей)
|
Ответ: Хитрая хитрость
Извuниете что я тут со своим мылом. у меня вопрос к Гениус)
нах так писать?
class A
{
B* GetB()..
C* GetC()..
};
class B :pub A{...};
class C :pub A{...};
А если еще надо детишек от А то это ты там будеш еще методы Get писать?
я конечно нубокодер)
но мне кажется на худой конец можно просто в родителя добавить переменную тип
а у детей типы разные писать )
|
(Offline)
|
|
28.06.2009, 02:03
|
#11
|
Знающий
Регистрация: 02.11.2007
Сообщений: 255
Написано 27 полезных сообщений (для 43 пользователей)
|
Ответ: Хитрая хитрость
Сообщение от Horror
Извuниете что я тут со своим мылом. у меня вопрос к Гениус)
нах так писать?
class A
{
B* GetB()..
C* GetC()..
};
class B :pub A{...};
class C :pub A{...};
А если еще надо детишек от А то это ты там будеш еще методы Get писать?
я конечно нубокодер)
но мне кажется на худой конец можно просто в родителя добавить переменную тип
а у детей типы разные писать )
|
Да буду добавлять,так-как это делается для проверки,откуда ты знаеш что GameObject* car - является классом Car? Эти Get'ы тоже самое что в блице делать проверку EntityClass(ent) == "Mesh"... Только удобнее.
Я не говорю что это униврсальный способ,и для игры где претпологается динамическое добавления новых типов игровых объектов,через скрипт,ini,и т.д он точно не подходит,а вот если все игровые объекты буду описаны кодом то это вполне удобное решение.
Последний раз редактировалось Genius, 28.06.2009 в 02:16.
|
(Offline)
|
|
28.06.2009, 03:21
|
#12
|
Терабайт исходников
Регистрация: 13.09.2008
Сообщений: 3,947
Написано 2,189 полезных сообщений (для 6,051 пользователей)
|
Ответ: Хитрая хитрость
просто представь что у тебя нету понятия индекс переменной, компилятор переменную которая у тебя написана второй может сделать первой или третей
программируй так чтобы тебе индекс переменной был не нужен
|
а где интересно было понятие индекс переменной?) конечно его нигде нет, я пишу:
мы сами суём в него указатели на филды при создании объекта в конструкторе класса.
|
т.е. в нужной последовательности.
ща объясню зачем всё надо)
у меня есть свой формат файла (левел). раньше он состоял из готовых блоков с четко заданой последовательностю и структурой. но потом я стал запариваться, когда нужно было ввести какой то новый параметр в один из видов объектов, или вообще новый вид объекта. старый загрузчик сбивался и грузил черти что, надо было аккуратно менять сначала только сохранение, потом пересохранять все имеющиеся карты, затем менять лоад и тогда только радоваться).
я решил сделать формат файла как бы параметр-driven. аналогичное наблюдается в формате FBX. структура такова:
объект
{
номер значения
значение
}
"номер значения-значение" конечно может быть много, до 255.
их структура выглядит так:
B номер значения
B тип данных
сами данные
(B - байт, тип данных от 1 до 5, соотв от байта до стринга).
а заголовок "объекта" представляет собой:
B тип объекта (номер класса, тут проверяем просто ифом, их немного)
L кол-во впереди идущих параметров со значениями
и в общем вот. я согласен конечно вручную указывать какой ячейке массива какое значение в объекте класса принадлежит, другое дело что я банально запутался во всей этой хитрости с кучей указателей на указатели и полиморфизмом)
вышеуказанный стиль формата файла имхо может весьма сократить расход нервов и сделать вполне совместимыми файлы разных версий (не хватает инфы? игнорим!)
|
(Offline)
|
|
28.06.2009, 03:55
|
#13
|
Знающий
Регистрация: 02.11.2007
Сообщений: 255
Написано 27 полезных сообщений (для 43 пользователей)
|
Ответ: Хитрая хитрость
Ёпть так надо было сразу с этого начинать...
Я бы так делал:
Мы уже имеем объекты:
представим что у нас в объекте есть массив так называемых Value,Value имеет 2 переменые 1) int,индификатор типа данных которые содержатся в Value и данные void*,
struct Value
{
enum{
INT=1,
FLOAT,
BOOL,
STRING
};
char type;
void* data;
void setInt(int v)
{
type = INT;
data = &v;
}
void setFloat(flaot v)
{
type = FLOAT;
data = &v;
}
void setBool(bool v)
{
type = BOOL;
data= &v;
}
void setString(char* str)
{
type = STRING;
data=str;
}
int toInt()
{
return *static_cast<int*>(data);
}
float toFloat()
{
return *static_cast<float*>(data);
}
bool toBool()
{
return *static_cast<bool*>(data);
}
char* toString()
{
return static_cast<char*>(data);
}
bool isINT()
{
return type == INT;
}
bool isFLOAT()
{
return type == FLOAT;
}
bool isBOOL()
{
return type == BOOL;
}
bool isSTRING()
{
return type == INT;
}
};
struct Object
{
char id; // индификатор 0-225
std::vector<Value> values;
};
пишем в файл кол-во объжектов
for(int i=0;i<count_objects;i++)
{
Object* obj = objects[i];
пишем в файл char - obj->id;
пишем в файл int - obj->values.size(); - кол-во value'ев
for(int k=0;k<obj->values.size();k++)
{
Value val = obj->values[k];
пишем char val->type; - тип value
switch(val->type)
{
case Value::INT:
{
пишем int - val->getInt();
}break;
case Value::FLOAT:
{
пишем float - val->getFloat();
}break;
case Value::BOOL:
{
пишем bool - val->getBool();
}break;
case Value::STRING:
{
пишем char* - val->getString();
}break;
}
}
}
Загрузка аналагично записи.
Еесли будет не понятно могу и пример загрузки этого чуда написать..
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
28.06.2009, 04:41
|
#14
|
Терабайт исходников
Регистрация: 13.09.2008
Сообщений: 3,947
Написано 2,189 полезных сообщений (для 6,051 пользователей)
|
Ответ: Хитрая хитрость
спасибо всем!
вроде тут сам успел допереть как то)
сделал так:
родительский класс:
class access
{
public:
int **ivec;
bool **bvec;
float **fvec;
string **svec;
};
дочерний (начало):
class material:public access{
private:
float alpha, brightness, contrast,...
конструктор дочернего класса (Начало):
(биндим к массиву содержимое объекта класса))
material::material()
{
svec = new (string*[3]);
fvec = new (float*[16]);
bvec = new (bool*[25]);
fvec[0]=α
fvec[1]=&brightness;
fvec[2]=&contrast;
загрузка:
access *Temp;
while (!myfile.eof())
{
objtype=readbyte(&myfile);
if (objtype==1) {
material *mat=new material; tempname="materials"; time=int(clock());
Temp = mat;
}
params=readlong(&myfile);
for(p=0;p<params;p++)
{
paramnum=readbyte(&myfile);
paramlen=readbyte(&myfile);
if (paramlen==1) *(Temp->bvec[paramnum-1])=bool(readbyte(&myfile));
if (paramlen==2) *(Temp->ivec[paramnum-1])=(readshort(&myfile));
if (paramlen==3) *(Temp->ivec[paramnum-1])=(readlong(&myfile));
if (paramlen==4) *(Temp->fvec[paramnum-1])=(readfloat(&myfile));
if (paramlen==5) *(Temp->svec[paramnum-1])=(readstringf(&myfile));
}
time=int(clock())-time;
cout << tempname << " loaded in " << time << "ms." << endl;
}
}
|
(Offline)
|
|
28.06.2009, 11:38
|
#15
|
|
Ответ: Хитрая хитрость
Mr_F_
я сделал проще немного, у меня в файле содержится имя переменной и её значение
в программе где нужно я просто получаю значение по имени
таким образом если переменной не было то вернётся default значение
|
|
|
Сообщение было полезно следующим пользователям:
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 12:52.
|