CC++Qt « Движение объекта (графика)
Использую: Visual Studio 2008, TXLib(графическая библиотека).
Проблема: Нужно заставить двигаться объект так, чтобы при движении он изменялся в соответствии с заданной функцией. Конкретно в этой задаче объект должен искажаться косинуидально по горизонтали и синусоидально по вертикали. Проблема заключается в том, что надо реализовать функцию, которая могла бы искажать любой заданный объект.
Вопрос: Какие можете предложить идеи по алгоритму?
Код:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .cpp.geshi_code {font-family:monospace;} .cpp.geshi_code .imp {font-weight: bold; color: red;} .cpp.geshi_code .kw1 {color: #0000ff;} .cpp.geshi_code .kw2 {color: #0000ff;} .cpp.geshi_code .kw3 {color: #0000dd;} .cpp.geshi_code .kw4 {color: #0000ff;} .cpp.geshi_code .co1 {color: #666666;} .cpp.geshi_code .co2 {color: #339900;} .cpp.geshi_code .coMULTI {color: #ff0000; font-style: italic;} .cpp.geshi_code .es0 {color: #000099; font-weight: bold;} .cpp.geshi_code .es1 {color: #000099; font-weight: bold;} .cpp.geshi_code .es2 {color: #660099; font-weight: bold;} .cpp.geshi_code .es3 {color: #660099; font-weight: bold;} .cpp.geshi_code .es4 {color: #660099; font-weight: bold;} .cpp.geshi_code .es5 {color: #006699; font-weight: bold;} .cpp.geshi_code .br0 {color: #008000;} .cpp.geshi_code .sy0 {color: #008000;} .cpp.geshi_code .sy1 {color: #000080;} .cpp.geshi_code .sy2 {color: #000040;} .cpp.geshi_code .sy3 {color: #000040;} .cpp.geshi_code .sy4 {color: #008080;} .cpp.geshi_code .st0 {color: #FF0000;} .cpp.geshi_code .nu0 {color: #0000dd;} .cpp.geshi_code .nu6 {color: #208080;} .cpp.geshi_code .nu8 {color: #208080;} .cpp.geshi_code .nu12 {color: #208080;} .cpp.geshi_code .nu16 {color:#800080;} .cpp.geshi_code .nu17 {color:#800080;} .cpp.geshi_code .nu18 {color:#800080;} .cpp.geshi_code .nu19 {color:#800080;} .cpp.geshi_code .me1 {color: #007788;} .cpp.geshi_code .me2 {color: #007788;} .cpp.geshi_code span.xtra { display:block; }
#include "TXLib.h"
#include "graphics.h"
#include <iostream>
using namespace std;
void main(){
// Класс графика.
class Graphic{
public:
float red, green, blue;
// Конструктор по умолчанию.
Graphic() : red(1.0), green(0.5), blue(0.25){}
// Конструктор с тремя аргументами.
Graphic(float r, float g, float b) : red(r), green(g), blue(b){}
~Graphic(){}
};
// Класс крест.
class Cross : public Graphic{
public:
// Координаты горизонтальной линии.
int GorX_1, VerX_1, GorX_2, VerX_2;
// Координаты вертикальной линии.
int GorY_1, VerY_1, GorY_2, VerY_2;
// Конструктор по умолчанию.
Cross() : GorX_1(0), VerX_1(100), GorX_2(50), VerX_2(100), GorY_1(25), VerY_1(10), GorY_2(25), VerY_2(130){}
// Конструктор с четыремя параметрами.
Cross(int gls, int gle, int vls, int vle, int glsy, int gley, int vlsy, int vley) : GorX_1(gls), VerX_1(gle), GorX_2(vls), VerX_2(vle), GorY_1(glsy), VerY_1(gley), GorY_2(vlsy), VerY_2(vley){}
~Cross(){}
};
txCreateWindow(800, 600, 1);
// Создать объект.
Cross KREST;
for(int i=0; i<750; i++){
// Задать цвет.
txColor(KREST.red=1.0, KREST.green=0.5, KREST.blue=0.25);
// Начертить вертикальную линию.
txLine(KREST.GorY_1+i, KREST.VerY_1, KREST.GorY_2+i, KREST.VerY_2);
// Задать цвет (стирающий).
txColor(KREST.red=0.0, KREST.green=0.0, KREST.blue=0.0);
// Начертить вертикальную линию (стирающую).
txLine(KREST.GorY_1+i-1, KREST.VerY_1, KREST.GorY_2+i-1, KREST.VerY_2);
// Задать цвет.
txColor(KREST.red=1.0, KREST.green=0.5, KREST.blue=0.25);
// Начертить горизонтальную линию.
txLine(KREST.GorX_1=i, KREST.VerX_1, KREST.GorX_2+i, KREST.VerX_2);
// Задать цвет (стирающий).
txColor(KREST.red=0.0, KREST.green=0.0, KREST.blue=0.0);
// Начертить горизонтальную линию (стирающую).
txLine(KREST.GorX_1=0, KREST.VerX_1, KREST.GorX_2-KREST.GorX_2+i, KREST.VerX_2);
Sleep(3);
}
}
Проблема: Нужно заставить двигаться объект так, чтобы при движении он изменялся в соответствии с заданной функцией. Конкретно в этой задаче объект должен искажаться косинуидально по горизонтали и синусоидально по вертикали. Проблема заключается в том, что надо реализовать функцию, которая могла бы искажать любой заданный объект.
Вопрос: Какие можете предложить идеи по алгоритму?
Код:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .cpp.geshi_code {font-family:monospace;} .cpp.geshi_code .imp {font-weight: bold; color: red;} .cpp.geshi_code .kw1 {color: #0000ff;} .cpp.geshi_code .kw2 {color: #0000ff;} .cpp.geshi_code .kw3 {color: #0000dd;} .cpp.geshi_code .kw4 {color: #0000ff;} .cpp.geshi_code .co1 {color: #666666;} .cpp.geshi_code .co2 {color: #339900;} .cpp.geshi_code .coMULTI {color: #ff0000; font-style: italic;} .cpp.geshi_code .es0 {color: #000099; font-weight: bold;} .cpp.geshi_code .es1 {color: #000099; font-weight: bold;} .cpp.geshi_code .es2 {color: #660099; font-weight: bold;} .cpp.geshi_code .es3 {color: #660099; font-weight: bold;} .cpp.geshi_code .es4 {color: #660099; font-weight: bold;} .cpp.geshi_code .es5 {color: #006699; font-weight: bold;} .cpp.geshi_code .br0 {color: #008000;} .cpp.geshi_code .sy0 {color: #008000;} .cpp.geshi_code .sy1 {color: #000080;} .cpp.geshi_code .sy2 {color: #000040;} .cpp.geshi_code .sy3 {color: #000040;} .cpp.geshi_code .sy4 {color: #008080;} .cpp.geshi_code .st0 {color: #FF0000;} .cpp.geshi_code .nu0 {color: #0000dd;} .cpp.geshi_code .nu6 {color: #208080;} .cpp.geshi_code .nu8 {color: #208080;} .cpp.geshi_code .nu12 {color: #208080;} .cpp.geshi_code .nu16 {color:#800080;} .cpp.geshi_code .nu17 {color:#800080;} .cpp.geshi_code .nu18 {color:#800080;} .cpp.geshi_code .nu19 {color:#800080;} .cpp.geshi_code .me1 {color: #007788;} .cpp.geshi_code .me2 {color: #007788;} .cpp.geshi_code span.xtra { display:block; }
#include "TXLib.h"
#include "graphics.h"
#include <iostream>
using namespace std;
void main(){
// Класс графика.
class Graphic{
public:
float red, green, blue;
// Конструктор по умолчанию.
Graphic() : red(1.0), green(0.5), blue(0.25){}
// Конструктор с тремя аргументами.
Graphic(float r, float g, float b) : red(r), green(g), blue(b){}
~Graphic(){}
};
// Класс крест.
class Cross : public Graphic{
public:
// Координаты горизонтальной линии.
int GorX_1, VerX_1, GorX_2, VerX_2;
// Координаты вертикальной линии.
int GorY_1, VerY_1, GorY_2, VerY_2;
// Конструктор по умолчанию.
Cross() : GorX_1(0), VerX_1(100), GorX_2(50), VerX_2(100), GorY_1(25), VerY_1(10), GorY_2(25), VerY_2(130){}
// Конструктор с четыремя параметрами.
Cross(int gls, int gle, int vls, int vle, int glsy, int gley, int vlsy, int vley) : GorX_1(gls), VerX_1(gle), GorX_2(vls), VerX_2(vle), GorY_1(glsy), VerY_1(gley), GorY_2(vlsy), VerY_2(vley){}
~Cross(){}
};
txCreateWindow(800, 600, 1);
// Создать объект.
Cross KREST;
for(int i=0; i<750; i++){
// Задать цвет.
txColor(KREST.red=1.0, KREST.green=0.5, KREST.blue=0.25);
// Начертить вертикальную линию.
txLine(KREST.GorY_1+i, KREST.VerY_1, KREST.GorY_2+i, KREST.VerY_2);
// Задать цвет (стирающий).
txColor(KREST.red=0.0, KREST.green=0.0, KREST.blue=0.0);
// Начертить вертикальную линию (стирающую).
txLine(KREST.GorY_1+i-1, KREST.VerY_1, KREST.GorY_2+i-1, KREST.VerY_2);
// Задать цвет.
txColor(KREST.red=1.0, KREST.green=0.5, KREST.blue=0.25);
// Начертить горизонтальную линию.
txLine(KREST.GorX_1=i, KREST.VerX_1, KREST.GorX_2+i, KREST.VerX_2);
// Задать цвет (стирающий).
txColor(KREST.red=0.0, KREST.green=0.0, KREST.blue=0.0);
// Начертить горизонтальную линию (стирающую).
txLine(KREST.GorX_1=0, KREST.VerX_1, KREST.GorX_2-KREST.GorX_2+i, KREST.VerX_2);
Sleep(3);
}
}
1 ответов
Вот более локализованно к данной задаче:
class AnimationObject // Интерфейс анимируемого объекта
{
public:
virtual float GetPositionX() = 0;
virtual float GetPositionY() = 0;
virtual bool MoveObjectAndChildren( float dX, float dY ) = 0;
};
class AnimationPoint
{
public:
int AnimationPoint::Work()
{
int dX = std::abs( _iX - _pAnimationObject->GetPositionX() );
int dY = std::abs( _iY - _pAnimationObject->GetPositionY() );
int speed = (int)(_fSpeed0 + _fCountTick*_fAcceleration);
if( dX > speed )
dX = speed;
if( dY > speed )
dY = speed;
if( _iX < _pItemShowing->_x )
dX = -dX;
if( _iY < _pItemShowing->_y )
dY = -dY;
_fCountTick += 1.0f;
_pAnimationObject->MoveObjectAndChildren( dX, dY );
if( _iX == _pAnimationObject->GetPositionX() && _iY == _pAnimationObject->GetPositionY() )
{
return 0;
}
return 1;
}
void Init( AnimationObject* pAnimationObject ); // Настроиться на новый объект
int _iX;
int _iY;
float _fSpeed0; // Начальная скорость движения
float _fAcceleration; // Ускорение движения
float _fCountTick; // Количество отработанных тиков, сбрасывается в ноль при инициализации
AnimationObject* _pAnimationObject; // То что анимируем
};
AnimationPoint конкретная функция движения, в твоем случае нужно реализовать аналогично объект AnimationSin
AnimationObject интерфейс который должны реализовывать все объекты которые нужно анимировать.
Далее в основном цикле программы вызываешь метод Work анимирующего объекта ( в данном примере AnimationPoint )
Здесь интересно описано движение шара http://orenstudent.ru/CometD.htm + можно программку с исходным кодом скачать.Хз.Я заказывал у автора немного переделанную работу,все очень хорошо выполнил
Использую что то подобное для анимации диалоговых элементов, привожу только интерфейс без реализации, если заинтересует приложу основные части:
1. Объект высокого уровня, с которым работает непосредственный клиент,
через него запускается определенный фрейм ( набор точек ).
///////////////////////////////////////////////////////////////////////////////
// DialogAnimation
//
// Декаратор диалоговых элементов,
// анимирует диалоги и/или отдельные элементы
// на входе принимает указатель на DialogItem,
// а также данные( фреймы ), являющиеся точками
// через которые и проходит анимация.
// Использование:
// Загрузить данные( метод Load)
// Инициализировать наблюдаемый объект( метод Init )
// Запустить фрейм( метод StartAnimation )
// Переодически обробатывать анимацтю( метод Work )
//
///////////////////////////////////////////////////////////////////////////////
class DialogAnimation
{
public:
// Конструктор/Деструктор
DialogAnimation();
~DialogAnimation();
void Init( DialogItem* pItemAnimation ); // Инициализировать данные и декарируемый объект
void Load( TiXmlElement* pXmlAnimationData ); // Загрузить анимацию из Xml
void Work(); // Обработать логику
void StartAnimation( String sNameAnimation ); // Запустить фрейм sNameAnimation
String& GetCurrentFrameName(); // Получить имя текущего фрейма
void RegisterPointFunction( String sNameFunction,
PPoint_Function pPointFunction ); // Зарегистрировать функцию обработчик
PPoint_Function GetPointFunction( String sNameFunction ); // Получить указатель на функцию оброботчик
private:
struct PointFunctionByName
{
String _sNameFunction;
PPoint_Function _pPointFunction;
};
typedef std::vector<PointFunctionByName> PointFunctionList;
FrameList _listFrames; // Список фреймов
PointFunctionList _listPointFunctions; // Список функций обработчиков
DialogItem* _pItemAnimation; // Декарируемый элемент
AnimationFrame* _pCurrentFrame; // Текущий работающий фрейм
int _iDeltaXPosInit; // Начальный сдвиг наблюдаемого объекта по X
int _iDeltaYPosInit; // Начальный сдвиг наблюдаемого объекта по Y
};
2. Объект перебирающей конкретные точки анимации
class AnimationFrame
{
public:
// Конструктор/Деструктор
AnimationFrame();
~AnimationFrame();
void Load( TiXmlElement* pXmlFrameData,
DialogAnimation* pAnimation ); // Загрузить анимацию из Xml
int Work(); // Обработать логику
void StartFrame( DialogItem* pItemShowing ); // Запустить фрейм
DialogAnimation* GetAnimation(); // Получить анимацию в которой находимся
String& GetName(); // Получить имя фрейма
private:
String _sNameFrame; // Имя фрейма
DialogAnimation* _pAnimation; // Анимация в которой мы находимся
PointList _listPoints; // Список точек фрейма
PointList::iterator _itCurrentPoint; // Текущая точка фрейма
DialogItem* _pItemShowing; // Декарируемый Элемент
};
3. Непосредственно передвигает элемент, стремясь к какой то точке, по окончанию вызывает функцию обработчик если задана.
// Обработчик точек анимации, вызывается при достижении точки
typedef void (Point_Function)( String& sParam1, String& sParam2 );
typedef Point_Function* PPoint_Function;
class AnimationPoint
{
public:
// Конструктор/Деструктор
AnimationPoint();
~AnimationPoint();
enum eAnimationWork
{
AW_NORMAL = 0,
AW_END
};
void Load( TiXmlElement* pXmlPointData,
AnimationFrame* pFrame ); // Загрузить анимацию из Xml
int Work(); // Обработать логику
void Init( DialogItem* pItemShowing ); // Настроиться на новый объект
private:
// Разброс координат
int _iMinX;
int _iMinY;
int _iMaxX;
int _iMaxY;
int _iX; // Утонавливается в Init Rand( _iMinX, _iMaxX )
int _iY; // Утонавливается в Init Rand( _iMinY, _iMaxY )
float _fSpeed0; // Начальная скорость движения
float _fAcceleration; // Ускорение движения
float _fCountTick; // Количество отработанных тиков, сбрасывается в ноль при инициализации
DialogItem* _pItemShowing; // То что анимируем
PPoint_Function PointFunction; // Функция обработчик
String _sParam1; // Параметр1 Точки
String _sParam2; // Параметр2 Точки
AnimationFrame* _pFrame; // Фрейм в котором находится точка
};
Как это все работает:
DialogAnimation это контейнер AnimationFrame, который в свою очередь контейнер AnimationPoint.
вот непосредственно анимация:
/////////////////////////////////////////////////////////////////////////////////////////////
// Обработать логику
/////////////////////////////////////////////////////////////////////////////////////////////
int AnimationPoint::Work()
{
int dX = abs( _iX - _pItemShowing->_x );
int dY = abs( _iY - _pItemShowing->_y );
int speed = (int)(_fSpeed0 + _fCountTick*_fAcceleration);
if( dX > speed )
dX = speed;
if( dY > speed )
dY = speed;
if( _iX < _pItemShowing->_x )
dX = -dX;
if( _iY < _pItemShowing->_y )
dY = -dY;
int iDeltaX[2] = { dX, 0 };
int iDeltaY[2] = { dY, 0 };
_fCountTick += 1.0f;
_pItemShowing->MoveItemAndChildren( iDeltaX, iDeltaY, false );
if( _iX == _pItemShowing->_x && _iY == _pItemShowing->_y )
{
if( PointFunction )
PointFunction( _sParam1, _sParam2 );
return AW_END;
}
return AW_NORMAL;
}
то есть анимируемый объект должен поддерживать метод MoveItemAndChildren и предоставлять доступ к текущим координатам( _x, _y )