Показать сообщение отдельно
Старый 31.03.2009, 07:23   #2
HolyDel
 
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений
(для 2,707 пользователей)
Ответ: Sigel Tutorial 1. Свой Crimsoland.

теперь научим нашего игрока стрелять. Для этого надо описать класс пули. Какие должны быть данные у пули? Как она должна обновляться? Все это нужно описать в структуре класса и его методах. Кроме самой пули еще нужны впсышки от выстрелов. По хорошему надо бы реализацию классов и их описание писать в разных .cpp и .h файлах, но мне влом. Тем более они будут сильно завязаны как друг на друге, так и на игроке (глобальная переменная, не забыли? )
кроме того, нужны будут глобальные переменные для спрайта вспышки выстрела и его текстуры, и текстуры пули.

Пишем:
Billboard *bspark;
Texture *bsparktex;
Texture *btex;

class Bullet
{
	Entity *ent;
	float l;
public:
	Bullet();
	~Bullet();

	void Update();

};

class Flash
{
	Entity *ent;
	float l;
public:
	Flash(Entity *asent);
	~Flash();

	void Update();
};
все пули и все вспышки надо хранить в списках. Списки std::list. Естественно храниться в списках будут не сами объекты а указатели на них.

typedef std::list<Bullet*> TBList;
TBList blist;

typedef std::list<Flash*> TFList;
TFList flist;
чтобы каждый раз не писать длинную муть вроде std::list<Bullet*> можно переопределить тип — командой typedef. У нее первое выражение это старое имя типа, а второе — новое.
Конструктор Bullet:
Bullet::Bullet()
{
	ent = new Entity(bb);
	ent->Blend(BM_ADD);
	ent->Position(player);
	ent->Rotate(player);
	ent->Move(2);
	ent->BindTex(btex);
	ent->Scale(0.5f);
	l = 1000.0f;

	Flash *f = new Flash(ent);

	blist.push_back(this);
}
как видите, создаем квад, ставим его в позицию игрока, сдвигаем на 2 еденицы вперед (Если у Move только один параметр — это значит смещение по Z в object-space), прикрепляем текстуру, настраиваем блендинг на аддиативный и размеры поменьще. Задаем время жизни в миллисекундах.
Кроме того, на месте пули создаем вспышку. И собственно добавляем созданный экземпляр в список. this – это указатель на текущий (создаваемый объект).

Деструктор пули:
Bullet::~Bullet()
{
	delete ent;
	blist.remove(this);
}
ну, тут ничего сложного — просто удаляем ентити и выкидываем из списка удаляемый экземпляр.

Функция обновления пули (она должна иметь именно такой формат):
void Bullet::Update()
{
	ent->Move(0.08f * dt);

	l -= dt;
	if(l<0)
		delete this;
}
двигаем вперед пулю (с учетом dt). Сокращаем время жизни. Не забывайте, что dt это вреся кадра в миллисекундах (пусть и дробное). Если пуля изжила свою секунду — она уничтожается.
Конструктор Flash:
Flash::Flash(Entity *asent)
{
	ent = new Entity(bspark);
	ent->Blend(BM_ADD);
	ent->Position(asent);
	ent->BindTex(bsparktex);
	ent->Animate(0.0f,8.0f,7.0f / 500.0f);
	flist.push_back(this);

	l = 500;
}
тут все тоже самое. Стоит только остановиться на методе — Animate. Он собственно задает границу анимации (начальный и конечный кадр). Третий параметр — скорость анимации.

Деструктор Flash аналогичен деструктору Bullet.

Метод обновления даже проще:
void Flash::Update()
{
	l-=dt;

	if(l<0)
		delete this;
}
далее, загрузка / создание ресурсов:

bspark = new Billboard(1.0f);
bspark->AnimLenght(8);
bspark->SetSmoothAnim(1);

bsparktex = new Texture("media/bflash.jpg");
btex = new Texture("media/bullet.jpg");
создаем биллбоард (он был выбран вместо квада так как его можно анимировать). Задаем ему длинну анимации в кадрах. Так как в текстуре 8 кадров то и тут пишем 8. SetSmoothAnim(1) – включает линейную интерполяцию между кадрами.

Ну и грузим две текстуры. Ничего сложного

до главного цикла объявили переменную float – fire.

if(MouseDown(1))
{
	if(fire<1)
	{
		Bullet *b = new Bullet();
		fire = 100;
	}
}

fire = max_(0,fire-dt);

misc::update_this<TBList>(blist);
misc::update_this<TFList>(flist);

AnimUpdate(dt);
первый фрагмент (там где MouseDown(1)) – это стрельба.
Если ствол остыл (fire<1) то можно стрелять.
Поэтому создаем новую пулю, не волнуйтесь, она не засрет память, даже если мы и теряем ее указатель, так как в списке она осталась, и будет корректо почищена.
Ствол остывает - fire = max_(0,fire-dt);

следующие две строчки очень интересны. Они запускают обновление элементов в списке. Он отличается от std::for_each тем, что в нем элементы во время обновления могут удалить сами себя. А в for_each теряется итератор.

AnimUpdate – обновляет все анимированные объекты. Параметр — это twin.


Исходник:
#define SIGEL_USE_ONLY
  #define SIGEL_DEVIL
  #define SIGEL_SOUND

#include <sigel/ISigel.h>

Surface *bb = 0;
Entity *player = 0;
float dt = 0;
Billboard *bspark;
Texture *bsparktex;
Texture *btex;

class Bullet
{
	Entity *ent;
	float l;
public:
	Bullet();
	~Bullet();

	void Update();

};

class Flash
{
	Entity *ent;
	float l;
public:
	Flash(Entity *asent);
	~Flash();

	void Update();
};

typedef std::list<Bullet*> TBList;
TBList blist;

typedef std::list<Flash*> TFList;
TFList flist;

Bullet::Bullet()
{
	ent = new Entity(bb);
	ent->Blend(BM_ADD);
	ent->Position(player);
	ent->Rotate(player);
	ent->MoveY(0,2);
	ent->BindTex(btex);
	ent->Scale(0.5f);
	l = 1000.0f;

	Flash *f = new Flash(ent);

	blist.push_back(this);
}

Bullet::~Bullet()
{
	delete ent;
	blist.remove(this);
}

void Bullet::Update()
{
	ent->Move(0.08f * dt);

	l -= dt;
	if(l<0)
		delete this;
}


Flash::Flash(Entity *asent)
{
	ent = new Entity(bspark);
	ent->Blend(BM_ADD);
	ent->Position(asent);
	ent->BindTex(bsparktex);
	ent->Animate(0.0f,8.0f,7.0f / 500.0f);
	flist.push_back(this);

	l = 500;
}

Flash::~Flash()
{
	delete ent;
	flist.remove(this);
}

void Flash::Update()
{
	l-=dt;

	if(l<0)
		delete this;
}

sGAME
{
	debug::startlog();
	Init();
	AppTitle("_ISh2");

	Image *cur = new Image("media/cur.jpg");

	Camera *eye = new Camera();
	Entity *cam = new Entity(EC_PIVOT);
	eye->BindEntity(cam);
	cam->Rotate(-90.0f,0,0);  //поворачиваем камеру вниз. Игра то с видом сверху.

	bb = new Surface();
	bb->MakeQuad(2.0f);

	player = new Entity(bb);
	player->Blend(BM_ALPHA);

	Texture *playerdiffus[19];

	for(int i=0;i<19;++i)
	{
		char buff[80];
		sprintf_s(buff,80,"media/solider/%d.png",i+1);
		playerdiffus[i] = new Texture(buff);
	}

	Surface *sfloor = new Surface();
	sfloor->MakeQuad(64.0f,16.0f);

	Entity *efloor = new Entity(sfloor);

	Texture *fdiffus = new Texture("media/Fieldstone.png",TF_MIPMAP | TF_ANISOTROPIC);
	efloor->BindTex(fdiffus);

	bspark = new Billboard(1.0f);
	bspark->AnimLenght(8);
	bspark->SetSmoothAnim(1);

	bsparktex = new Texture("media/bflash.jpg");
	btex = new Texture("media/bullet.jpg");

	VWait(0);

	TFont *fnt = new TFont("tahoma.txt");

	player -> Position(32.0f,0.5f,32.0f); //ставим игрока на середину. (чуть выше земли).

	int move = 0;
	float frame = 0;
	player->BindTex(playerdiffus[(int)frame]);

	HidePointer();
	float fire = 0;
	while(!KeyDown(VK_ESCAPE))
	{
		dt = GetFrameTime();
		//3d
		move = 0;
		Vector2D mdir(0,0);

		if(KeyDown('W'))
		{
			move = 1;
			mdir.y -= 1;
		}

		if(KeyDown('S'))
		{
			move = 1;
			mdir.y += 1;
		}

		if(KeyDown('A'))
		{
			move = 1;
			mdir.x -= 1;
		}

		if(KeyDown('D'))
		{
			move = 1;
			mdir.x += 1;
		}


		if(move)
		{
			if(mdir.length()>0.1f)
				mdir.normalize();

			mdir *= (dt*0.01f);

			player->Translate(mdir.x,0,mdir.y);

			frame += dt * 0.03f;
			if(frame>18.0f)
				frame -= 18.0f;

			player->BindTex(playerdiffus[(int)frame]);
		}

		float a = atan2f((float)((ScreenWidth()/2)-MouseX()),(float)((ScreenHeight()/2)-MouseY()));
		player->RotateY(a*57.1f);


		cam->Position(player);
		cam->PositionY(24.0f);

		if(MouseDown(1))
		{
			if(fire<1)
			{
				Bullet *b = new Bullet();

				fire = 100;
			}

		}

		fire = max_(0,fire-dt);

		misc::update_this<TBList>(blist);
		misc::update_this<TFList>(flist);

		AnimUpdate(dt);
		Render();
		//2d


		fnt->Text(GetFPS(),10,10);

		Blend(BM_ADD);
		cur->Draw(MouseX()-16,MouseY()-16);
		Blend(BM_ALPHA);
		Flip();
	}
	ShowPointer();
	DeInit();
	debug::endlog();
};
часть скриншота:
Нажмите на изображение для увеличения
Название: pic7.png
Просмотров: 1148
Размер:	626.5 Кб
ID:	5725
(Offline)
 
Ответить с цитированием
Эти 5 пользователя(ей) сказали Спасибо HolyDel за это полезное сообщение:
-=SCiP=- (31.03.2009), falcon (31.03.2009), h1dd3n (31.03.2009), H@NON (31.03.2009), impersonalis (31.03.2009)